feat: add update checker on version info

This commit is contained in:
Ruben Fiszel
2023-06-22 18:11:58 +02:00
parent a1b5c142bd
commit f9341af2fe
9 changed files with 130 additions and 34 deletions
+14
View File
@@ -41,6 +41,20 @@ paths:
schema:
type: string
/uptodate:
get:
summary: is backend up to date
operationId: backendUptodate
tags:
- settings
responses:
"200":
description: is backend up to date
content:
text/plain:
schema:
type: string
/ee_license:
get:
summary: get license id
+28
View File
@@ -30,6 +30,8 @@ use tower_http::{
};
use windmill_common::utils::rd_string;
use windmill_common::error::AppError;
mod apps;
mod audit;
mod capture;
@@ -189,6 +191,7 @@ pub async fn run_server(
)
.nest("/oauth", oauth2::global_service())
.route("/version", get(git_v))
.route("/uptodate", get(is_up_to_date))
.route("/ee_license", get(ee_license))
.route("/openapi.yaml", get(openapi)),
)
@@ -211,6 +214,31 @@ pub async fn run_server(
Ok(())
}
async fn is_up_to_date() -> Result<String, AppError> {
let error_reading_version = || anyhow::anyhow!("Error reading latest released version");
let version = HTTP_CLIENT
.get("https://api.github.com/repos/windmill-labs/windmill/releases/latest")
.send()
.await?
.json::<serde_json::Value>()
.await?
.get("tag_name")
.ok_or_else(error_reading_version)?
.as_str()
.ok_or_else(error_reading_version)?
.to_string();
let release = GIT_VERSION
.split('-')
.next()
.ok_or_else(error_reading_version)?
.to_string();
if version == release {
Ok("yes".to_string())
} else {
Ok(format!("Update: {GIT_VERSION} -> {version}"))
}
}
#[cfg(feature = "enterprise")]
async fn git_v() -> String {
format!("EE {GIT_VERSION}")
+26
View File
@@ -6,6 +6,7 @@
* LICENSE-AGPL for a copy of the license.
*/
use axum::response::Response;
#[cfg(feature = "axum")]
use axum::{
body::{self, BoxBody},
@@ -107,3 +108,28 @@ impl<T> OrElseNotFound<T> for Option<T> {
self.ok_or_else(|| Error::NotFound(s.to_string()))
}
}
// Make our own error that wraps `anyhow::Error`.
pub struct AppError(anyhow::Error);
// Tell axum how to convert `AppError` into a response.
impl IntoResponse for AppError {
fn into_response(self) -> Response {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Something went wrong: {}", self.0),
)
.into_response()
}
}
// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into
// `Result<_, AppError>`. That way you don't need to do that manually.
impl<E> From<E> for AppError
where
E: Into<anyhow::Error>,
{
fn from(err: E) -> Self {
Self(err.into())
}
}
@@ -1,16 +1,11 @@
<script lang="ts">
import { SettingsService } from '$lib/gen'
import { onMount } from 'svelte'
import WindmillIcon from './icons/WindmillIcon.svelte'
import Uptodate from './Uptodate.svelte'
import Version from './Version.svelte'
export let subtitle: string | undefined = undefined
export let title = 'Windmill'
export let disableLogo = false
let version = ''
onMount(async () => {
version = await SettingsService.backendVersion()
})
</script>
<div class="center-center min-h-screen p-4 relative bg-gray-50">
@@ -42,7 +37,9 @@
</div>
</div>
<div class="absolute top-0 right-0 text-2xs text-gray-800 italic px-3 py-1">
<span class="font-mono">{version}</span>
<div class="absolute top-0 right-0 text-2xs text-gray-600 italic px-3 py-1">
<span class="font-mono flex flex-col">
<div>Windmill <Version /></div><div><Uptodate /></div>
</span>
</div>
</div>
@@ -1,5 +1,5 @@
<script lang="ts">
import { UserService, SettingsService, GlobalUserInfo } from '$lib/gen'
import { UserService, GlobalUserInfo } from '$lib/gen'
import TableCustom from '$lib/components/TableCustom.svelte'
import PageHeader from '$lib/components/PageHeader.svelte'
import InviteGlobalUser from '$lib/components/InviteGlobalUser.svelte'
@@ -8,12 +8,13 @@
import SearchItems from './SearchItems.svelte'
import { page } from '$app/stores'
import { goto } from '$app/navigation'
import Version from './Version.svelte'
import Uptodate from './Uptodate.svelte'
let drawer: Drawer
let filter = ''
export function openDrawer() {
loadVersion()
listUsers()
drawer?.openDrawer?.()
}
@@ -30,14 +31,9 @@
goto(hashRemoved)
}
let version: string | undefined
let users: GlobalUserInfo[] = []
let filteredUsers: GlobalUserInfo[] = []
async function loadVersion(): Promise<void> {
version = await SettingsService.backendVersion()
}
async function listUsers(): Promise<void> {
users = await UserService.listUsersAsSuperAdmin({ perPage: 100000 })
}
@@ -54,8 +50,8 @@
<DrawerContent overflow_y={false} title="Superadmin Settings" on:close={closeDrawer}>
<div class="flex flex-col h-full">
<div>
<div class="text-xs pt-1 text-gray-500">
Windmill {version}
<div class="text-xs pt-1 text-gray-500 flex flex-col">
<div>Windmill <Version /></div><div><Uptodate /></div>
</div>
<PageHeader title="All global users" primary={false} />
@@ -0,0 +1,30 @@
<script lang="ts">
import { SettingsService } from '$lib/gen'
import Tooltip from './Tooltip.svelte'
let uptodate: string | undefined = undefined
loadVersion()
async function loadVersion() {
try {
const res = await SettingsService.backendUptodate()
console.log(res)
if (res != 'yes') {
uptodate = res
}
} catch (e) {
console.warn('Could not fetch latest version', e)
}
}
</script>
{#if uptodate}
<span class="text-blue-400"
>{uptodate} &nbsp;<Tooltip>
How to update?<br />
- docker: `docker compose up`<br />-
<a href="https://github.com/windmill-labs/windmill-helm-charts#install">helm</a>
</Tooltip></span
>
{/if}
@@ -1,7 +1,7 @@
<script lang="ts">
import { usersWorkspaceStore } from '$lib/stores'
import type { TruncatedToken, NewToken } from '$lib/gen'
import { UserService, SettingsService } from '$lib/gen'
import { UserService } from '$lib/gen'
import { displayDate, copyToClipboard } from '$lib/utils'
import { faClipboard, faPlus } from '@fortawesome/free-solid-svg-icons'
import TableCustom from '$lib/components/TableCustom.svelte'
@@ -12,7 +12,6 @@
let newPassword: string | undefined
let passwordError: string | undefined
let version: string | undefined
let tokens: TruncatedToken[]
let newToken: string | undefined
let newTokenLabel: string | undefined
@@ -26,11 +25,11 @@
import { goto } from '$app/navigation'
import { sendUserToast } from '$lib/toast'
import Tooltip from './Tooltip.svelte'
import Version from './Version.svelte'
let drawer: Drawer
export function openDrawer() {
loadVersion()
loadLoginType()
listTokens()
drawer?.openDrawer()
@@ -60,9 +59,6 @@
}
}
async function loadVersion(): Promise<void> {
version = await SettingsService.backendVersion()
}
async function loadLoginType(): Promise<void> {
login_type = (await UserService.globalWhoami()).login_type
}
@@ -96,8 +92,8 @@
<DrawerContent title="User Settings" on:close={closeDrawer}>
<div class="flex flex-col h-full">
<div>
<div class="text-xs pt-1 pb-2 text-gray-500">
Windmill {version}
<div class="text-xs pt-1 pb-2 text-gray-500 flex-col flex">
Windmill <Version />
</div>
{#if scopes == undefined}
@@ -0,0 +1,13 @@
<script lang="ts">
import { SettingsService } from '$lib/gen'
let version = ''
loadVersion()
async function loadVersion() {
version = await SettingsService.backendVersion()
}
</script>
{version}
@@ -3,7 +3,7 @@
import { page } from '$app/stores'
import { faGithub, faGitlab, faGoogle, faMicrosoft } from '@fortawesome/free-brands-svg-icons'
import { onMount } from 'svelte'
import { OauthService, SettingsService, UserService, WorkspaceService } from '$lib/gen'
import { OauthService, UserService, WorkspaceService } from '$lib/gen'
import { clearStores, usersWorkspaceStore, workspaceStore, userStore } from '$lib/stores'
import { classNames, parseQueryParams } from '$lib/utils'
import { getUserExt } from '$lib/user'
@@ -12,6 +12,8 @@
import { sendUserToast } from '$lib/toast'
import { isCloudHosted } from '$lib/cloud'
import { refreshSuperadmin } from '$lib/refreshUser'
import Version from '$lib/components/Version.svelte'
import Uptodate from '$lib/components/Uptodate.svelte'
let email = $page.url.searchParams.get('email') ?? ''
let password = $page.url.searchParams.get('password') ?? ''
@@ -151,17 +153,11 @@
$: if (error) {
sendUserToast(error, true)
}
let version = ''
onMount(async () => {
version = await SettingsService.backendVersion()
})
</script>
<div class="flex flex-col justify-center py-12 sm:px-6 lg:px-8 relative bg-gray-50 h-screen">
<div class="absolute top-0 right-0 text-2xs text-gray-800 italic px-3 py-1">
<span class="font-mono">{version}</span>
<div class="font-mono flex-col flex"><Version /><div><Uptodate /></div></div>
</div>
<div class="sm:mx-auto sm:w-full sm:max-w-md">
<div class="mx-auto flex justify-center">