Skip to content

Commit

Permalink
Merge pull request #1448 from cloud-pi-native/hotfix/gitlab-plugin-2
Browse files Browse the repository at this point in the history
Hotfix/gitlab plugin 2
  • Loading branch information
ArnaudTA authored Nov 8, 2024
2 parents 3b070ad + 16f195e commit dff379a
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 116 deletions.
150 changes: 79 additions & 71 deletions apps/client/src/views/admin/AdminProject.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import { onBeforeMount, ref } from 'vue'
// @ts-ignore '@gouvminint/vue-dsfr' missing types
import { getRandomId } from '@gouvminint/vue-dsfr'
import type { Environment, Log, PluginsUpdateBody, ProjectService, ProjectV2 } from '@cpn-console/shared'
import { sortArrByObjKeyAsc } from '@cpn-console/shared'
import type { Environment, Log, PluginsUpdateBody, ProjectService, ProjectV2, Repo } from '@cpn-console/shared'
import fr from 'javascript-time-ago/locale/fr'
import TimeAgo from 'javascript-time-ago'
import { useSnackbarStore } from '@/stores/snackbar.js'
Expand Down Expand Up @@ -39,38 +38,13 @@ const logsId = 'logsView'
const project = computed(() => projectStore.projectsById[props.projectId])
const environments = ref<Environment[]>()
const repositories = ref<Repo[]>()
// Add locale-specific relative date/time formatting rules.
TimeAgo.addLocale(fr)
// Create relative date/time formatter.
const timeAgo = new TimeAgo('fr-FR')
const repoRows = computed(() => {
if (!project.value.repositories?.length) {
return [[{
text: 'Aucun dépôt existant',
cellAttrs: {
colspan: headerRepos.length,
},
}]]
}
return sortArrByObjKeyAsc(project.value.repositories, 'internalRepoName')
.map(({ internalRepoName, isInfra, externalRepoUrl, isPrivate, createdAt }) => (
[
internalRepoName,
isInfra ? 'Infra' : 'Applicatif',
isPrivate ? 'oui' : 'non',
externalRepoUrl || '-',
{
text: timeAgo.format(new Date(createdAt)),
title: (new Date(createdAt)).toLocaleString(),
component: 'span',
},
]
),
)
})
function unSelectProject() {
router.push({ name: 'ListProjects' })
}
Expand Down Expand Up @@ -109,12 +83,13 @@ async function transferOwnerShip(nextOwnerId: string) {
async function getProjectDetails() {
try {
const [envs] = await Promise.all([
const [projectDetails] = await Promise.all([
project.value.refresh(),
reloadProjectServices(),
showLogs(0),
])
environments.value = envs.environments
environments.value = projectDetails.environments
repositories.value = projectDetails.repositories
} catch (error) {
console.trace(error)
}
Expand Down Expand Up @@ -314,59 +289,91 @@ async function getProjectLogs({ offset, limit }: { offset: number, limit: number
:key="environmentsCtKey"
title="Environnements"
>
<thead>
<td
v-for="header in headerEnvs"
:key="header"
>
{{ header }}
</td>
</thead>
<tbody>
<tr
v-for="env in environments?.sort((e1, e2) => Number(e1.createdAt) - Number(e2.createdAt))"
:key="env.id"
>
<td>{{ env.name }}</td>
<td>{{ stageStore.stages.find(stage => stage.id === env.stageId)?.name ?? 'Type inconnu...' }}</td>
<td>
<DsfrSelect
v-model="env.quotaId"
label=""
:options="quotaStore.quotas.filter(quota => quota.stageIds.includes(env.stageId)).map(quota => ({
text: `${quota.name} (${quota.cpu}CPU, ${quota.memory})`,
value: quota.id,
}))"
select-id="quota-select"
@update:model-value="(event: string) => updateEnvironmentQuota({ environmentId: env.id, quotaId: event })"
/>
</td>
<template #header>
<tr>
<td
:title="(new Date(env.createdAt)).toLocaleString()"
v-for="header in headerEnvs"
:key="header"
>
<span>{{ timeAgo.format(new Date(env.createdAt)) }}</span>
{{ header }}
</td>
</tr>
<tr
v-if="!project.environments?.length"
</template>
<tr
v-for="env in environments?.sort((e1, e2) => Number(e1.createdAt) - Number(e2.createdAt))"
:key="env.id"
>
<td>{{ env.name }}</td>
<td>{{ stageStore.stages.find(stage => stage.id === env.stageId)?.name ?? 'Type inconnu...' }}</td>
<td>
<DsfrSelect
v-model="env.quotaId"
label=""
:options="quotaStore.quotas.filter(quota => quota.stageIds.includes(env.stageId)).map(quota => ({
text: `${quota.name} (${quota.cpu}CPU, ${quota.memory})`,
value: quota.id,
}))"
select-id="quota-select"
@update:model-value="(event: string) => updateEnvironmentQuota({ environmentId: env.id, quotaId: event })"
/>
</td>
<td
:title="(new Date(env.createdAt)).toLocaleString()"
>
<td
:colspan="headerEnvs.length"
>
Aucun environnement existant
</td>
</tr>
</tbody>
<span>{{ timeAgo.format(new Date(env.createdAt)) }}</span>
</td>
</tr>
<tr
v-if="!project.environments?.length"
>
<td
:colspan="headerEnvs.length"
>
Aucun environnement existant
</td>
</tr>
</DsfrTable>

