Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ENVIRONMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ pnpm docker:dev
| `ARGOCD_URL` | — | URL publique ArgoCD |
| `ARGOCD_INTERNAL_URL` | — | URL interne ArgoCD |
| `ARGOCD_EXTRA_REPOSITORIES` | — | Répôts additionnels (JSON) |
| `ARGOCD_SHARED_SOURCE_REPOSITORIES` | — | Sources autorisées pour tous les projets, `<project>` remplacé par le slug (ex. `oci://registry.example.com/<project>/**`) |

### Variables GitLab

Expand Down
4 changes: 4 additions & 0 deletions apps/server-nestjs/.env.integ-example
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ ARGO_NAMESPACE=
ARGOCD_URL=
# URL interne de l'API ArgoCD
ARGOCD_INTERNAL_URL=
# Sources autorisées pour tous les projets, séparées par des virgules.
# <project> est remplacé par le slug du projet.
# Ex. pour le registre Harbor : oci://registry.example.com/<project>/**
ARGOCD_SHARED_SOURCE_REPOSITORIES=

# --- GitLab ---
# Token d'accès personnel GitLab (scope api)
Expand Down
16 changes: 15 additions & 1 deletion apps/server-nestjs/src/config/argocd.config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { argocdConfigFactory } from './argocd.config'
import { resetEnvs } from './config-testing.utils'

