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

feat(gitlab): support GitLab CI/CD component references #26660

Merged
merged 24 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7458246
feat(gitlab): support GitLab CI/CD component references
fgreinacher Jan 16, 2024
3384d43
Merge branch 'main' into feat/cicd-components
fgreinacher Jan 16, 2024
f2e6482
refactor: reject incomplete project paths
fgreinacher Jan 16, 2024
f784b6c
refactor: ignore external component references
fgreinacher Jan 16, 2024
36fbbc6
refactor: rename variable
fgreinacher Jan 16, 2024
d5107b0
Merge branch 'main' into feat/cicd-components
fgreinacher Jan 16, 2024
144978f
refactor: remove unneeded optional accessor
fgreinacher Jan 17, 2024
12a5a4f
refactor: replace snapshot by inline object
fgreinacher Jan 17, 2024
8e79c98
refactor: remove unneeded array handling
fgreinacher Jan 17, 2024
457c124
refactor: simplify regex matching
fgreinacher Jan 17, 2024
acb0b13
Merge branch 'main' into feat/cicd-components
fgreinacher Jan 17, 2024
80b0211
Merge branch 'main' into feat/cicd-components
fgreinacher Jan 17, 2024
c3a6318
refactor: set registry URL for external component reference
fgreinacher Jan 17, 2024
ef932dd
refactor: move new logic to gitlabci manager
fgreinacher Jan 17, 2024
14b9e30
test: adapt fixtures
fgreinacher Jan 17, 2024
08b3044
Merge remote-tracking branch 'upstream/main' into feat/cicd-components
fgreinacher Jan 19, 2024
5d82bc1
test: add missing test case
fgreinacher Jan 19, 2024
c11ba71
refactor: delete unneeded fixture
fgreinacher Jan 19, 2024
e61f617
fix: update supported datasources
fgreinacher Jan 19, 2024
dac0433
docs: remove wrong comment
fgreinacher Jan 19, 2024
2e37a6e
refactor: inline variable
fgreinacher Jan 20, 2024
3cbce5a
refactor: always set registryUrls
fgreinacher Jan 20, 2024
ec13858
Update extract.ts
fgreinacher Jan 20, 2024
91a4d20
Merge branch 'main' into feat/cicd-components
fgreinacher Jan 23, 2024
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
61 changes: 0 additions & 61 deletions lib/modules/manager/gitlabci-include/common.spec.ts

This file was deleted.

34 changes: 0 additions & 34 deletions lib/modules/manager/gitlabci-include/common.ts

This file was deleted.

10 changes: 5 additions & 5 deletions lib/modules/manager/gitlabci-include/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { logger } from '../../../logger';
import { regEx } from '../../../util/regex';
import { parseSingleYaml } from '../../../util/yaml';
import { GitlabTagsDatasource } from '../../datasource/gitlab-tags';
import {
filterIncludeFromGitlabPipeline,
isGitlabIncludeProject,
isNonEmptyObject,
} from '../gitlabci/common';
import type {
GitlabInclude,
GitlabIncludeProject,
GitlabPipeline,
} from '../gitlabci/types';
import { replaceReferenceTags } from '../gitlabci/utils';
import type { PackageDependency, PackageFileContent } from '../types';
import {
filterIncludeFromGitlabPipeline,
isGitlabIncludeProject,
isNonEmptyObject,
} from './common';

