Skip to content

Commit

Permalink
feat: add mount-docker-socket option (#749)
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Kriese <[email protected]>
  • Loading branch information
mtardy and viceice authored May 26, 2023
1 parent da15a1b commit 7c65b94
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ GitHub Action to run Renovate self-hosted.
- [Options](#options)
- [`configurationFile`](#configurationfile)
- [`env-regex`](#env-regex)
- [`mount-docker-socket`](#mount-docker-socket)
- [`token`](#token)
- [`renovate-image`](#renovate-image)
- [`renovate-version`](#renovate-version)
Expand Down Expand Up @@ -59,6 +60,13 @@ If you want to use this with just the single configuration file, make sure to in
Allows to configure the regex to define which environment variables are passed to the renovate container.
See [Passing other environment variables](#passing-other-environment-variables) section for more details.

## `mount-docker-socket`

Default to `false`. If set to `true` the action will mount the Docker socket
inside the renovate container so that the commands can use Docker. Can be useful
for `postUpgradeTasks`'s commands. Also add the user inside the renovate
container to the docker group for socket permissions.

### `token`

[Generate a personal access token](https://github.com/settings/tokens), with the `repo:public_repo` scope for only public repositories or the `repo` scope for public and private repositories, and add it to _Secrets_ (repository settings) as `RENOVATE_TOKEN`. You can also create a token without a specific scope, which gives read-only access to public repositories, for testing. This token is only used by Renovate, see the [token configuration](https://docs.renovatebot.com/self-hosted-configuration/#token), and gives it access to the repositories. The name of the secret can be anything as long as it matches the argument given to the `token` option.
Expand Down
6 changes: 6 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ inputs:
Renovate docker image name.
Defaults to `ghcr.io/renovate/renovate`.
required: false
mount-docker-socket:
description: |
Mount the Docker socket inside the renovate container so that the commands
can use Docker. Also add the user inside the renovate container to the
docker group for socket permissions.
required: false
runs:
using: node16
main: dist/index.js
4 changes: 4 additions & 0 deletions src/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ class Input {
return !!version && version !== '' ? version : null;
}

mountDockerSocket(): boolean {
return core.getInput('mount-docker-socket') === 'true';
}

/**
* Convert to environment variables.
*
Expand Down
34 changes: 34 additions & 0 deletions src/renovate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import fs from 'fs';
import path from 'path';

class Renovate {
static dockerGroupRegex = /^docker:x:(?<groupId>[1-9][0-9]*):/m;
private configFileMountDir = '/github-action';

private docker: Docker;
Expand All @@ -31,6 +32,13 @@ class Renovate {
);
}

if (this.input.mountDockerSocket()) {
dockerArguments.push(
'--volume /var/run/docker.sock:/var/run/docker.sock',
`--group-add ${this.getDockerGroupId()}`
);
}

dockerArguments.push('--volume /tmp:/tmp', '--rm', this.docker.image());

const command = `docker run ${dockerArguments.join(' ')}`;
Expand All @@ -41,6 +49,32 @@ class Renovate {
}
}

/**
* Fetch the host docker group of the GitHub Action runner.
*
* The Renovate container needs access to this group in order to have the
* required permissions on the Docker socket.
*/
private getDockerGroupId(): string {
const groupFile = '/etc/group';
const groups = fs.readFileSync(groupFile, {
encoding: 'utf-8',
});

/**
* The group file has `groupname:group-password:GID:username-list` as
* structure and we're interested in the `GID` (the group ID).
*
* Source: https://www.thegeekdiary.com/etcgroup-file-explained/
*/
const match = Renovate.dockerGroupRegex.exec(groups);
if (match?.groups?.groupId === undefined) {
throw new Error(`Could not find group docker in ${groupFile}`);
}

return match.groups.groupId;
}

private validateArguments(): void {
if (/\s/.test(this.input.token.value)) {
throw new Error('Token MUST NOT contain whitespace');
Expand Down

0 comments on commit 7c65b94

Please sign in to comment.