From 2d2a599b91216eb24322986ca00b8cab22935a7d Mon Sep 17 00:00:00 2001 From: Oleg Krivtsov Date: Wed, 20 Oct 2021 20:59:33 +0700 Subject: [PATCH] feat(bitbucket-pipelines): support bitbucket pipe renovations (#11859) --- lib/manager/api.ts | 2 + .../__fixtures__/bitbucket-pipelines.yaml | 24 ++++++++ .../bitbucket-pipelines/extract.spec.ts | 45 ++++++++++++++ lib/manager/bitbucket-pipelines/extract.ts | 61 +++++++++++++++++++ lib/manager/bitbucket-pipelines/index.ts | 7 +++ lib/manager/bitbucket-pipelines/readme.md | 3 + 6 files changed, 142 insertions(+) create mode 100644 lib/manager/bitbucket-pipelines/__fixtures__/bitbucket-pipelines.yaml create mode 100644 lib/manager/bitbucket-pipelines/extract.spec.ts create mode 100644 lib/manager/bitbucket-pipelines/extract.ts create mode 100644 lib/manager/bitbucket-pipelines/index.ts create mode 100644 lib/manager/bitbucket-pipelines/readme.md diff --git a/lib/manager/api.ts b/lib/manager/api.ts index 6d0925b2e92e33..71970dc081fce3 100644 --- a/lib/manager/api.ts +++ b/lib/manager/api.ts @@ -5,6 +5,7 @@ import * as azurePipelines from './azure-pipelines'; import * as batect from './batect'; import * as batectWrapper from './batect-wrapper'; import * as bazel from './bazel'; +import * as bitbucketPipelines from './bitbucket-pipelines'; import * as buildkite from './buildkite'; import * as bundler from './bundler'; import * as cake from './cake'; @@ -72,6 +73,7 @@ api.set('azure-pipelines', azurePipelines); api.set('batect', batect); api.set('batect-wrapper', batectWrapper); api.set('bazel', bazel); +api.set('bitbucket-pipelines', bitbucketPipelines); api.set('buildkite', buildkite); api.set('bundler', bundler); api.set('cake', cake); diff --git a/lib/manager/bitbucket-pipelines/__fixtures__/bitbucket-pipelines.yaml b/lib/manager/bitbucket-pipelines/__fixtures__/bitbucket-pipelines.yaml new file mode 100644 index 00000000000000..ec44288c93764c --- /dev/null +++ b/lib/manager/bitbucket-pipelines/__fixtures__/bitbucket-pipelines.yaml @@ -0,0 +1,24 @@ +image: node:10.15.1 + +pipelines: + default: + - step: + name: Build and Test + image: node:10.15.2 + script: + - npm install + - npm test + - npm run dist + artifacts: + - dist/** + - step: + name: Deploy + deployment: production + script: + - pipe: atlassian/aws-s3-deploy:0.2.1 + variables: + AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY + AWS_DEFAULT_REGION: "us-east-1" + S3_BUCKET: "my-bucket-name" + LOCAL_PATH: "dist" \ No newline at end of file diff --git a/lib/manager/bitbucket-pipelines/extract.spec.ts b/lib/manager/bitbucket-pipelines/extract.spec.ts new file mode 100644 index 00000000000000..578081826d4c61 --- /dev/null +++ b/lib/manager/bitbucket-pipelines/extract.spec.ts @@ -0,0 +1,45 @@ +import { loadFixture } from '../../../test/util'; +import { extractPackageFile } from './extract'; + +const bitbucketPipelinesYAML = loadFixture('bitbucket-pipelines.yaml'); + +describe('manager/bitbucket-pipelines/extract', () => { + describe('extractPackageFile()', () => { + it('returns null for empty', () => { + expect(extractPackageFile('nothing here')).toBeNull(); + }); + + it('extracts dependencies', () => { + const res = extractPackageFile(bitbucketPipelinesYAML); + expect(res.deps).toMatchInlineSnapshot(` +Array [ + Object { + "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", + "currentDigest": undefined, + "currentValue": "10.15.1", + "datasource": "docker", + "depName": "node", + "depType": "docker", + "replaceString": "node:10.15.1", + }, + Object { + "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", + "currentDigest": undefined, + "currentValue": "10.15.2", + "datasource": "docker", + "depName": "node", + "depType": "docker", + "replaceString": "node:10.15.2", + }, + Object { + "currentValue": "0.2.1", + "datasource": "bitbucket-tags", + "depName": "atlassian/aws-s3-deploy", + "depType": "bitbucket-tags", + }, +] +`); + expect(res.deps).toHaveLength(3); + }); + }); +}); diff --git a/lib/manager/bitbucket-pipelines/extract.ts b/lib/manager/bitbucket-pipelines/extract.ts new file mode 100644 index 00000000000000..cdefc542d7626c --- /dev/null +++ b/lib/manager/bitbucket-pipelines/extract.ts @@ -0,0 +1,61 @@ +import { logger } from '../../logger'; +import { regEx } from '../../util/regex'; +import { getDep } from '../dockerfile/extract'; +import type { PackageDependency, PackageFile } from '../types'; + +const pipeRegex = regEx(`^\\s*-\\s?pipe:\\s*'?"?([^\\s'"]+)'?"?\\s*$`); +const dockerImageRegex = regEx(`^\\s*-?\\s?image:\\s*'?"?([^\\s'"]+)'?"?\\s*$`); + +export function extractPackageFile(content: string): PackageFile | null { + const deps: PackageDependency[] = []; + + try { + const lines = content.split('\n'); + for (const line of lines) { + const pipeMatch = pipeRegex.exec(line); + if (pipeMatch) { + const pipe = pipeMatch[1]; + const [depName, currentValue] = pipe.split(':'); + + const dep: PackageDependency = { + depName, + currentValue, + datasource: 'bitbucket-tags', + }; + + logger.trace( + { + depName: dep.depName, + currentValue: dep.currentValue, + }, + 'Bitbucket pipe' + ); + dep.depType = 'bitbucket-tags'; + deps.push(dep); + } + + const dockerImageMatch = dockerImageRegex.exec(line); + if (dockerImageMatch) { + const currentFrom = dockerImageMatch[1]; + const dep = getDep(currentFrom); + + logger.trace( + { + depName: dep.depName, + currentValue: dep.currentValue, + currentDigest: dep.currentDigest, + }, + 'Docker image' + ); + dep.depType = 'docker'; + deps.push(dep); + } + } + } catch (err) /* istanbul ignore next */ { + logger.warn({ err }, 'Error extracting Bitbucket Pipes dependencies'); + } + if (!deps.length) { + return null; + } + return { deps }; +} diff --git a/lib/manager/bitbucket-pipelines/index.ts b/lib/manager/bitbucket-pipelines/index.ts new file mode 100644 index 00000000000000..6a0b52dd7f353c --- /dev/null +++ b/lib/manager/bitbucket-pipelines/index.ts @@ -0,0 +1,7 @@ +import { extractPackageFile } from './extract'; + +export { extractPackageFile }; + +export const defaultConfig = { + fileMatch: ['(^|/)\\.bitbucket-pipelines\\.yaml$'], +}; diff --git a/lib/manager/bitbucket-pipelines/readme.md b/lib/manager/bitbucket-pipelines/readme.md new file mode 100644 index 00000000000000..1926b90deee40c --- /dev/null +++ b/lib/manager/bitbucket-pipelines/readme.md @@ -0,0 +1,3 @@ +Extracts dependencies from Bitbucket Pipelines config files. + +If you need to change the versioning format, read the [versioning](https://docs.renovatebot.com/modules/versioning/) documentation to learn more.