Skip to content

Commit

Permalink
feat(tekton): support pipelinesascode annotation (#26033)
Browse files Browse the repository at this point in the history
Co-authored-by: Rhys Arkins <rhys@arkins.net>
  • Loading branch information
fabian-heib and rarkins committed Dec 5, 2023
1 parent 540ad4f commit 8c17027
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 2 deletions.
26 changes: 26 additions & 0 deletions lib/modules/manager/tekton/__fixtures__/multi-doc-annotations.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
kind: PipelineRun
metadata:
annotations:
pipelinesascode.tekton.dev/on-event: "[pull_request]"
pipelinesascode.tekton.dev/task: "[git-clone,https://github.com/foo/bar/releases/download/v0.0.4/stakater-create-git-tag.yaml]"
---
kind: PipelineRun
metadata:
annotations:
pipelinesascode.tekton.dev/task: "[git-clone,
https://raw.githubusercontent.com/foo/bar/v0.0.6/tasks/create-git-tag/create-git-tag.yaml]"
---
kind: PipelineRun
metadata:
annotations:
pipelinesascode.tekton.dev/task: "git-clone"
pipelinesascode.tekton.dev/task-1: "https://github.com/foo/bar/raw/v0.0.8/tasks/create-git-tag/create-git-tag.yaml"
---
kind: PipelineRun
metadata:
annotations:
pipelinesascode.tekton.dev/task: "[git-clone,
https://github.com/foo/bar/releases/download/v0.0.9/stakater-create-git-tag.yaml,
https://github.com/foo/bar/raw/v0.0.7/tasks/create-git-tag/create-git-tag.yaml,
https://raw.githubusercontent.com/foo/bar/v0.0.5/tasks/create-git-tag/create-git-tag.yaml]"
53 changes: 53 additions & 0 deletions lib/modules/manager/tekton/extract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,59 @@ describe('modules/manager/tekton/extract', () => {
expect(result?.deps).toHaveLength(39);
});

it('extracts deps from a file in annotations', () => {
const result = extractPackageFile(
Fixtures.get('multi-doc-annotations.yaml'),
'test-file.yaml',
);
expect(result).toEqual({
deps: [
{
currentValue: 'v0.0.4',
datasource: 'github-releases',
depName: 'github.com/foo/bar',
depType: 'tekton-annotation',
packageName: 'foo/bar',
},
{
currentValue: 'v0.0.6',
datasource: 'git-tags',
depName: 'github.com/foo/bar',
depType: 'tekton-annotation',
packageName: 'https://github.com/foo/bar',
},
{
currentValue: 'v0.0.8',
datasource: 'git-tags',
depName: 'github.com/foo/bar',
depType: 'tekton-annotation',
packageName: 'https://github.com/foo/bar',
},
{
currentValue: 'v0.0.9',
datasource: 'github-releases',
depName: 'github.com/foo/bar',
depType: 'tekton-annotation',
packageName: 'foo/bar',
},
{
currentValue: 'v0.0.7',
datasource: 'git-tags',
depName: 'github.com/foo/bar',
depType: 'tekton-annotation',
packageName: 'https://github.com/foo/bar',
},
{
currentValue: 'v0.0.5',
datasource: 'git-tags',
depName: 'github.com/foo/bar',
depType: 'tekton-annotation',
packageName: 'https://github.com/foo/bar',
},
],
});
});

it('ignores file without any deps', () => {
expect(extractPackageFile('foo: bar', 'test-file.yaml')).toBeNull();
});
Expand Down
76 changes: 76 additions & 0 deletions lib/modules/manager/tekton/extract.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import is from '@sindresorhus/is';
import { logger } from '../../../logger';
import { coerceArray } from '../../../util/array';
import { regEx } from '../../../util/regex';
import { parseYaml } from '../../../util/yaml';
import { GitTagsDatasource } from '../../datasource/git-tags';
import { GithubReleasesDatasource } from '../../datasource/github-releases';
import { getDep } from '../dockerfile/extract';
import type { PackageDependency, PackageFileContent } from '../types';
import type {
Expand Down Expand Up @@ -52,6 +55,8 @@ function getDeps(doc: TektonResource): PackageDependency[] {
// Handle PipelineRun resource
addDep(doc.spec?.pipelineRef, deps);

addPipelineAsCodeAnnotations(doc.metadata?.annotations, deps);

// Handle PipelineRun resource with inline Pipeline definition
const pipelineSpec = doc.spec?.pipelineSpec;
if (is.truthy(pipelineSpec)) {
Expand Down Expand Up @@ -80,6 +85,77 @@ function getDeps(doc: TektonResource): PackageDependency[] {
return deps;
}

const taskAnnotation = regEx(/^pipelinesascode\.tekton\.dev\/task(-[0-9]+)?$/);

function addPipelineAsCodeAnnotations(
annotations: Record<string, string> | undefined | null,
deps: PackageDependency[],
): void {
if (is.nullOrUndefined(annotations)) {
return;
}

for (const [key, value] of Object.entries(annotations)) {
if (!taskAnnotation.test(key)) {
continue;
}

const tasks = value
.replace(regEx(/]$/), '')
.replace(regEx(/^\[/), '')
.split(',');
for (const task of tasks) {
const dep = getAnnotationDep(task.trim());
if (!dep) {
continue;
}
deps.push(dep);
}
}
}

const githubRelease = regEx(
/^(?<url>(?:(?:http|https):\/\/)?(?<path>(?:[^:/\s]+[:/])?(?<project>[^/\s]+\/[^/\s]+)))\/releases\/download\/(?<currentValue>.+)\/(?<subdir>[^?\s]*)$/,
);

const gitUrl = regEx(
/^(?<url>(?:(?:http|https):\/\/)?(?<path>(?:[^:/\s]+[:/])?(?<project>[^/\s]+\/[^/\s]+)))(?:\/raw)?\/(?<currentValue>.+?)\/(?<subdir>[^?\s]*)$/,
);

function getAnnotationDep(url: string): PackageDependency | null {
const dep: PackageDependency = {};
dep.depType = 'tekton-annotation';

let groups = githubRelease.exec(url)?.groups;

if (groups) {
dep.datasource = GithubReleasesDatasource.id;

dep.depName = groups.path;
dep.packageName = groups.project;
dep.currentValue = groups.currentValue;
return dep;
}

groups = gitUrl.exec(url)?.groups;
if (groups) {
dep.datasource = GitTagsDatasource.id;

dep.depName = groups.path.replace(
'raw.githubusercontent.com',
'github.com',
);
dep.packageName = groups.url.replace(
'raw.githubusercontent.com',
'github.com',
);
dep.currentValue = groups.currentValue;
return dep;
}

return null;
}

function addDep(ref: TektonBundle, deps: PackageDependency[]): void {
if (is.falsy(ref)) {
return;
Expand Down
3 changes: 2 additions & 1 deletion lib/modules/manager/tekton/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Category } from '../../../constants';
import { DockerDatasource } from '../../datasource/docker';
import { GitTagsDatasource } from '../../datasource/git-tags';
import { extractPackageFile } from './extract';

export const defaultConfig = {
Expand All @@ -8,6 +9,6 @@ export const defaultConfig = {

export const categories: Category[] = ['ci', 'cd'];

export const supportedDatasources = [DockerDatasource.id];
export const supportedDatasources = [DockerDatasource.id, GitTagsDatasource.id];

export { extractPackageFile };
21 changes: 20 additions & 1 deletion lib/modules/manager/tekton/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,28 @@ They can be created directly as a Kubernetes resource with standard tools like `
Tasks and Pipeline definitions can also live outside the Kubernetes cluster and get fetched by Tekton when needed, this approach relies on Tekton resource references rather than the resource definition.
The `tekton` manager focuses on providing updates to Tekton resource references.

Right now, Renovate's Tekton manager only supports references that are [Bundles](https://tekton.dev/docs/pipelines/tekton-bundle-contracts/).
Right now, Renovate's Tekton manager supports references that are [Bundles](https://tekton.dev/docs/pipelines/tekton-bundle-contracts/) and [PipelinesAsCode](https://pipelinesascode.com) with [remote HTTP URL resolver](https://pipelinesascode.com/docs/guide/resolver/#remote-http-url).
Read the [Tekton Pipeline remote resolution docs](https://tekton.dev/docs/pipelines/resolution/) for the different kinds of Tekton references and their corresponding resolvers.

### Using a PipelinesAsCode remote URL reference

By specifying the annotation with a remote task based on the recommended way using [git based versioning](https://github.com/tektoncd/community/blob/main/teps/0115-tekton-catalog-git-based-versioning.md). How this can be used can be seen in the example below.

```yaml title="How an annotation in could look like in an pipeline-run.yaml"
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: main
annotations:
pipelinesascode.tekton.dev/task: 'https://github.com/foo/bar/raw/v0.0.1/tasks/task/task.yaml'
```

Supported URLs:

1. <https://github.com/foo/bar/raw/v0.0.1/tasks/task/task.yaml><
2. <https://raw.githubusercontent.com/foo/bar/v0.0.1/tasks/task/task.yaml>
3. <https://github.com/foo/bar/releases/download/v0.0.1/create-git-tag-task.yaml>

### Using a Tekton Bundle reference

There are three ways to use a Tekton Bundle reference:
Expand Down
3 changes: 3 additions & 0 deletions lib/modules/manager/tekton/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export interface TektonResource {
spec: TektonResourceSpec;
items?: TektonResource[];
metadata?: {
annotations: Record<string, string>;
};
}

export interface TektonResourceSpec {
Expand Down

0 comments on commit 8c17027

Please sign in to comment.