Skip to content

Commit

Permalink
Merge branch 'main' into implement-terraform-lock-files
Browse files Browse the repository at this point in the history
  • Loading branch information
viceice authored Jun 17, 2021
2 parents a0d8661 + 55d23ad commit 2542dd1
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 47 deletions.
47 changes: 47 additions & 0 deletions docs/usage/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
45 changes: 45 additions & 0 deletions lib/datasource/docker/common.spec.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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",
}
`);
});
});
});
10 changes: 9 additions & 1 deletion lib/datasource/docker/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
58 changes: 26 additions & 32 deletions lib/util/cache/package/decorator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import is from '@sindresorhus/is';
import { logger } from '../../../logger';
import * as packageCache from '.';

type Handler<T> = (parameters: DecoratorParameters<T>) => Promise<unknown>;
Expand Down Expand Up @@ -90,37 +89,32 @@ export function cache<T>({
ttlMinutes = 30,
}: CacheParameters): Decorator<T> {
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<unknown>(
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<unknown>(
finalNamespace,
finalKey
);

if (cachedResult !== undefined) {
return cachedResult;
}

const result = await callback();

await packageCache.set(finalNamespace, finalKey, result, ttlMinutes);
return result;
});
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,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",
Expand Down
24 changes: 11 additions & 13 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1896,13 +1896,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/[email protected]":
version "4.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.26.1.tgz#b9c7313321cb837e2bf8bebe7acc2220659e67d3"
Expand Down Expand Up @@ -5424,14 +5417,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:
Expand Down Expand Up @@ -9375,11 +9368,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"
Expand Down

0 comments on commit 2542dd1

Please sign in to comment.