function extractDepFromIncludeFile(
includeObj: GitlabIncludeProject,
Expand Down
13 changes: 13 additions & 0 deletions lib/modules/manager/gitlabci/__fixtures__/include.2.yaml
fgreinacher marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
include:
- project: mikebryant/include-source-example
file: /template.yaml
ref: 1.0.0
- project: mikebryant/include-source-example2
file: /template.yaml
ref: master
- {"project":"mikebryant/include-source-example3", "file": "/template.yaml",}
- {}

script:
- !reference [.setup, script]
- !reference [arbitrary job name with space and no starting dot, nested1, nested2, nested3]
47 changes: 46 additions & 1 deletion lib/modules/manager/gitlabci/common.spec.ts
fgreinacher marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
import { isGitlabIncludeLocal } from './common';
import { Fixtures } from '../../../../test/fixtures';
import { parseSingleYaml } from '../../../util/yaml';
import type { GitlabPipeline } from '../gitlabci/types';
import { replaceReferenceTags } from '../gitlabci/utils';
import {
filterIncludeFromGitlabPipeline,
isGitlabIncludeLocal,
isGitlabIncludeProject,
isNonEmptyObject,
} from './common';

const yamlFileMultiConfig = Fixtures.get('include.2.yaml');
// TODO: use schema (#9610)
const pipeline = parseSingleYaml<GitlabPipeline>(
replaceReferenceTags(yamlFileMultiConfig),
);
const includeLocal = { local: 'something' };
const includeProject = { project: 'something' };

describe('modules/manager/gitlabci/common', () => {
describe('filterIncludeFromGitlabPipeline()', () => {
it('returns GitlabPipeline without top level include key', () => {
expect(pipeline).toHaveProperty('include');
const filtered_pipeline = filterIncludeFromGitlabPipeline(pipeline);
expect(filtered_pipeline).not.toHaveProperty('include');
expect(filtered_pipeline).toEqual({
script: [null, null],
});
});
});

describe('isGitlabIncludeLocal()', () => {
it('returns true if GitlabInclude is GitlabIncludeLocal', () => {
expect(isGitlabIncludeLocal(includeLocal)).toBe(true);
Expand All @@ -13,4 +38,24 @@ describe('modules/manager/gitlabci/common', () => {
expect(isGitlabIncludeLocal(includeProject)).toBe(false);
});
});

describe('isGitlabIncludeProject()', () => {
it('returns true if GitlabInclude is GitlabIncludeProject', () => {
expect(isGitlabIncludeProject(includeProject)).toBe(true);
});

it('returns false if GitlabInclude is not GitlabIncludeProject', () => {
expect(isGitlabIncludeProject(includeLocal)).toBe(false);
});
});

describe('isNonEmptyObject()', () => {
it('returns true if not empty', () => {
expect(isNonEmptyObject({ attribute1: 1 })).toBe(true);
});

it('returns false if empty', () => {
expect(isNonEmptyObject({})).toBe(false);
});
});
});
35 changes: 34 additions & 1 deletion lib/modules/manager/gitlabci/common.ts
fgreinacher marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,8 +1,41 @@
import is from '@sindresorhus/is';
import type { GitlabInclude, GitlabIncludeLocal } from '../gitlabci/types';
import type {
GitlabInclude,
GitlabIncludeComponent,
GitlabIncludeLocal,
GitlabIncludeProject,
GitlabPipeline,
} from '../gitlabci/types';

export function isNonEmptyObject(obj: any): boolean {
return is.object(obj) && Object.keys(obj).length !== 0;
}

export function filterIncludeFromGitlabPipeline(
pipeline: GitlabPipeline,
): GitlabPipeline {
const pipeline_without_include: GitlabPipeline = {};
for (const key of Object.keys(pipeline).filter((key) => key !== 'include')) {
const pipeline_key = key as keyof typeof pipeline;
pipeline_without_include[pipeline_key] = pipeline[pipeline_key];
}
return pipeline_without_include;
}

export function isGitlabIncludeProject(
include: GitlabInclude,
): include is GitlabIncludeProject {
return !is.undefined((include as GitlabIncludeProject).project);
}

export function isGitlabIncludeLocal(
include: GitlabInclude,
): include is GitlabIncludeLocal {
return !is.undefined((include as GitlabIncludeLocal).local);
}

export function isGitlabIncludeComponent(
include: GitlabInclude,
): include is GitlabIncludeComponent {
return !is.undefined((include as GitlabIncludeComponent).component);
}
59 changes: 59 additions & 0 deletions lib/modules/manager/gitlabci/extract.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { codeBlock } from 'common-tags';
import { logger } from '../../../../test/util';
import { GlobalConfig } from '../../../config/global';
import type { RepoGlobalConfig } from '../../../config/types';
Expand Down Expand Up @@ -347,5 +348,63 @@ describe('modules/manager/gitlabci/extract', () => {
expect(extractFromJob(undefined)).toBeEmptyArray();
expect(extractFromJob({ image: 'image:test' })).toEqual(expectedRes);
});

it('extracts component references', () => {
GlobalConfig.set({
endpoint: 'https://gitlab.example.com',
});

const content = codeBlock`
include:
- component: gitlab.example.com/an-org/a-project/a-component@1.0
inputs:
stage: build
- component: gitlab.example.com/an-org/a-subgroup/a-project/a-component@e3262fdd0914fa823210cdb79a8c421e2cef79d8
- component: gitlab.example.com/an-org/a-subgroup/another-project/a-component@main
- component: gitlab.example.com/another-org/a-project/a-component@~latest
inputs:
stage: test
- component: gitlab.example.com/malformed-component-reference
- component:
malformed: true
- component: gitlab.example.com/an-org/a-component@1.0
- component: other-gitlab.example.com/an-org/a-project/a-component@1.0
`;
const res = extractPackageFile(content, '', {});
expect(res?.deps).toMatchObject([
{
currentValue: '1.0',
datasource: 'gitlab-tags',
depName: 'an-org/a-project',
depType: 'repository',
},
{
currentValue: 'e3262fdd0914fa823210cdb79a8c421e2cef79d8',
datasource: 'gitlab-tags',
depName: 'an-org/a-subgroup/a-project',
depType: 'repository',
},
{
currentValue: 'main',
datasource: 'gitlab-tags',
depName: 'an-org/a-subgroup/another-project',
depType: 'repository',
},
{
currentValue: '~latest',
datasource: 'gitlab-tags',
depName: 'another-org/a-project',
depType: 'repository',
skipReason: 'unsupported-version',
},
{
currentValue: '1.0',
datasource: 'gitlab-tags',
depName: 'an-org/a-project',
depType: 'repository',
registryUrls: ['https://other-gitlab.example.com'],
},
]);
});
});
});
Loading