diff --git a/lib/modules/manager/api.ts b/lib/modules/manager/api.ts index 3f45b28b1b1380eaab073ca49e5cb91774765b3d..ebe04c9b60ce0f4591b39f05fb271e8be6c96a7e 100644 --- a/lib/modules/manager/api.ts +++ b/lib/modules/manager/api.ts @@ -67,6 +67,7 @@ import * as terragrunt from './terragrunt'; import * as terragruntVersion from './terragrunt-version'; import * as travis from './travis'; import type { ManagerApi } from './types'; +import * as velaci from './velaci'; const api = new Map<string, ManagerApi>(); export default api; @@ -139,3 +140,4 @@ api.set('terraform-version', terraformVersion); api.set('terragrunt', terragrunt); api.set('terragrunt-version', terragruntVersion); api.set('travis', travis); +api.set('velaci', velaci); diff --git a/lib/modules/manager/velaci/__fixtures__/.vela-secrets.yml b/lib/modules/manager/velaci/__fixtures__/.vela-secrets.yml new file mode 100644 index 0000000000000000000000000000000000000000..69f7d1a31e3f5070388f25ae461ae31f38878f95 --- /dev/null +++ b/lib/modules/manager/velaci/__fixtures__/.vela-secrets.yml @@ -0,0 +1,24 @@ +version: "1" + +steps: + - name: node + image: amd64/node:10.0.0@sha256:5082d4db78ee2d24f72b25eb75537f2e19c49f04a595378d1ae8814d6f2fbf28 + commands: + - npm install + - npm test + +secrets: + # Implicit secret definition. + - name: vault_token + + - origin: + name: private vault + image: target/secret-vault:v0.1.0 + secrets: [ vault_token ] + parameters: + addr: vault.example.com + auth_method: token + username: octocat + items: + - source: secret/docker + path: docker diff --git a/lib/modules/manager/velaci/__fixtures__/.vela-services.yml b/lib/modules/manager/velaci/__fixtures__/.vela-services.yml new file mode 100644 index 0000000000000000000000000000000000000000..4f04272d5dbdccb26d2d2ef9199ea6120693df99 --- /dev/null +++ b/lib/modules/manager/velaci/__fixtures__/.vela-services.yml @@ -0,0 +1,15 @@ +version: "1" + +services: + - name: mysql + image: mysql:5.7.24 + + - name: redis + image: redis:alpine + +steps: + - name: node + image: amd64/node:10.0.0@sha256:5082d4db78ee2d24f72b25eb75537f2e19c49f04a595378d1ae8814d6f2fbf28 + commands: + - npm install + - npm test diff --git a/lib/modules/manager/velaci/__fixtures__/.vela-stages.yaml b/lib/modules/manager/velaci/__fixtures__/.vela-stages.yaml new file mode 100644 index 0000000000000000000000000000000000000000..24e084dc8ecce97851bad0c371c88210e01fe711 --- /dev/null +++ b/lib/modules/manager/velaci/__fixtures__/.vela-stages.yaml @@ -0,0 +1,21 @@ +version: "1" + +stages: + go: + steps: + - name: go + image: golang:1.13 + environment: + CGO_ENABLED: '0' + GOOS: linux + commands: + - go get ./... + - go test ./... + node: + steps: + - name: node + image: amd64/node:10.0.0@sha256:5082d4db78ee2d24f72b25eb75537f2e19c49f04a595378d1ae8814d6f2fbf28 + commands: + - npm install + - npm test + diff --git a/lib/modules/manager/velaci/__fixtures__/.vela-steps.yml b/lib/modules/manager/velaci/__fixtures__/.vela-steps.yml new file mode 100644 index 0000000000000000000000000000000000000000..75546f7c6a32094672694dc08c9fd6e7d3fdaa4b --- /dev/null +++ b/lib/modules/manager/velaci/__fixtures__/.vela-steps.yml @@ -0,0 +1,17 @@ +version: "1" + +steps: + - name: go + image: golang:1.13 + environment: + CGO_ENABLED: '0' + GOOS: linux + commands: + - go get ./... + - go test ./... + + - name: node + image: amd64/node:10.0.0@sha256:5082d4db78ee2d24f72b25eb75537f2e19c49f04a595378d1ae8814d6f2fbf28 + commands: + - npm install + - npm test diff --git a/lib/modules/manager/velaci/extract.spec.ts b/lib/modules/manager/velaci/extract.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..50be1f0ad08fdd7c72d98b2de5db1952549e3d05 --- /dev/null +++ b/lib/modules/manager/velaci/extract.spec.ts @@ -0,0 +1,76 @@ +import { Fixtures } from '../../../../test/fixtures'; +import { extractPackageFile } from '.'; + +describe('modules/manager/velaci/extract', () => { + describe('extractPackageFile()', () => { + it('should handle invalid YAML', () => { + const res = extractPackageFile('foo: bar: invalid'); + expect(res).toBeNull(); + }); + + it('should handle YAML without pipeline/images', () => { + const res = extractPackageFile('no: pipeline'); + expect(res).toBeNull(); + }); + + it('extracts multiple step pipeline image lines', () => { + const res = extractPackageFile(Fixtures.get('.vela-steps.yml')); + expect(res.deps).toMatchObject([ + { + currentValue: '1.13', + depName: 'golang', + }, + { + currentValue: '10.0.0', + depName: 'node', + }, + ]); + }); + + it('extracts multiple services pipeline image lines', () => { + const res = extractPackageFile(Fixtures.get('.vela-services.yml')); + expect(res.deps).toMatchObject([ + { + currentValue: '10.0.0', + depName: 'node', + }, + { + currentValue: '5.7.24', + depName: 'mysql', + }, + { + currentValue: 'alpine', + depName: 'redis', + }, + ]); + }); + + it('extracts multiple stages pipeline image lines', () => { + const res = extractPackageFile(Fixtures.get('.vela-stages.yaml')); + expect(res.deps).toMatchObject([ + { + currentValue: '1.13', + depName: 'golang', + }, + { + currentValue: '10.0.0', + depName: 'node', + }, + ]); + }); + + it('extracts multiple secrets pipeline image lines', () => { + const res = extractPackageFile(Fixtures.get('.vela-secrets.yml')); + expect(res.deps).toMatchObject([ + { + currentValue: '10.0.0', + depName: 'node', + }, + { + currentValue: 'v0.1.0', + depName: 'target/secret-vault', + }, + ]); + }); + }); +}); diff --git a/lib/modules/manager/velaci/extract.ts b/lib/modules/manager/velaci/extract.ts new file mode 100644 index 0000000000000000000000000000000000000000..05fa1279b1853e549dbfbaef20509bb023226a84 --- /dev/null +++ b/lib/modules/manager/velaci/extract.ts @@ -0,0 +1,56 @@ +import { load } from 'js-yaml'; +import { logger } from '../../../logger'; +import { getDep } from '../dockerfile/extract'; +import type { PackageDependency, PackageFile } from '../types'; +import type { VelaPipelineConfiguration } from './types'; + +export function extractPackageFile(file: string): PackageFile | null { + let doc: VelaPipelineConfiguration | undefined; + + try { + doc = load(file, { json: true }) as VelaPipelineConfiguration; + } catch (err) { + logger.debug({ err, file }, 'Failed to parse Vela file.'); + return null; + } + + const deps: PackageDependency[] = []; + + // iterate over steps + for (const step of doc.steps ?? []) { + const dep = getDep(step.image); + + deps.push(dep); + } + + // iterate over services + for (const service of doc.services ?? []) { + const dep = getDep(service.image); + + deps.push(dep); + } + + // iterate over stages + for (const stage of Object.values(doc.stages ?? {})) { + for (const step of stage.steps ?? []) { + const dep = getDep(step.image); + + deps.push(dep); + } + } + + // check secrets + for (const secret of Object.values(doc.secrets ?? {})) { + if (secret.origin) { + const dep = getDep(secret.origin.image); + + deps.push(dep); + } + } + + if (!deps.length) { + return null; + } + + return { deps }; +} diff --git a/lib/modules/manager/velaci/index.ts b/lib/modules/manager/velaci/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..4b082311045748127ccabb62fb15068188eef991 --- /dev/null +++ b/lib/modules/manager/velaci/index.ts @@ -0,0 +1,9 @@ +import { DockerDatasource } from '../../datasource/docker'; + +export { extractPackageFile } from './extract'; + +export const defaultConfig = { + fileMatch: ['(^|/).vela.ya?ml$'], +}; + +export const supportedDatasources = [DockerDatasource.id]; diff --git a/lib/modules/manager/velaci/readme.md b/lib/modules/manager/velaci/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..3826cd91769b46dd8dc8a3206f0483d51956db53 --- /dev/null +++ b/lib/modules/manager/velaci/readme.md @@ -0,0 +1,3 @@ +Extracts Docker-type dependencies from VelaCI config files. + +If you need to change the versioning format, read the [versioning](https://docs.renovatebot.com/modules/versioning/) documentation to learn more. diff --git a/lib/modules/manager/velaci/types.ts b/lib/modules/manager/velaci/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..d1cf8e92368e119f32f669355abb2df7c6a827e0 --- /dev/null +++ b/lib/modules/manager/velaci/types.ts @@ -0,0 +1,25 @@ +/** + * VelaPipelineConfiguration + * + * Spec: https://github.com/go-vela/types/releases/latest/download/schema.json + * Docs: https://go-vela.github.io/docs/reference/yaml/ + */ +export interface VelaPipelineConfiguration { + secrets?: { + origin?: ObjectWithImageProp; + }[]; + + services?: ObjectWithImageProp[]; + + stages?: Record<string, Stage>; + + steps?: ObjectWithImageProp[]; +} + +export interface ObjectWithImageProp { + image: string; +} + +export interface Stage { + steps: ObjectWithImageProp[]; +}