Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add mount-docker-socket option #749

Merged
merged 4 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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