feat: circleci orb support (#2955)

Closes #2950
This commit is contained in:
Rhys Arkins 2018-12-16 14:32:11 +01:00 committed by GitHub
parent 83b4bead48
commit 7d4cd7ca60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 594 additions and 33 deletions

View file

@ -1,5 +1,6 @@
const { parse } = require('../util/purl'); const { parse } = require('../util/purl');
const orb = require('./orb');
const docker = require('./docker'); const docker = require('./docker');
const github = require('./github'); const github = require('./github');
const go = require('./go'); const go = require('./go');
@ -10,6 +11,7 @@ const pypi = require('./pypi');
const terraform = require('./terraform'); const terraform = require('./terraform');
const datasources = { const datasources = {
orb,
docker, docker,
github, github,
go, go,
@ -53,6 +55,10 @@ const manualChangelogUrls = {
// Use this object to define manual source URLs for packages // Use this object to define manual source URLs for packages
// Only necessary if the datasource is unable to locate the source URL itself // Only necessary if the datasource is unable to locate the source URL itself
const manualSourceUrls = { const manualSourceUrls = {
orb: {
'hutson/library-release-workflows':
'https://github.com/hyper-expanse/library-release-workflows',
},
docker: { docker: {
node: 'https://github.com/nodejs/node', node: 'https://github.com/nodejs/node',
}, },

69
lib/datasource/orb.js Normal file
View file

@ -0,0 +1,69 @@
const got = require('got');
const { isVersion, sortVersions } = require('../versioning/semver');
module.exports = {
getPkgReleases,
};
/*
* orb.getPkgReleases
*
* This function will fetch an orb from CircleCI and return all semver versions.
*/
async function getPkgReleases(purl) {
const { fullname: dependency } = purl;
logger.debug({ dependency }, 'orb.getPkgReleases()');
const cacheNamespace = 'orb';
const cacheKey = dependency;
const cachedResult = await renovateCache.get(cacheNamespace, cacheKey);
// istanbul ignore if
if (cachedResult) {
return cachedResult;
}
const url = 'https://circleci.com/graphql-unstable';
const body = {
query: `{orb(name:"${dependency}"){name, homeUrl, versions {version, createdAt}}}`,
variables: {},
};
try {
const res = (await got.post(url, {
body,
json: true,
retry: 5,
})).body.data.orb;
// Simplify response before caching and returning
const dep = {
name: dependency,
versions: {},
};
if (res.homeUrl && res.homeUrl.length) {
dep.homepage = res.homeUrl;
}
dep.homepage =
dep.homepage || `https://circleci.com/orbs/registry/orb/${dependency}`;
dep.releases = res.versions.map(v => v.version);
dep.releases = dep.releases.filter(v => isVersion(v));
dep.releases = dep.releases.sort(sortVersions);
dep.releases = dep.releases.map(version => ({
version,
}));
logger.trace({ dep }, 'dep');
const cacheMinutes = 30;
await renovateCache.set(cacheNamespace, cacheKey, dep, cacheMinutes);
return dep;
} catch (err) /* istanbul ignore next */ {
if (err.statusCode === 404 || err.code === 'ENOTFOUND') {
logger.info({ dependency }, `CircleCI Orb lookup failure: not found`);
logger.debug({
err,
});
return null;
}
logger.warn(
{ err, dependency },
'CircleCI Orb lookup failure: Unknown error'
);
return null;
}
}

View file

@ -5,10 +5,40 @@ module.exports = {
}; };
function extractPackageFile(content) { function extractPackageFile(content) {
logger.debug('circleci.extractPackageFile()');
const deps = []; const deps = [];
let lineNumber = 0; try {
for (const line of content.split('\n')) { const lines = content.split('\n');
for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {
const line = lines[lineNumber];
const orbs = line.match(/^\s*orbs:\s*$/);
if (orbs) {
logger.trace(`Matched orbs on line ${lineNumber}`);
let foundOrb;
do {
foundOrb = false;
const orbLine = lines[lineNumber + 1];
logger.trace(`orbLine: "${orbLine}"`);
const orbMatch = orbLine.match(/^\s+([^:]+):\s(.+)$/);
if (orbMatch) {
logger.trace('orbMatch');
foundOrb = true;
lineNumber += 1;
const depName = orbMatch[1];
const [orbName, currentValue] = orbMatch[2].split('@');
const dep = {
depType: 'orb',
depName,
currentValue,
lineNumber,
purl: 'pkg:orb/' + orbName,
commitMessageTopic: '{{{depName}}} orb',
versionScheme: 'semver',
rangeStrategy: 'pin',
};
deps.push(dep);
}
} while (foundOrb);
}
const match = line.match(/^\s*- image:\s*'?"?([^\s'"]+)'?"?\s*$/); const match = line.match(/^\s*- image:\s*'?"?([^\s'"]+)'?"?\s*$/);
if (match) { if (match) {
const currentFrom = match[1]; const currentFrom = match[1];
@ -22,10 +52,16 @@ function extractPackageFile(content) {
}, },
'CircleCI docker image' 'CircleCI docker image'
); );
dep.depType = 'docker';
dep.lineNumber = lineNumber; dep.lineNumber = lineNumber;
deps.push(dep); deps.push(dep);
} }
lineNumber += 1; }
} catch (err) /* istanbul ignore next */ {
logger.error(
{ err, message: err.message },
'Error extracting buildkite plugins'
);
} }
if (!deps.length) { if (!deps.length) {
return null; return null;

View file

@ -6,10 +6,11 @@ module.exports = {
function updateDependency(fileContent, upgrade) { function updateDependency(fileContent, upgrade) {
try { try {
const newFrom = getNewFrom(upgrade);
logger.debug(`circleci.updateDependency(): ${newFrom}`);
const lines = fileContent.split('\n'); const lines = fileContent.split('\n');
const lineToChange = lines[upgrade.lineNumber]; const lineToChange = lines[upgrade.lineNumber];
if (upgrade.depType === 'docker') {
const newFrom = getNewFrom(upgrade);
logger.debug(`circleci.updateDependency(): ${newFrom}`);
const imageLine = new RegExp(/^(\s*- image:\s*'?"?)[^\s'"]+('?"?\s*)$/); const imageLine = new RegExp(/^(\s*- image:\s*'?"?)[^\s'"]+('?"?\s*)$/);
if (!lineToChange.match(imageLine)) { if (!lineToChange.match(imageLine)) {
logger.debug('No image line found'); logger.debug('No image line found');
@ -22,6 +23,23 @@ function updateDependency(fileContent, upgrade) {
} }
lines[upgrade.lineNumber] = newLine; lines[upgrade.lineNumber] = newLine;
return lines.join('\n'); return lines.join('\n');
}
if (upgrade.depType === 'orb') {
const orbLine = new RegExp(`^(\\s+${upgrade.depName}:\\s[^@]+@).+$`);
if (!lineToChange.match(orbLine)) {
logger.debug('No image line found');
return null;
}
const newLine = lineToChange.replace(orbLine, `$1${upgrade.newValue}`);
if (newLine === lineToChange) {
logger.debug('No changes necessary');
return fileContent;
}
lines[upgrade.lineNumber] = newLine;
return lines.join('\n');
}
logger.error('Unknown circleci depType');
return null;
} catch (err) { } catch (err) {
logger.info({ err }, 'Error setting new CircleCI image value'); logger.info({ err }, 'Error setting new CircleCI image value');
return null; return null;

View file

@ -0,0 +1,98 @@
version: 2.1
orbs:
release-workflows: hutson/library-release-workflows@4.1.0
no-version: abc/def
volatile: zzz/zzz@volatile
test_plan: &test_plan
steps:
- checkout
- run: pip install --no-cache-dir pipenv==2018.11.26
- run: pipenv install --dev --python python
- run: pipenv run tox
# TODO: Upload binary distributable to Circle CI using the `Artifact` feature
jobs:
python_3_4_test_plan:
<<: [*test_plan]
docker:
- image: python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077
environment:
TOXENV: py34
python_3_5_test_plan:
<<: [*test_plan]
docker:
- image: python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077
environment:
TOXENV: py35
python_3_6_test_plan:
<<: [*test_plan]
docker:
- image: python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077
environment:
TOXENV: py36
python_3_7_test_plan:
<<: [*test_plan]
docker:
- image: python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077
environment:
TOXENV: py37
pypy_3_6_test_plan:
# TODO: We do not use this job because, at the time of writing, pipenv has not released a version
# with support for pypy - https://github.com/pypa/pipenv/issues/3313
<<: [*test_plan]
docker:
- image: pypy:3-6@sha256:eb6325b75c1c70b4992eaa1bdd29e24e5f14d5324b4714a49f3e67783473214b
environment:
TOXENV: pypy
python_lint_test_plan:
<<: [*test_plan]
docker:
- image: python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077
environment:
TOXENV: lint
workflows:
version: 2
build_and_test:
jobs:
- python_3_4_test_plan
- python_3_5_test_plan
- python_3_6_test_plan
- python_3_7_test_plan
- python_lint_test_plan
- release-workflows/deliver:
# TODO: Upload all binary distributables to the GitHub Release page.
# TODO: Where do we build and upload the source distributable, `sdist`, for upload to the GitHub Release page?
context: github-interaction
filters:
branches:
only: master
requires:
- python_3_4_test_plan
- python_3_5_test_plan
- python_3_6_test_plan
- python_3_7_test_plan
- python_lint_test_plan
deploy:
jobs:
# TODO: Re-use the build artifacts from the `build_and_test` workflow.
- release-workflows/python-deploy:
context: pypi-interaction
# TODO: Share these `filters` once we can publish workflows in Orbs - https://circleci.ideas.aha.io/ideas/CCI-I-615
filters:
tags:
# Match only semantically valid semver tags - Authored by David Fichtmueller - https://github.com/semver/semver/issues/232#issue-48635632
# TODO: Support all PEP440-valid tag names.
only: /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/
branches:
ignore: /.*/

View file

@ -0,0 +1,81 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`datasource/orb getPkgReleases processes homeUrl 1`] = `
Object {
"homepage": "https://google.com",
"name": "hyper-expanse/library-release-workflows",
"releases": Array [
Object {
"version": "3.0.0",
},
Object {
"version": "4.0.0",
},
Object {
"version": "4.1.0",
},
Object {
"version": "4.1.1",
},
Object {
"version": "4.1.2",
},
Object {
"version": "4.1.3",
},
Object {
"version": "4.1.4",
},
Object {
"version": "4.1.5",
},
Object {
"version": "4.1.6",
},
Object {
"version": "4.2.0",
},
],
"versions": Object {},
}
`;
exports[`datasource/orb getPkgReleases processes real data 1`] = `
Object {
"homepage": "https://circleci.com/orbs/registry/orb/hyper-expanse/library-release-workflows",
"name": "hyper-expanse/library-release-workflows",
"releases": Array [
Object {
"version": "3.0.0",
},
Object {
"version": "4.0.0",
},
Object {
"version": "4.1.0",
},
Object {
"version": "4.1.1",
},
Object {
"version": "4.1.2",
},
Object {
"version": "4.1.3",
},
Object {
"version": "4.1.4",
},
Object {
"version": "4.1.5",
},
Object {
"version": "4.1.6",
},
Object {
"version": "4.2.0",
},
],
"versions": Object {},
}
`;

View file

@ -0,0 +1,85 @@
const got = require('got');
const datasource = require('../../lib/datasource');
jest.mock('got');
const orbData = {
data: {
orb: {
name: 'hutson/library-release-workflows',
homeUrl: '',
versions: [
{ version: '4.2.0', createdAt: '2018-12-13T23:19:09.356Z' },
{ version: '4.1.6', createdAt: '2018-12-12T18:56:42.563Z' },
{ version: '4.1.5', createdAt: '2018-12-12T17:13:31.542Z' },
{ version: '4.1.4', createdAt: '2018-12-11T22:13:29.297Z' },
{ version: '4.1.3', createdAt: '2018-12-11T21:40:44.870Z' },
{ version: '4.1.2', createdAt: '2018-12-11T21:28:37.846Z' },
{ version: '4.1.1', createdAt: '2018-12-11T18:24:13.119Z' },
{ version: '4.1.0', createdAt: '2018-12-11T18:14:41.116Z' },
{ version: '4.0.0', createdAt: '2018-12-11T17:41:26.595Z' },
{ version: '3.0.0', createdAt: '2018-12-11T05:28:14.080Z' },
],
},
},
};
describe('datasource/orb', () => {
describe('getPkgReleases', () => {
beforeEach(() => {
jest.clearAllMocks();
return global.renovateCache.rmAll();
});
it('returns null for empty result', async () => {
got.mockReturnValueOnce({ body: {} });
expect(
await datasource.getPkgReleases(
'pkg:orb/hyper-expanse/library-release-workflows'
)
).toBeNull();
});
it('returns null for 404', async () => {
got.mockImplementationOnce(() =>
Promise.reject({
statusCode: 404,
})
);
expect(
await datasource.getPkgReleases(
'pkg:orb/hyper-expanse/library-release-workflows'
)
).toBeNull();
});
it('returns null for unknown error', async () => {
got.mockImplementationOnce(() => {
throw new Error();
});
expect(
await datasource.getPkgReleases(
'pkg:orb/hyper-expanse/library-release-workflows'
)
).toBeNull();
});
it('processes real data', async () => {
got.post.mockReturnValueOnce({
body: orbData,
});
const res = await datasource.getPkgReleases(
'pkg:orb/hyper-expanse/library-release-workflows'
);
expect(res).toMatchSnapshot();
expect(res).not.toBeNull();
});
it('processes homeUrl', async () => {
orbData.data.orb.homeUrl = 'https://google.com';
got.post.mockReturnValueOnce({
body: orbData,
});
const res = await datasource.getPkgReleases(
'pkg:orb/hyper-expanse/library-release-workflows'
);
expect(res).toMatchSnapshot();
expect(res.homepage).toEqual('https://google.com');
});
});
});

View file

@ -10,6 +10,7 @@ Array [
"currentFrom": "node", "currentFrom": "node",
"currentValue": undefined, "currentValue": undefined,
"depName": "node", "depName": "node",
"depType": "docker",
"dockerRegistry": undefined, "dockerRegistry": undefined,
"lineNumber": 12, "lineNumber": 12,
"purl": "pkg:docker/node", "purl": "pkg:docker/node",
@ -22,6 +23,7 @@ Array [
"currentFrom": "node:4", "currentFrom": "node:4",
"currentValue": "4", "currentValue": "4",
"depName": "node", "depName": "node",
"depType": "docker",
"dockerRegistry": undefined, "dockerRegistry": undefined,
"lineNumber": 57, "lineNumber": 57,
"purl": "pkg:docker/node", "purl": "pkg:docker/node",
@ -34,6 +36,7 @@ Array [
"currentFrom": "node:6", "currentFrom": "node:6",
"currentValue": "6", "currentValue": "6",
"depName": "node", "depName": "node",
"depType": "docker",
"dockerRegistry": undefined, "dockerRegistry": undefined,
"lineNumber": 61, "lineNumber": 61,
"purl": "pkg:docker/node", "purl": "pkg:docker/node",
@ -46,9 +49,117 @@ Array [
"currentFrom": "node:8.9.0", "currentFrom": "node:8.9.0",
"currentValue": "8.9.0", "currentValue": "8.9.0",
"depName": "node", "depName": "node",
"depType": "docker",
"dockerRegistry": undefined, "dockerRegistry": undefined,
"lineNumber": 65, "lineNumber": 65,
"purl": "pkg:docker/node", "purl": "pkg:docker/node",
}, },
] ]
`; `;
exports[`lib/manager/circleci/extract extractPackageFile() extracts orbs too 1`] = `
Array [
Object {
"commitMessageTopic": "{{{depName}}} orb",
"currentValue": "4.1.0",
"depName": "release-workflows",
"depType": "orb",
"lineNumber": 3,
"purl": "pkg:orb/hutson/library-release-workflows",
"rangeStrategy": "pin",
"versionScheme": "semver",
},
Object {
"commitMessageTopic": "{{{depName}}} orb",
"currentValue": undefined,
"depName": "no-version",
"depType": "orb",
"lineNumber": 4,
"purl": "pkg:orb/abc/def",
"rangeStrategy": "pin",
"versionScheme": "semver",
},
Object {
"commitMessageTopic": "{{{depName}}} orb",
"currentValue": "volatile",
"depName": "volatile",
"depType": "orb",
"lineNumber": 5,
"purl": "pkg:orb/zzz/zzz",
"rangeStrategy": "pin",
"versionScheme": "semver",
},
Object {
"currentDepTag": "python:3.7",
"currentDepTagDigest": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentValue": "3.7",
"depName": "python",
"depType": "docker",
"dockerRegistry": undefined,
"lineNumber": 20,
"purl": "pkg:docker/python",
},
Object {
"currentDepTag": "python:3.7",
"currentDepTagDigest": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentValue": "3.7",
"depName": "python",
"depType": "docker",
"dockerRegistry": undefined,
"lineNumber": 27,
"purl": "pkg:docker/python",
},
Object {
"currentDepTag": "python:3.7",
"currentDepTagDigest": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentValue": "3.7",
"depName": "python",
"depType": "docker",
"dockerRegistry": undefined,
"lineNumber": 34,
"purl": "pkg:docker/python",
},
Object {
"currentDepTag": "python:3.7",
"currentDepTagDigest": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentValue": "3.7",
"depName": "python",
"depType": "docker",
"dockerRegistry": undefined,
"lineNumber": 41,
"purl": "pkg:docker/python",
},
Object {
"currentDepTag": "pypy:3-6",
"currentDepTagDigest": "pypy:3-6@sha256:eb6325b75c1c70b4992eaa1bdd29e24e5f14d5324b4714a49f3e67783473214b",
"currentDigest": "sha256:eb6325b75c1c70b4992eaa1bdd29e24e5f14d5324b4714a49f3e67783473214b",
"currentFrom": "pypy:3-6@sha256:eb6325b75c1c70b4992eaa1bdd29e24e5f14d5324b4714a49f3e67783473214b",
"currentValue": "3-6",
"depName": "pypy",
"depType": "docker",
"dockerRegistry": undefined,
"lineNumber": 50,
"purl": "pkg:docker/pypy",
},
Object {
"currentDepTag": "python:3.7",
"currentDepTagDigest": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentDigest": "sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentFrom": "python:3.7@sha256:3870d35b962a943df72d948580fc66ceaaee1c4fbd205930f32e0f0760eb1077",
"currentValue": "3.7",
"depName": "python",
"depType": "docker",
"dockerRegistry": undefined,
"lineNumber": 57,
"purl": "pkg:docker/python",
},
]
`;

View file

@ -1,7 +1,8 @@
const fs = require('fs'); const fs = require('fs');
const { extractPackageFile } = require('../../../lib/manager/circleci/extract'); const { extractPackageFile } = require('../../../lib/manager/circleci/extract');
const yamlFile = fs.readFileSync('test/_fixtures/circleci/config.yml', 'utf8'); const file1 = fs.readFileSync('test/_fixtures/circleci/config.yml', 'utf8');
const file2 = fs.readFileSync('test/_fixtures/circleci/config2.yml', 'utf8');
describe('lib/manager/circleci/extract', () => { describe('lib/manager/circleci/extract', () => {
describe('extractPackageFile()', () => { describe('extractPackageFile()', () => {
@ -13,9 +14,14 @@ describe('lib/manager/circleci/extract', () => {
expect(extractPackageFile('nothing here', config)).toBe(null); expect(extractPackageFile('nothing here', config)).toBe(null);
}); });
it('extracts multiple image lines', () => { it('extracts multiple image lines', () => {
const res = extractPackageFile(yamlFile, config); const res = extractPackageFile(file1, config);
expect(res.deps).toMatchSnapshot(); expect(res.deps).toMatchSnapshot();
expect(res.deps).toHaveLength(4); expect(res.deps).toHaveLength(4);
}); });
it('extracts orbs too', () => {
const res = extractPackageFile(file2, config);
expect(res.deps).toMatchSnapshot();
// expect(res.deps).toHaveLength(4);
});
}); });
}); });

View file

@ -2,12 +2,17 @@ const fs = require('fs');
const dcUpdate = require('../../../lib/manager/circleci/update'); const dcUpdate = require('../../../lib/manager/circleci/update');
const yamlFile = fs.readFileSync('test/_fixtures/circleci/config.yml', 'utf8'); const yamlFile = fs.readFileSync('test/_fixtures/circleci/config.yml', 'utf8');
const yamlFile2 = fs.readFileSync(
'test/_fixtures/circleci/config2.yml',
'utf8'
);
describe('manager/circleci/update', () => { describe('manager/circleci/update', () => {
describe('updateDependency', () => { describe('updateDependency', () => {
it('replaces existing value', () => { it('replaces existing value', () => {
const upgrade = { const upgrade = {
lineNumber: 65, lineNumber: 65,
depType: 'docker',
depName: 'node', depName: 'node',
newValue: '8.10.0', newValue: '8.10.0',
newDigest: 'sha256:abcdefghijklmnop', newDigest: 'sha256:abcdefghijklmnop',
@ -19,6 +24,7 @@ describe('manager/circleci/update', () => {
it('returns same', () => { it('returns same', () => {
const upgrade = { const upgrade = {
lineNumber: 12, lineNumber: 12,
depType: 'docker',
depName: 'node', depName: 'node',
}; };
const res = dcUpdate.updateDependency(yamlFile, upgrade); const res = dcUpdate.updateDependency(yamlFile, upgrade);
@ -27,6 +33,7 @@ describe('manager/circleci/update', () => {
it('returns null if mismatch', () => { it('returns null if mismatch', () => {
const upgrade = { const upgrade = {
lineNumber: 17, lineNumber: 17,
depType: 'docker',
depName: 'postgres', depName: 'postgres',
newValue: '9.6.8', newValue: '9.6.8',
newDigest: 'sha256:abcdefghijklmnop', newDigest: 'sha256:abcdefghijklmnop',
@ -38,5 +45,49 @@ describe('manager/circleci/update', () => {
const res = dcUpdate.updateDependency(null, null); const res = dcUpdate.updateDependency(null, null);
expect(res).toBe(null); expect(res).toBe(null);
}); });
it('replaces orbs', () => {
const upgrade = {
currentValue: '4.1.0',
depName: 'release-workflows',
depType: 'orb',
lineNumber: 3,
newValue: '4.2.0',
};
const res = dcUpdate.updateDependency(yamlFile2, upgrade);
expect(res).not.toEqual(yamlFile2);
expect(res.includes(upgrade.newValue)).toBe(true);
});
it('returns same orb', () => {
const upgrade = {
currentValue: '4.0.0',
depName: 'release-workflows',
depType: 'orb',
lineNumber: 3,
newValue: '4.1.0',
};
const res = dcUpdate.updateDependency(yamlFile2, upgrade);
expect(res).toEqual(yamlFile2);
});
it('returns null for orb mismatch', () => {
const upgrade = {
currentValue: '4.1.0',
depName: 'release-workflows',
depType: 'orb',
lineNumber: 2,
newValue: '4.2.0',
};
const res = dcUpdate.updateDependency(yamlFile2, upgrade);
expect(res).toBeNull();
});
it('returns null for unknown depType', () => {
const upgrade = {
currentValue: '4.1.0',
depName: 'release-workflows',
lineNumber: 3,
newValue: '4.2.0',
};
const res = dcUpdate.updateDependency(yamlFile2, upgrade);
expect(res).toBeNull();
});
}); });
}); });