Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add version and update notes #2722

Merged
merged 11 commits into from
Nov 4, 2023
13 changes: 9 additions & 4 deletions .woodpecker/docs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
when:
- event: tag
- event: pull_request
- event: push
path: &when_path
Expand Down Expand Up @@ -59,22 +60,26 @@ steps:
secrets:
- BOT_PRIVATE_KEY
commands:
- apk add openssh-client git rsync
- apk add openssh-client git rsync jq
- mkdir -p $HOME/.ssh
- ssh-keyscan -t rsa github.com >> $HOME/.ssh/known_hosts
- echo "$BOT_PRIVATE_KEY" > $HOME/.ssh/id_rsa
- chmod 0600 $HOME/.ssh/id_rsa
- git config --global user.email "woodpecker-bot@obermui.de"
- git config --global user.name "woodpecker-bot"
- git clone --depth 1 --single-branch git@github.com:woodpecker-ci/woodpecker-ci.github.io.git /repo
# update latest and next version
- if [ "$CI_PIPELINE_EVENT" == "tag" ] ; then jq '.latest = ${CI_COMMIT_TAG}' repo/version.json > repo/version.json.tmp && mv repo/version.json.tmp repo/version.json ; fi
- if [ "$CI_PIPELINE_EVENT" == "push" ] ; then jq "next-" '.next = ${CI_COMMIT_SHA:0:10}' repo/version.json > repo/version.json.tmp && mv repo/version.json.tmp repo/version.json ; fi
# copy all docs files and delete all old ones, but leave CNAME and index.yaml untouched
- rsync -r --exclude .git --exclude CNAME --exclude index.yaml --exclude README.md --delete docs/build/ /repo
- rsync -r --exclude .git --exclude CNAME --exclude index.yaml --exclude README.md --exclude version.json --delete docs/build/ /repo
- cd /repo
- git add .
# exit successfully if nothing changed
- test -n "$(git status --porcelain)" || exit 0
- git commit -m "Deploy website - based on ${CI_COMMIT_SHA}"
- git push
when:
event: [push, cron]
path: *when_path
- event: [push, cron]
path: *when_path
- event: tag
2 changes: 2 additions & 0 deletions web/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare module 'vue' {
ActionsTab: typeof import('./src/components/repo/settings/ActionsTab.vue')['default']
ActivePipelines: typeof import('./src/components/layout/header/ActivePipelines.vue')['default']
AdminAgentsTab: typeof import('./src/components/admin/settings/AdminAgentsTab.vue')['default']
AdminInfoTab: typeof import('./src/components/admin/settings/AdminInfoTab.vue')['default']
AdminOrgsTab: typeof import('./src/components/admin/settings/AdminOrgsTab.vue')['default']
AdminQueueStats: typeof import('./src/components/admin/settings/queue/AdminQueueStats.vue')['default']
AdminQueueTab: typeof import('./src/components/admin/settings/AdminQueueTab.vue')['default']
Expand All @@ -22,6 +23,7 @@ declare module 'vue' {
Checkbox: typeof import('./src/components/form/Checkbox.vue')['default']
CheckboxesField: typeof import('./src/components/form/CheckboxesField.vue')['default']
Container: typeof import('./src/components/layout/Container.vue')['default']
copy: typeof import('./src/components/admin/settings/AdminAgentsTab copy.vue')['default']
CronTab: typeof import('./src/components/repo/settings/CronTab.vue')['default']
DeployPipelinePopup: typeof import('./src/components/layout/popups/DeployPipelinePopup.vue')['default']
DocsLink: typeof import('./src/components/atomic/DocsLink.vue')['default']
Expand Down
5 changes: 4 additions & 1 deletion web/src/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -501,5 +501,8 @@
"internal_error": "Some internal error occurred",
"access_denied": "You are not allowed to login"
},
"default": "default"
"default": "default",
"info": "Info",
"running_version": "You are running woodpecker {0}",
"update_woodpecker": "Please update your Woodpecker instance to {0}"
}
29 changes: 29 additions & 0 deletions web/src/components/admin/settings/AdminInfoTab.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<template>
<Settings :title="$t('info')">
<div class="flex flex-col items-center gap-4">
<WoodpeckerLogo class="w-48 h-48" />

<i18n-t keypath="running_version" tag="p" class="text-xl">
<span class="font-bold">{{ version?.current }}</span>
</i18n-t>

<i18n-t v-if="version?.needsUpdate" keypath="update_woodpecker" tag="span" class="text-int-wp-state-error-100">
<a
:href="`https://github.com/woodpecker-ci/woodpecker/releases/tag/${version.latest}`"
target="_blank"
rel="noopener noreferrer"
class="underline"
>{{ version.latest }}</a
anbraten marked this conversation as resolved.
Show resolved Hide resolved
>
</i18n-t>
</div>
</Settings>
</template>

<script lang="ts" setup>
import WoodpeckerLogo from '~/assets/logo.svg?component';
import Settings from '~/components/layout/Settings.vue';
import { useVersion } from '~/compositions/useVersion';