<hr>
<DsfrTable
:id="repositoriesId"
:key="repositoriesCtKey"
title="Dépôts"
:headers="headerRepos"
:rows="repoRows"
/>
>
<template #header>
<tr>
<td
v-for="header in headerRepos"
:key="header"
>
{{ header }}
</td>
</tr>
</template>
<tr
v-for="repo in repositories"
:key="repo.id"
>
<td>{{ repo.internalRepoName }}</td>
<td>{{ repo.isInfra ? 'Infra' : 'Applicatif' }}</td>
<td>{{ repo.isPrivate ? 'oui' : 'non' }}</td>
<td>{{ repo.externalRepoUrl || '-' }}</td>
<td
:title="(new Date(repo.createdAt)).toLocaleString()"
>
{{ timeAgo.format(new Date(repo.createdAt)) }}
</td>
</tr>
<tr
v-if="!repositories?.length"
>
<td
:colspan="headerEnvs.length"
>
Aucun dépôt existant
</td>
</tr>
</DsfrTable>
<hr>
<TeamCt
:id="membersId"
Expand All @@ -388,6 +395,7 @@ async function getProjectLogs({ offset, limit }: { offset: number, limit: number
:services="projectServices"
permission-target="admin"
:display-global="false"
:disabled="false"
@update="(data: PluginsUpdateBody) => saveProjectServices(data)"
@reload="() => reloadProjectServices()"
/>
Expand Down
2 changes: 1 addition & 1 deletion plugins/gitlab/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@cpn-console/gitlab-plugin",
"type": "module",
"version": "2.4.0",
"version": "2.4.1",
"private": false,
"description": "",
"main": "dist/index.js",
Expand Down
7 changes: 4 additions & 3 deletions plugins/gitlab/src/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import type { VaultProjectApi } from '@cpn-console/vault-plugin/types/class.js'
import { objectEntries } from '@cpn-console/shared'
import type { GitbeakerRequestError } from '@gitbeaker/requester-utils'
import { getOrganizationId } from './group.js'
import { getApi, getConfig, getGroupRootId, infraAppsRepoName, internalMirrorRepoName } from './utils.js'
import { getApi, getGroupRootId, infraAppsRepoName, internalMirrorRepoName } from './utils.js'
import config from './config.js'

type setVariableResult = 'created' | 'updated' | 'already up-to-date'
type AccessLevelAllowed = AccessLevel.NO_ACCESS | AccessLevel.MINIMAL_ACCESS | AccessLevel.GUEST | AccessLevel.REPORTER | AccessLevel.DEVELOPER | AccessLevel.MAINTAINER | AccessLevel.OWNER
Expand Down Expand Up @@ -118,7 +119,7 @@ export class GitlabProjectApi extends PluginApi {
}

public async getProjectId(projectName: string) {
const pathProjectName = `${getConfig().projectsRootDir}/${this.project.organization.name}/${this.project.name}/${projectName}`
const pathProjectName = `${config().projectsRootDir}/${this.project.organization.name}/${this.project.name}/${projectName}`
const project = (await this.api.Projects.search(projectName)).find(p => p.path_with_namespace === pathProjectName)

if (!project) {
Expand Down Expand Up @@ -183,7 +184,7 @@ export class GitlabProjectApi extends PluginApi {

// Repositories
public async getRepoUrl(repoName: string) {
return `${getConfig().url}/${getConfig().projectsRootDir}/${this.project.organization.name}/${this.project.name}/${repoName}.git`
return `${config().publicUrl}/${config().projectsRootDir}/${this.project.organization.name}/${this.project.name}/${repoName}.git`
}

public async listRepositories() {
Expand Down
26 changes: 26 additions & 0 deletions plugins/gitlab/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { removeTrailingSlash, requiredEnv } from '@cpn-console/shared'

class Config {
publicUrl: string
internalUrl: string
token: string
projectsRootDir: string
constructor() {
this.token = requiredEnv('GITLAB_TOKEN')
this.publicUrl = removeTrailingSlash(requiredEnv('GITLAB_URL'))
this.projectsRootDir = requiredEnv('PROJECTS_ROOT_DIR')
this.internalUrl = process.env.GITLAB_INTERNAL_URL
? removeTrailingSlash(process.env.GITLAB_INTERNAL_URL)
: this.publicUrl
}
}

let config: Config | undefined

function getConfig() {
if (!config) {
config = new Config()
}
return config
}
export default getConfig
5 changes: 3 additions & 2 deletions plugins/gitlab/src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { createUsername, getUser } from './user.js'
import { ensureMembers } from './members.js'
import { ensureRepositories } from './repositories.js'
import type { VaultSecrets } from './utils.js'
import { cleanGitlabError, getConfig } from './utils.js'
import { cleanGitlabError } from './utils.js'
import config from './config.js'

// Check
export const checkApi: StepCall<Project> = async (payload) => {
Expand Down Expand Up @@ -53,7 +54,7 @@ export const getDsoProjectSecrets: StepCall<ProjectLite> = async (payload) => {
'-F ref=main',
'-F variables[GIT_BRANCH_DEPLOY]=\${BRANCH_TO_SYNC}',
'-F variables[PROJECT_NAME]=\${REPOSITORY_NAME}',
`"${getConfig().url}/api/v4/projects/${gitlab.GIT_MIRROR_PROJECT_ID}/trigger/pipeline"`,
`"${config().publicUrl}/api/v4/projects/${gitlab.GIT_MIRROR_PROJECT_ID}/trigger/pipeline"`,
]
/* eslint-enable */
const secrets: Record<string, string> = {
Expand Down
5 changes: 4 additions & 1 deletion plugins/gitlab/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import { GitlabProjectApi } from './class.js'
const onlyApi = { api: (project: Project | UniqueRepo) => new GitlabProjectApi(project) }

function start() {
getGroupRootId()
getGroupRootId().catch((error) => {
console.log(error)
throw new Error('Error at gitlab plugin start')
})
}

export const plugin: Plugin = {
Expand Down
4 changes: 2 additions & 2 deletions plugins/gitlab/src/infos.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ServiceInfos } from '@cpn-console/hooks'
import { ENABLED } from '@cpn-console/shared'
import { getConfig } from './utils.js'
import config from './config.js'

const infos = {
name: 'gitlab',
to: ({ project, organization }) => `${getConfig().url}/${getConfig().projectsRootDir}/${organization}/${project}`,
to: ({ project, organization }) => `${config().publicUrl}/${config().projectsRootDir}/${organization}/${project}`,
title: 'Gitlab',
imgSrc: '/img/gitlab.svg',
description: 'GitLab est un service d\'hébergement de code source et de pipeline CI/CD',
Expand Down
4 changes: 2 additions & 2 deletions plugins/gitlab/src/monitor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Monitor, type MonitorInfos, MonitorStatus } from '@cpn-console/shared'
import axios from 'axios'
import { getConfig } from './utils.js'
import config from './config.js'

enum HealthStatus {
failed = 'failed',
Expand All @@ -12,7 +12,7 @@ const coreComponents = ['gitaly_check', 'master_check', 'db_check', 'sessions_ch
async function monitor(instance: Monitor): Promise<MonitorInfos> {
instance.lastStatus.lastUpdateTimestamp = (new Date()).getTime()
try {
const res = await axios.get(`${getConfig().internalUrl}/-/readiness?all=1`, {
const res = await axios.get(`${config().publicUrl}/-/readiness?all=1`, {
validateStatus: res => res === 200,
})
if (res.status === 200) { // 200 only means api responds
Expand Down
37 changes: 3 additions & 34 deletions plugins/gitlab/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
import { Gitlab } from '@gitbeaker/rest'
import type { Gitlab as IGitlab } from '@gitbeaker/core'
import { removeTrailingSlash, requiredEnv } from '@cpn-console/shared'
import { GitbeakerRequestError } from '@gitbeaker/requester-utils'
import config from './config.js'

let api: IGitlab | undefined

let groupRootId: number | void

const config: {
token?: string
url?: string
internaUrl?: string
projectsRootDir?: string
} = {
token: undefined,
url: undefined,
projectsRootDir: undefined,
}

export async function getGroupRootId(): Promise<number> {
const gitlabApi = getApi()
const projectRootDir = getConfig().projectsRootDir
const projectRootDir = config().projectsRootDir
if (groupRootId) return groupRootId
const groupRootSearch = await gitlabApi.Groups.search(projectRootDir)
groupRootId = (groupRootSearch.find(grp => grp.full_path === projectRootDir))?.id
Expand All @@ -32,31 +21,11 @@ export async function getGroupRootId(): Promise<number> {

export function getApi(): IGitlab {
if (!api) {
const gitlabUrl = getConfig().internalUrl
const gitlabToken = requiredEnv('GITLAB_TOKEN')
// @ts-ignore
api = new Gitlab({ token: gitlabToken, host: gitlabUrl })
api = new Gitlab({ token: config().token, host: config().internalUrl })
}
// @ts-ignore
return api
}

export function getConfig(): {
token: string
url: string
internalUrl?: string
projectsRootDir: string
} {
if (!config.projectsRootDir || !config.token || !config.url || !config.internaUrl) {
config.token = requiredEnv('GITLAB_TOKEN')
config.url = removeTrailingSlash(requiredEnv('GITLAB_URL'))
config.internaUrl = process.env.GITLAB_INTERNAL_URL ? removeTrailingSlash(process.env.GITLAB_INTERNAL_URL) : config.url
config.projectsRootDir = requiredEnv('PROJECTS_ROOT_DIR')
}
// @ts-ignore trouver un meilleur softboot
return config
}

export const infraAppsRepoName = 'infra-apps'
export const internalMirrorRepoName = 'mirror'

Expand Down

0 comments on commit dff379a

Please sign in to comment.