From 5c21d440555e9bb236ede506e7627e2fa1bd5f4c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 16 Jun 2021 19:05:37 +0200 Subject: [PATCH 1/3] chore(deps): update dependency jest-junit to v12.2.0 (#10470) --- package.json | 2 +- yarn.lock | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 932aa713a1ded5..542f90451298e1 100644 --- a/package.json +++ b/package.json @@ -250,7 +250,7 @@ "jest": "27.0.4", "jest-circus": "27.0.4", "jest-extended": "0.11.5", - "jest-junit": "12.1.0", + "jest-junit": "12.2.0", "jest-mock-extended": "1.0.15", "jest-silent-reporter": "0.5.0", "markdownlint-cli2": "0.1.3", diff --git a/yarn.lock b/yarn.lock index 306b918059594a..06ac8c3a75e5c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1889,13 +1889,6 @@ dependencies: "@types/yargs-parser" "*" -"@types/yauzl@^2.9.1": - version "2.9.1" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af" - integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA== - dependencies: - "@types/node" "*" - "@typescript-eslint/eslint-plugin@4.26.1": version "4.26.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.26.1.tgz#b9c7313321cb837e2bf8bebe7acc2220659e67d3" @@ -5394,14 +5387,14 @@ jest-jasmine2@^27.0.4: pretty-format "^27.0.2" throat "^6.0.1" -jest-junit@12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-12.1.0.tgz#f27173529e7f8f10eac37beb30f8b9bc97e8f3c3" - integrity sha512-Z45INyzEAqTkCHX/hGCPgVFfZP3hQVgI68CgoEwkCiBuxETsPsniq5yPd8oxbMMHtDCpUlxXzoq7jY35dcuLKw== +jest-junit@12.2.0: + version "12.2.0" + resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-12.2.0.tgz#cff7f9516e84f8e30f6bdea04cd84db6b095a376" + integrity sha512-ecGzF3KEQwLbMP5xMO7wqmgmyZlY/5yWDvgE/vFa+/uIT0KsU5nluf0D2fjIlOKB+tb6DiuSSpZuGpsmwbf7Fw== dependencies: mkdirp "^1.0.4" strip-ansi "^5.2.0" - uuid "^3.3.3" + uuid "^8.3.2" xml "^1.0.1" jest-leak-detector@^27.0.2: @@ -9339,11 +9332,16 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -uuid@^3.0.0, uuid@^3.3.2, uuid@^3.3.3: +uuid@^3.0.0, uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" From d4a22c7f3c874a7d451022e4680b66abca196796 Mon Sep 17 00:00:00 2001 From: Niels Basjes Date: Wed, 16 Jun 2021 22:22:32 +0200 Subject: [PATCH 2/3] feat(docker): Support for Bearer token to access the Docker registry (#10400) --- docs/usage/docker.md | 47 ++++++++++++++++++++++++++++ lib/datasource/docker/common.spec.ts | 45 ++++++++++++++++++++++++++ lib/datasource/docker/common.ts | 10 +++++- 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/docs/usage/docker.md b/docs/usage/docker.md index 38a6cec386e3c0..5146194127eac7 100644 --- a/docs/usage/docker.md +++ b/docs/usage/docker.md @@ -206,6 +206,53 @@ module.exports = { }; ``` +#### Google Container Registry + +Assume you are running GitLab CI in the Google Cloud, and you are storing your Docker images in the Google Container Registry (GCR). + +Access to the GCR uses Bearer token based authentication. +This token can be obtained by running `gcloud auth print-access-token`, which requires the Google Cloud SDK to be installed. + +The token expires after 60 minutes so you cannot store it in a variable for subsequent builds (like you can with `RENOVATE_TOKEN`). + +When running Renovate in this context the Google access token must be retrieved and injected into the `hostRules` configuration just before Renovate is started. + +_This documentation gives **a few hints** on **a possible way** to achieve this end result._ + +The basic approach is that you create a custom image and then run Renovate as one of the stages of your project. +To make this run independent of any user you should use a [`Project Access Token`](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html) (with Scopes: `api`, `read_api` and `write_repository`) for the project and use this as the `RENOVATE_TOKEN` variable for Gitlab CI. +See also the [renovate-runner repository on GitLab](https://gitlab.com/renovate-bot/renovate-runner) where `.gitlab-ci.yml` configuration examples can be found. + +To get access to the token a custom Renovate Docker image is needed that includes the Google Cloud SDK. +The Dockerfile to create such an image can look like this: + +```Dockerfile +FROM renovate/renovate:25.40.1 +# Include the "Docker tip" which you can find here https://cloud.google.com/sdk/docs/install +# under "Installation" for "Debian/Ubuntu" +RUN ... +``` + +For Renovate to access the Google Container Registry (GCR) it needs the current Google Access Token. +The configuration fragment to do that looks something like this: + +```js +hostRules: [ + { + matchHost: 'eu.gcr.io', + token: 'MyReallySecretTokenThatExpiresAfter60Minutes', + }, +]; +``` + +One way to provide the short-lived Google Access Token to Renovate is by generating these settings into a `config.js` file from within the `.gitlab-ci.yml` right before starting Renovate: + +```yaml +script: + - 'echo "module.exports = { hostRules: [ { matchHost: ''eu.gcr.io'', token: ''"$(gcloud auth print-access-token)"'' } ] };" > config.js' + - renovate $RENOVATE_EXTRA_FLAGS +``` + #### ChartMuseum Maybe you're running your own ChartMuseum server to host your private Helm Charts. diff --git a/lib/datasource/docker/common.spec.ts b/lib/datasource/docker/common.spec.ts index 7bc9b260cae97b..6c652b798a2846 100644 --- a/lib/datasource/docker/common.spec.ts +++ b/lib/datasource/docker/common.spec.ts @@ -1,3 +1,4 @@ +import * as httpMock from '../../../test/http-mock'; import { getName, mocked } from '../../../test/util'; import * as _hostRules from '../../util/host-rules'; import * as dockerCommon from './common'; @@ -70,4 +71,48 @@ describe(getName(), () => { `); }); }); + describe('getAuthHeaders', () => { + beforeEach(() => { + httpMock + .scope('https://my.local.registry') + .get('/v2/') + .reply(401, '', { 'www-authenticate': 'Authenticate you must' }); + hostRules.hosts.mockReturnValue([]); + }); + + it('returns "authType token" if both provided', async () => { + hostRules.find.mockReturnValue({ + authType: 'some-authType', + token: 'some-token', + }); + + const headers = await dockerCommon.getAuthHeaders( + 'https://my.local.registry', + 'https://my.local.registry/prefix' + ); + + expect(headers).toMatchInlineSnapshot(` + Object { + "authorization": "some-authType some-token", + } + `); + }); + + it('returns "Bearer token" if only token provided', async () => { + hostRules.find.mockReturnValue({ + token: 'some-token', + }); + + const headers = await dockerCommon.getAuthHeaders( + 'https://my.local.registry', + 'https://my.local.registry/prefix' + ); + + expect(headers).toMatchInlineSnapshot(` + Object { + "authorization": "Bearer some-token", + } + `); + }); + }); }); diff --git a/lib/datasource/docker/common.ts b/lib/datasource/docker/common.ts index 14d9d1468e95e7..b90cf21ea0892a 100644 --- a/lib/datasource/docker/common.ts +++ b/lib/datasource/docker/common.ts @@ -81,12 +81,20 @@ export async function getAuthHeaders( 'base64' ); opts.headers = { authorization: `Basic ${auth}` }; + } else if (opts.token) { + const authType = opts.authType ?? 'Bearer'; + logger.trace( + `Using ${authType} token for Docker registry ${registryHost}` + ); + opts.headers = { authorization: `${authType} ${opts.token}` }; + return opts.headers; } delete opts.username; delete opts.password; + delete opts.token; if (authenticateHeader.scheme.toUpperCase() === 'BASIC') { - logger.debug(`Using Basic auth for docker registry ${dockerRepository}`); + logger.trace(`Using Basic auth for docker registry ${registryHost}`); await http.get(apiCheckUrl, opts); return opts.headers; } From 55d23ad3b94501770d17fa497194ae269d90b36f Mon Sep 17 00:00:00 2001 From: Jamie Magee Date: Wed, 16 Jun 2021 22:36:34 -0700 Subject: [PATCH 3/3] fix(cache): don't catch errors (#10449) --- lib/util/cache/package/decorator.ts | 58 +++++++++++++---------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/lib/util/cache/package/decorator.ts b/lib/util/cache/package/decorator.ts index 3a355090a82960..3de488f59c5ccc 100644 --- a/lib/util/cache/package/decorator.ts +++ b/lib/util/cache/package/decorator.ts @@ -1,5 +1,4 @@ import is from '@sindresorhus/is'; -import { logger } from '../../../logger'; import * as packageCache from '.'; type Handler = (parameters: DecoratorParameters) => Promise; @@ -90,37 +89,32 @@ export function cache({ ttlMinutes = 30, }: CacheParameters): Decorator { return decorate(async ({ args, instance, callback }) => { - try { - let finalNamespace: string; - if (is.string(namespace)) { - finalNamespace = namespace; - } else if (is.function_(namespace)) { - finalNamespace = namespace.apply(instance, args); - } - - let finalKey: string; - if (is.string(key)) { - finalKey = key; - } else if (is.function_(key)) { - finalKey = key.apply(instance, args); - } - - const cachedResult = await packageCache.get( - finalNamespace, - finalKey - ); - - if (cachedResult !== undefined) { - return cachedResult; - } - - const result = await callback(); - - await packageCache.set(finalNamespace, finalKey, result, ttlMinutes); - return result; - } catch (err) /* istanbul ignore next */ { - logger.error({ err }, 'cache decorate error'); - throw err; + let finalNamespace: string; + if (is.string(namespace)) { + finalNamespace = namespace; + } else if (is.function_(namespace)) { + finalNamespace = namespace.apply(instance, args); } + + let finalKey: string; + if (is.string(key)) { + finalKey = key; + } else if (is.function_(key)) { + finalKey = key.apply(instance, args); + } + + const cachedResult = await packageCache.get( + finalNamespace, + finalKey + ); + + if (cachedResult !== undefined) { + return cachedResult; + } + + const result = await callback(); + + await packageCache.set(finalNamespace, finalKey, result, ttlMinutes); + return result; }); }