const version = useVersion();
</script>
40 changes: 20 additions & 20 deletions web/src/components/layout/header/Navbar.vue
Original file line number Diff line number Diff line change
@@ -1,47 +1,46 @@
<template>
<!-- Navbar -->
<nav
class="flex bg-wp-primary-200 dark:bg-wp-primary-300 text-neutral-content p-4 border-b border-wp-background-100 font-bold text-wp-primary-text-100"
>
<!-- Left Links Box -->
<div class="flex items-center space-x-2">
<!-- Logo -->
<router-link :to="{ name: 'home' }" class="flex flex-col -my-2 px-2">
<WoodpeckerLogo class="w-8 h-8" />
<span class="text-xs">{{ version }}</span>
<span
class="text-xs"
:class="{ 'text-int-wp-state-error-100': version?.needsUpdate }"
anbraten marked this conversation as resolved.
Show resolved Hide resolved
:title="version?.current"
>{{ version?.currentShort }}</span
>
</router-link>
<!-- Repo Link -->
<router-link v-if="user" :to="{ name: 'repos' }" class="navbar-link navbar-clickable">
<span class="flex md:hidden">{{ $t('repos') }}</span>
<span class="hidden md:flex">{{ $t('repositories') }}</span>
</router-link>
<!-- Docs Link -->
<a href="https://woodpecker-ci.org/" target="_blank" class="navbar-link navbar-clickable hidden md:flex">{{
$t('docs')
}}</a>
<!-- API Link -->
<a v-if="enableSwagger" :href="apiUrl" target="_blank" class="navbar-link navbar-clickable hidden md:flex">{{
$t('api')
}}</a>
</div>
<!-- Right Icons Box -->
<div class="flex ml-auto -m-1.5 items-center space-x-2">
<!-- Admin Settings -->
<IconButton
v-if="user?.admin"
class="navbar-icon"
:title="$t('admin.settings.settings')"
:to="{ name: 'admin-settings' }"
icon="settings"
/>
<div v-if="user?.admin" class="relative">
<IconButton
class="navbar-icon"
:title="$t('admin.settings.settings')"
:to="{ name: 'admin-settings' }"
icon="settings"
/>
<div
v-if="version?.needsUpdate"
class="absolute top-2 right-2 bg-int-wp-state-error-100 rounded-full w-3 h-3"
/>
</div>

<!-- Active Pipelines Indicator -->
<ActivePipelines v-if="user" class="navbar-icon" />
<!-- User Avatar -->
<IconButton v-if="user" :to="{ name: 'user' }" :title="$t('user.settings.settings')" class="navbar-icon !p-1.5">
<img v-if="user && user.avatar_url" class="rounded-md" :src="`${user.avatar_url}`" />
</IconButton>
<!-- Login Button -->
<Button v-else :text="$t('login')" @click="doLogin" />
</div>
</nav>
Expand All @@ -55,9 +54,11 @@ import Button from '~/components/atomic/Button.vue';
import IconButton from '~/components/atomic/IconButton.vue';
import useAuthentication from '~/compositions/useAuthentication';
import useConfig from '~/compositions/useConfig';
import { useVersion } from '~/compositions/useVersion';

import ActivePipelines from './ActivePipelines.vue';

const version = useVersion();
const config = useConfig();
const route = useRoute();
const authentication = useAuthentication();
Expand All @@ -68,7 +69,6 @@ function doLogin() {
authentication.authenticate(route.fullPath);
}

const version = config.version?.startsWith('next') ? 'next' : config.version;
const { enableSwagger } = config;
</script>

Expand Down
84 changes: 84 additions & 0 deletions web/src/compositions/useVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { onMounted, ref } from 'vue';

import useAuthentication from './useAuthentication';
import useConfig from './useConfig';

type VersionInfo = {
latest: string;
next: string;
};

const version = ref<{
latest: string | undefined;
current: string;
currentShort: string;
needsUpdate: boolean;
}>();

async function fetchVersion(): Promise<VersionInfo | undefined> {
try {
const resp = await fetch('https://woodpecker-ci.org/version.json');
const json = await resp.json();
return json;
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to fetch version info', error);
return undefined;
}
}

const isInitialised = ref(false);

export function useVersion() {
if (isInitialised.value) {
return version;
}
isInitialised.value = true;

const config = useConfig();
const current = config.version as string;
const usesNext = config.version?.startsWith('next');

const { user } = useAuthentication();
if (!user?.admin) {
version.value = {
latest: undefined,
current,
currentShort: usesNext ? 'next' : current,
needsUpdate: false,
};
return version;
}

if (current === 'dev') {
version.value = {
latest: undefined,
current,
currentShort: current,
needsUpdate: false,
};
return version;
}

onMounted(async () => {
const versionInfo = await fetchVersion();

let needsUpdate = false;
if (versionInfo) {
if (usesNext) {
needsUpdate = versionInfo.next !== current;
} else {
needsUpdate = versionInfo.latest !== current;
}
}

version.value = {
latest: usesNext ? versionInfo?.next : versionInfo?.latest,
current,
currentShort: usesNext ? 'next' : current,
needsUpdate,
};
});

return version;
}
4 changes: 4 additions & 0 deletions web/src/views/admin/AdminSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
<template #title>
{{ $t('repo.settings.settings') }}
</template>
<Tab id="info" :title="$t('info')">
<AdminInfoTab />
</Tab>
<Tab id="secrets" :title="$t('admin.settings.secrets.secrets')">
<AdminSecretsTab />
</Tab>
Expand Down Expand Up @@ -30,6 +33,7 @@ import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';

import AdminAgentsTab from '~/components/admin/settings/AdminAgentsTab.vue';
import AdminInfoTab from '~/components/admin/settings/AdminInfoTab.vue';
import AdminOrgsTab from '~/components/admin/settings/AdminOrgsTab.vue';
import AdminQueueTab from '~/components/admin/settings/AdminQueueTab.vue';
import AdminReposTab from '~/components/admin/settings/AdminReposTab.vue';
Expand Down