describe('argocdConfig', () => {
beforeEach(() => { resetEnvs(['ARGO_NAMESPACE', 'ARGOCD_URL', 'ARGOCD_INTERNAL_URL', 'DSO_ENV_CHART_VERSION', 'DSO_NS_CHART_VERSION', 'VAULT__DEPLOY_VAULT_CONNECTION_IN_NS']) })
beforeEach(() => { resetEnvs(['ARGO_NAMESPACE', 'ARGOCD_URL', 'ARGOCD_INTERNAL_URL', 'DSO_ENV_CHART_VERSION', 'DSO_NS_CHART_VERSION', 'VAULT__DEPLOY_VAULT_CONNECTION_IN_NS', 'ARGOCD_SHARED_SOURCE_REPOSITORIES']) })
afterEach(() => { vi.unstubAllEnvs() })

it('parses a full config', () => {
Expand Down Expand Up @@ -46,6 +46,20 @@ describe('argocdConfig', () => {
expect(argocdConfigFactory().extraRepositories).toEqual([])
})

it('parses shared source repositories', () => {
vi.stubEnv('ARGOCD_URL', 'https://argocd.internal')
vi.stubEnv('ARGOCD_SHARED_SOURCE_REPOSITORIES', 'oci://registry.internal/<project>/**,https://charts.internal/**')
expect(argocdConfigFactory().sharedSourceRepositories).toEqual([
'oci://registry.internal/<project>/**',
'https://charts.internal/**',
])
})

it('defaults sharedSourceRepositories to an empty array', () => {
vi.stubEnv('ARGOCD_URL', 'https://argocd.internal')
expect(argocdConfigFactory().sharedSourceRepositories).toEqual([])
})

it('throws when a required var is missing', () => {
expect(() => argocdConfigFactory()).toThrow()
})
Expand Down
2 changes: 2 additions & 0 deletions apps/server-nestjs/src/config/argocd.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const argocdFeatureSchema = z.object({
ARGOCD_URL: z.string().url(),
ARGOCD_INTERNAL_URL: z.string().url().optional(),
ARGOCD_EXTRA_REPOSITORIES: csv(z.string()),
ARGOCD_SHARED_SOURCE_REPOSITORIES: csv(z.string()),
DSO_ENV_CHART_VERSION: z.string().default('dso-env-1.6.0'),
DSO_NS_CHART_VERSION: z.string().default('dso-ns-1.1.5'),
VAULT__DEPLOY_VAULT_CONNECTION_IN_NS: truthySchema.default('false').transform(v => v === 'true' || v === '1'),
Expand All @@ -15,6 +16,7 @@ const argocdFeatureSchema = z.object({
url: raw.ARGOCD_URL,
internalUrl: raw.ARGOCD_INTERNAL_URL,
extraRepositories: raw.ARGOCD_EXTRA_REPOSITORIES,
sharedSourceRepositories: raw.ARGOCD_SHARED_SOURCE_REPOSITORIES,
dsoEnvChartVersion: raw.DSO_ENV_CHART_VERSION,
dsoNsChartVersion: raw.DSO_NS_CHART_VERSION,
vaultDeployVaultConnectionInNs: raw.VAULT__DEPLOY_VAULT_CONNECTION_IN_NS,
Expand Down
10 changes: 9 additions & 1 deletion apps/server-nestjs/src/modules/argocd/argocd.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@ import { ArgoCDPluginService } from './argocd-plugin.service'
import { ArgoCDService } from './argocd.service'

@Module({
imports: [DatabaseModule, GitlabModule, TerminusModule, VaultModule, ConfigModule.forFeature(argocdConfigFactory), ConfigModule.forFeature(vaultConfigFactory), ConfigModule.forFeature(baseConfigFactory)],
imports: [
DatabaseModule,
GitlabModule,
TerminusModule,
VaultModule,
ConfigModule.forFeature(argocdConfigFactory),
ConfigModule.forFeature(vaultConfigFactory),
ConfigModule.forFeature(baseConfigFactory),
],
providers: [ArgoCDHealthService, ArgoCDPluginService, ArgoCDService, ArgoCDDatastoreService],
exports: [ArgoCDHealthService, ArgoCDPluginService, ArgoCDService],
})
Expand Down
44 changes: 44 additions & 0 deletions apps/server-nestjs/src/modules/argocd/argocd.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe('argoCDService', () => {
url: 'https://argocd.internal',
internalUrl: undefined,
extraRepositories: ['repo3'],
sharedSourceRepositories: ['oci://harbor.internal/<project>/**'],
dsoEnvChartVersion: 'dso-env-1.6.0',
dsoNsChartVersion: 'dso-ns-1.1.5',
vaultDeployVaultConnectionInNs: false,
Expand Down Expand Up @@ -302,6 +303,7 @@ describe('argoCDService', () => {
},
sourceRepositories: [
'https://gitlab.internal/group/project-1/**',
'oci://harbor.internal/project-1/**',
'repo2',
],
destination: {
Expand Down Expand Up @@ -377,6 +379,7 @@ describe('argoCDService', () => {
},
sourceRepositories: [
'https://gitlab.internal/group/project-1/**',
'oci://harbor.internal/project-1/**',
'repo2',
],
destination: {
Expand Down Expand Up @@ -637,6 +640,7 @@ describe('argoCDService', () => {
},
sourceRepositories: [
'https://gitlab.internal/group/project-1/**',
'oci://harbor.internal/project-1/**',
'repo2',
],
destination: {
Expand Down Expand Up @@ -817,4 +821,44 @@ describe('argoCDService', () => {

expect(values.application.repositories[0].valueFiles).toStrictEqual(['values-<env>.yaml'])
})

it('should omit shared source repositories when none are configured', async () => {
argocdConfig.sharedSourceRepositories = []
const mockProject = makeProjectWithDetails({
slug: 'project-1',
name: 'Project 1',
environments: [
makeProjectEnvironment({ name: 'dev', cluster: { id: 'c1', label: 'cluster-1', zone: { slug: 'zone-1' } } }),
],
repositories: [],
plugins: [{ pluginName: 'argocd', key: 'extraRepositories', value: 'repo2' }],
deployments: [],
})

const infraProject = makeProjectSchema({ id: 100, http_url_to_repo: 'https://gitlab.internal/infra' })
datastore.getAllProjects.mockResolvedValue([mockProject])
gitlab.getOrCreateInfraGroupRepo.mockResolvedValue(infraProject)
gitlab.getOrCreateProjectGroupPublicUrl.mockResolvedValue('https://gitlab.internal/group')
gitlab.getOrCreateInfraGroupRepoPublicUrl.mockResolvedValue('https://gitlab.internal/infra-repo')
gitlab.listFiles.mockResolvedValue([])
vault.getAuthApproleRoleRoleId.mockResolvedValue('role-id')
vault.createAuthApproleRoleSecretId.mockResolvedValue('secret-id')
gitlab.generateCreateOrUpdateAction.mockImplementation(async (_repoId, _ref, filePath: string, content: string) => {
return makeCommitAction({ filePath, content })
})

await expect(service.handleCron()).resolves.not.toThrow()

const actions = gitlab.maybeCreateCommit.mock.calls[0][2]
const values = actions
.filter((action): action is typeof action & { content: string } => 'content' in action)
.map(action => parse(action.content))
.find(v => v.application?.sourceRepositories)
expect(values).toBeDefined()

expect(values.application.sourceRepositories).toStrictEqual([
'https://gitlab.internal/group/project-1/**',
'repo2',
])
})
})
13 changes: 12 additions & 1 deletion apps/server-nestjs/src/modules/argocd/argocd.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ export class ArgoCDService {
environment,
cluster,
gitlabPublicProjectUrl,
sharedSourceRepositories: formatSharedSourceRepositories(this.argocdConfig.sharedSourceRepositories, project.slug),
argocdExtraRepositories: this.getExtraRepositories(project),
infraProject,
valueFilePath,
Expand Down Expand Up @@ -378,6 +379,7 @@ export class ArgoCDService {
environment,
cluster,
gitlabPublicProjectUrl,
sharedSourceRepositories: formatSharedSourceRepositories(this.argocdConfig.sharedSourceRepositories, project.slug),
argocdExtraRepositories: this.getExtraRepositories(project),
infraProject,
valueFilePath,
Expand Down Expand Up @@ -611,14 +613,20 @@ function formatEnvironmentValues(

interface FormatSourceRepositoriesValuesOptions {
gitlabPublicProjectUrl: string
sharedSourceRepositories: string[]
argocdExtraRepositories?: string[]
}

function formatSharedSourceRepositories(sharedSourceRepositories: string[], projectSlug: string): string[] {
return sharedSourceRepositories.map(repository => repository.replaceAll('<project>', projectSlug))
}

function formatSourceRepositoriesValues(
{ gitlabPublicProjectUrl, argocdExtraRepositories = [] }: FormatSourceRepositoriesValuesOptions,
{ gitlabPublicProjectUrl, sharedSourceRepositories, argocdExtraRepositories = [] }: FormatSourceRepositoriesValuesOptions,
): string[] {
return [
`${gitlabPublicProjectUrl}/**`,
...sharedSourceRepositories,
...argocdExtraRepositories,
]
}
Expand Down Expand Up @@ -661,6 +669,7 @@ interface FormatValuesOptions {
environment: ProjectWithDetails['environments'][number]
cluster: ProjectWithDetails['environments'][number]['cluster']
gitlabPublicProjectUrl: string
sharedSourceRepositories: string[]
argocdExtraRepositories?: string[]
vaultValues: Record<string, any>
infraProject: SimpleProjectSchema
Expand All @@ -676,6 +685,7 @@ function formatValues({
environment,
cluster,
gitlabPublicProjectUrl,
sharedSourceRepositories,
argocdExtraRepositories,
vaultValues,
infraProject,
Expand Down Expand Up @@ -708,6 +718,7 @@ function formatValues({
},
sourceRepositories: formatSourceRepositoriesValues({
gitlabPublicProjectUrl,
sharedSourceRepositories,
argocdExtraRepositories,
}),
destination: {
Expand Down