mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-01-29 18:04:15 +02:00
parent
5e595978fa
commit
37c82b905c
@ -180,6 +180,30 @@ func GetProcLogs(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func GetBuildConfig(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
repo := session.Repo(c)
|
||||
num, err := strconv.ParseInt(c.Param("number"), 10, 64)
|
||||
if err != nil {
|
||||
_ = c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
build, err := _store.GetBuildNumber(repo, num)
|
||||
if err != nil {
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
configs, err := _store.ConfigsForBuild(build.ID)
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, configs)
|
||||
}
|
||||
|
||||
// DeleteBuild cancels a build
|
||||
func DeleteBuild(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
|
@ -61,6 +61,7 @@ func apiRoutes(e *gin.Engine) {
|
||||
|
||||
repo.GET("/builds", api.GetBuilds)
|
||||
repo.GET("/builds/:number", api.GetBuild)
|
||||
repo.GET("/builds/:number/config", api.GetBuildConfig)
|
||||
|
||||
// requires push permissions
|
||||
repo.POST("/builds/:number", session.MustPush, api.PostBuild)
|
||||
|
@ -1,5 +1,16 @@
|
||||
import ApiClient, { encodeQueryString } from './client';
|
||||
import { Build, BuildFeed, BuildLog, BuildProc, Registry, Repo, RepoPermissions, RepoSettings, Secret } from './types';
|
||||
import {
|
||||
Build,
|
||||
BuildConfig,
|
||||
BuildFeed,
|
||||
BuildLog,
|
||||
BuildProc,
|
||||
Registry,
|
||||
Repo,
|
||||
RepoPermissions,
|
||||
RepoSettings,
|
||||
Secret,
|
||||
} from './types';
|
||||
|
||||
type RepoListOptions = {
|
||||
all?: boolean;
|
||||
@ -49,6 +60,10 @@ export default class WoodpeckerClient extends ApiClient {
|
||||
return this._get(`/api/repos/${owner}/${repo}/builds/${number}`) as Promise<Build>;
|
||||
}
|
||||
|
||||
getBuildConfig(owner: string, repo: string, number: number): Promise<BuildConfig[]> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/builds/${number}/config`) as Promise<BuildConfig[]>;
|
||||
}
|
||||
|
||||
getBuildFeed(opts?: Record<string, string | number | boolean>): Promise<BuildFeed[]> {
|
||||
const query = encodeQueryString(opts);
|
||||
return this._get(`/api/user/feed?${query}`) as Promise<BuildFeed[]>;
|
||||
|
6
web/src/lib/api/types/buildConfig.ts
Normal file
6
web/src/lib/api/types/buildConfig.ts
Normal file
@ -0,0 +1,6 @@
|
||||
// A config for a build.
|
||||
export type BuildConfig = {
|
||||
hash: string;
|
||||
name: string;
|
||||
data: string;
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
export * from './build';
|
||||
export * from './buildConfig';
|
||||
export * from './registry';
|
||||
export * from './repo';
|
||||
export * from './secret';
|
||||
|
@ -58,6 +58,12 @@ const routes: RouteRecordRaw[] = [
|
||||
component: (): Component => import('~/views/repo/build/Build.vue'),
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'config',
|
||||
name: 'repo-build-config',
|
||||
component: (): Component => import('~/views/repo/build/BuildConfig.vue'),
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
58
web/src/views/repo/build/BuildConfig.vue
Normal file
58
web/src/views/repo/build/BuildConfig.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<FluidContainer v-if="buildConfigs" class="flex flex-col gap-y-6 text-gray-500 justify-between !py-0">
|
||||
<Panel v-for="buildConfig in buildConfigs" :key="buildConfig.hash" :title="buildConfig.name">
|
||||
<span class="font-mono whitespace-pre">{{ buildConfig.data }}</span>
|
||||
</Panel>
|
||||
</FluidContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, inject, onMounted, Ref, ref, watch } from 'vue';
|
||||
|
||||
import FluidContainer from '~/components/layout/FluidContainer.vue';
|
||||
import Panel from '~/components/layout/Panel.vue';
|
||||
import useApiClient from '~/compositions/useApiClient';
|
||||
import { Build, BuildConfig, Repo } from '~/lib/api/types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BuildConfig',
|
||||
|
||||
components: {
|
||||
FluidContainer,
|
||||
Panel,
|
||||
},
|
||||
|
||||
setup() {
|
||||
const build = inject<Ref<Build>>('build');
|
||||
const apiClient = useApiClient();
|
||||
const repo = inject<Ref<Repo>>('repo');
|
||||
if (!repo || !build) {
|
||||
throw new Error('Unexpected: "repo" & "build" should be provided at this place');
|
||||
}
|
||||
|
||||
const buildConfigs = ref<BuildConfig[]>();
|
||||
async function loadBuildConfig() {
|
||||
if (!repo || !build) {
|
||||
throw new Error('Unexpected: "repo" & "build" should be provided at this place');
|
||||
}
|
||||
|
||||
buildConfigs.value = (await apiClient.getBuildConfig(repo.value.owner, repo.value.name, build.value.number)).map(
|
||||
(i) => ({
|
||||
...i,
|
||||
data: atob(i.data),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadBuildConfig();
|
||||
});
|
||||
|
||||
watch(build, () => {
|
||||
loadBuildConfig();
|
||||
});
|
||||
|
||||
return { buildConfigs };
|
||||
},
|
||||
});
|
||||
</script>
|
@ -31,6 +31,7 @@
|
||||
<div class="flex flex-wrap gap-y-2 items-center justify-between">
|
||||
<Tabs v-model="activeTab" disable-hash-mode>
|
||||
<Tab id="tasks" title="Tasks" />
|
||||
<Tab id="config" title="Config" />
|
||||
</Tabs>
|
||||
|
||||
<div class="flex justify-between gap-x-4 text-gray-500 flex-shrink-0 ml-auto">
|
||||
@ -63,7 +64,7 @@ import {
|
||||
toRef,
|
||||
watch,
|
||||
} from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import Button from '~/components/atomic/Button.vue';
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
@ -122,6 +123,7 @@ export default defineComponent({
|
||||
|
||||
setup(props) {
|
||||
const apiClient = useApiClient();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const notifications = useNotifications();
|
||||
const favicon = useFavicon();
|
||||
@ -191,12 +193,20 @@ export default defineComponent({
|
||||
|
||||
const activeTab = computed({
|
||||
get() {
|
||||
if (route.name === 'repo-build-config') {
|
||||
return 'config';
|
||||
}
|
||||
|
||||
return 'tasks';
|
||||
},
|
||||
set(tab: string) {
|
||||
if (tab === 'tasks') {
|
||||
router.replace({ name: 'repo-build' });
|
||||
}
|
||||
|
||||
if (tab === 'config') {
|
||||
router.replace({ name: 'repo-build-config' });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user