Add api for forges (#3733)

This commit is contained in:
Anbraten
2024-06-20 13:08:54 +02:00
committed by GitHub
parent eadead6c07
commit fbb96ff8f5
15 changed files with 611 additions and 98 deletions

View File

@@ -33,7 +33,7 @@
<i-simple-icons-gitea v-else-if="name === 'gitea'" class="h-8 w-8" />
<i-simple-icons-forgejo v-else-if="name === 'forgejo'" class="h-8 w-8" />
<i-ph-gitlab-logo-simple-fill v-else-if="name === 'gitlab'" class="h-8 w-8" />
<i-mdi-bitbucket v-else-if="name === 'bitbucket' || name === 'bitbucket_dc'" class="h-8 w-8" />
<i-mdi-bitbucket v-else-if="name === 'bitbucket' || name === 'bitbucket-dc'" class="h-8 w-8" />
<i-vaadin-question-circle-o v-else-if="name === 'question'" class="h-6 w-6" />
<i-ic-twotone-add v-else-if="name === 'plus'" class="h-6 w-6" />
<i-mdi-format-list-bulleted v-else-if="name === 'list'" class="h-6 w-6" />
@@ -86,7 +86,7 @@ export type IconNames =
| 'gitea'
| 'gitlab'
| 'bitbucket'
| 'bitbucket_dc'
| 'bitbucket-dc'
| 'forgejo'
| 'question'
| 'list'

View File

@@ -6,7 +6,6 @@ declare global {
WOODPECKER_VERSION: string | undefined;
WOODPECKER_SKIP_VERSION_CHECK: boolean | undefined;
WOODPECKER_CSRF: string | undefined;
WOODPECKER_FORGE: 'github' | 'gitlab' | 'gitea' | 'forgejo' | 'bitbucket' | 'bitbucket_dc' | undefined;
WOODPECKER_ROOT_PATH: string | undefined;
WOODPECKER_ENABLE_SWAGGER: boolean | undefined;
}
@@ -17,7 +16,6 @@ export default () => ({
version: window.WOODPECKER_VERSION,
skipVersionCheck: window.WOODPECKER_SKIP_VERSION_CHECK === true || false,
csrf: window.WOODPECKER_CSRF ?? null,
forge: window.WOODPECKER_FORGE ?? null,
rootPath: window.WOODPECKER_ROOT_PATH ?? '',
enableSwagger: window.WOODPECKER_ENABLE_SWAGGER === true || false,
});

View File

@@ -0,0 +1,30 @@
import { defineStore } from 'pinia';
import { computed, reactive, type Ref } from 'vue';
import useApiClient from '~/compositions/useApiClient';
import type { Forge } from '~/lib/api/types';
export const useForgeStore = defineStore('forges', () => {
const apiClient = useApiClient();
const forges = reactive<Map<number, Forge>>(new Map());
async function loadForge(forgeId: number): Promise<Forge> {
const forge = await apiClient.getForge(forgeId);
forges.set(forge.id, forge);
return forge;
}
async function getForge(forgeId: number): Promise<Ref<Forge | undefined>> {
if (!forges.has(forgeId)) {
await loadForge(forgeId);
}
return computed(() => forges.get(forgeId));
}
return {
getForge,
loadForge,
};
});

View File

@@ -2,6 +2,7 @@ import ApiClient, { encodeQueryString } from './client';
import type {
Agent,
Cron,
Forge,
Org,
OrgPermissions,
Pipeline,
@@ -284,6 +285,27 @@ export default class WoodpeckerClient extends ApiClient {
return this._delete(`/api/agents/${agent.id}`);
}
getForges(opts?: PaginationOptions): Promise<Forge[] | null> {
const query = encodeQueryString(opts);
return this._get(`/api/forges?${query}`) as Promise<Forge[] | null>;
}
getForge(forgeId: Forge['id']): Promise<Forge> {
return this._get(`/api/forges/${forgeId}`) as Promise<Forge>;
}
createForge(forge: Partial<Forge>): Promise<Forge> {
return this._post('/api/forges', forge) as Promise<Forge>;
}
updateForge(forge: Partial<Forge>): Promise<unknown> {
return this._patch(`/api/forges/${forge.id}`, forge);
}
deleteForge(forge: Forge): Promise<unknown> {
return this._delete(`/api/forges/${forge.id}`);
}
getQueueInfo(): Promise<QueueInfo> {
return this._get('/api/queue/info') as Promise<QueueInfo>;
}

View File

@@ -0,0 +1,12 @@
export type ForgeType = 'github' | 'gitlab' | 'gitea' | 'bitbucket' | 'bitbucket-dc' | 'addon';
export interface Forge {
id: number;
type: ForgeType;
url: string;
client?: string;
client_secret?: string;
skip_verify?: boolean;
oauth_host?: string;
additional_options?: Record<string, unknown>;
}

View File

@@ -1,5 +1,6 @@
export * from './agent';
export * from './cron';
export * from './forge';
export * from './org';
export * from './pipeline';
export * from './pipelineConfig';

View File

@@ -9,6 +9,9 @@ export interface Repo {
// The id of the repository on the source control management system.
forge_remote_id: string;
// The id of the forge that the repository is on.
forge_id: number;
// The source control management being used.
// Currently, this is either 'git' or 'hg' (Mercurial).
scm: string;

View File

@@ -17,7 +17,7 @@
<a v-if="badgeUrl" :href="badgeUrl" target="_blank">
<img :src="badgeUrl" />
</a>
<IconButton :href="repo.forge_url" :title="$t('repo.open_in_forge')" :icon="forge ?? 'repo'" class="forge" />
<IconButton :href="repo.forge_url" :title="$t('repo.open_in_forge')" :icon="forgeIcon" class="forge" />
<IconButton
v-if="repoPermissions.admin"
:to="{ name: 'repo-settings' }"
@@ -49,6 +49,7 @@ import { computed, onMounted, provide, ref, toRef, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import type { IconNames } from '~/components/atomic/Icon.vue';
import IconButton from '~/components/atomic/IconButton.vue';
import ManualPipelinePopup from '~/components/layout/popups/ManualPipelinePopup.vue';
import Scaffold from '~/components/layout/scaffold/Scaffold.vue';
@@ -56,8 +57,9 @@ import Tab from '~/components/layout/scaffold/Tab.vue';
import useApiClient from '~/compositions/useApiClient';
import useAuthentication from '~/compositions/useAuthentication';
import useConfig from '~/compositions/useConfig';
import { useForgeStore } from '~/compositions/useForgeStore';
import useNotifications from '~/compositions/useNotifications';
import type { RepoPermissions } from '~/lib/api/types';
import type { Forge, RepoPermissions } from '~/lib/api/types';
import { usePipelineStore } from '~/store/pipelines';
import { useRepoStore } from '~/store/repos';
@@ -76,14 +78,21 @@ const route = useRoute();
const router = useRouter();
const i18n = useI18n();
const config = useConfig();
const forgeStore = useForgeStore();
const { forge } = useConfig(); // TODO: remove this and use the forge type from the corresponding repo
const repo = repoStore.getRepo(repositoryId);
const repoPermissions = ref<RepoPermissions>();
const pipelines = pipelineStore.getRepoPipelines(repositoryId);
provide('repo', repo);
provide('repo-permissions', repoPermissions);
provide('pipelines', pipelines);
const forge = ref<Forge>();
const forgeIcon = computed<IconNames>(() => {
if (forge.value && forge.value.type !== 'addon') {
return forge.value.type;
}
return 'repo';
});
const showManualPipelinePopup = ref(false);
@@ -102,6 +111,10 @@ async function loadRepo() {
await repoStore.loadRepo(repositoryId.value);
await pipelineStore.loadRepoPipelines(repositoryId.value);
if (repo.value) {
forge.value = (await forgeStore.getForge(repo.value?.forge_id)).value;
}
}
onMounted(() => {