diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76f7c1fdcd..1acd0d6b86 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -94,6 +94,16 @@ jobs: configurationFile: ${{ matrix.configurationFile }} renovate-version: ${{ env.RENOVATE_VERSION }} + - name: Renovate test with entrypoint + uses: ./ + env: + LOG_LEVEL: debug + with: + configurationFile: ${{ matrix.configurationFile }} + renovate-version: ${{ env.RENOVATE_VERSION }} + docker-cmd-file: example/entrypoint.sh + docker-user: root + release: needs: [lint, commitlint, e2e] runs-on: ubuntu-latest diff --git a/README.md b/README.md index be47f46bd7..c15239d26c 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ GitHub Action to run Renovate self-hosted. - [Badges](#badges) - [Options](#options) - [`configurationFile`](#configurationfile) + - [`docker-cmd-file`](#docker-cmd-file) + - [`docker-user`](#docker-user) - [`env-regex`](#env-regex) - [`mount-docker-socket`](#mount-docker-socket) - [`token`](#token) @@ -65,6 +67,53 @@ This disables the requirement of a configuration file for the repository and dis requireConfig: false, ``` +### `docker-cmd-file` + +Specify a command to run when the image start. +By default the image run +`renovate`. +This option is useful to customize the image before running `renovate`. +It must be an existing executable file on the local system. +It will be mounted to the docker container. + +For example you can create a simple script like this one (let's call it +`renovate-entrypoint.sh`). + +```sh +#!/bin/bash + +apt update + +apt install -y build-essential libpq-dev + +runuser -u ubuntu renovate +``` + +Now use this action + +```yml +.... +jobs: + renovate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3.5.3 + - name: Self-hosted Renovate + uses: renovatebot/github-action@v39.0.0 + with: + docker-cmd-file: .github/renovate-entrypoint.sh + docker-user: root + token: ${{ secrets.RENOVATE_TOKEN }} +``` + +### `docker-user` + +Specify a user (or user-id) to run docker command. + +You can use it with [`docker-cmd-file`](#docker-cmd-file) in order to start the +image as root, do some customization and switch back to a unprivileged user. + ### `env-regex` Allows to configure the regex to define which environment variables are passed to the renovate container. diff --git a/action.yml b/action.yml index 325990a578..4306b0b566 100644 --- a/action.yml +++ b/action.yml @@ -36,6 +36,15 @@ inputs: can use Docker. Also add the user inside the renovate container to the docker group for socket permissions. required: false + docker-cmd-file: + description: | + Override docker command. Default command is `renovate` + required: false + docker-user: + description: | + Docker user. Default to an unprivileged user + required: false + runs: using: node16 main: dist/index.js diff --git a/example/entrypoint.sh b/example/entrypoint.sh new file mode 100755 index 0000000000..d7ab098513 --- /dev/null +++ b/example/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +install-apt sl + +exec runuser -u ubuntu renovate diff --git a/src/input.ts b/src/input.ts index f24a6301da..c3e7ce4f09 100644 --- a/src/input.ts +++ b/src/input.ts @@ -73,6 +73,15 @@ class Input { return core.getInput('mount-docker-socket') === 'true'; } + getDockerCmdFile(): string | null { + const cmdFile = core.getInput('docker-cmd-file'); + return !!cmdFile && cmdFile !== '' ? path.resolve(cmdFile) : null; + } + + getDockerUser(): string | null { + return core.getInput('docker-user') || null; + } + /** * Convert to environment variables. * diff --git a/src/renovate.ts b/src/renovate.ts index 9677c85043..1ab0d0af3f 100644 --- a/src/renovate.ts +++ b/src/renovate.ts @@ -39,8 +39,26 @@ class Renovate { ); } + const dockerCmdFile = this.input.getDockerCmdFile(); + let dockerCmd: string | null = null; + if (dockerCmdFile !== null) { + const baseName = path.basename(dockerCmdFile); + const mountPath = `/${baseName}`; + dockerArguments.push(`--volume ${dockerCmdFile}:${mountPath}`); + dockerCmd = mountPath; + } + + const dockerUser = this.input.getDockerUser(); + if (dockerUser !== null) { + dockerArguments.push(`--user ${dockerUser}`); + } + dockerArguments.push('--volume /tmp:/tmp', '--rm', this.docker.image()); + if (dockerCmd !== null) { + dockerArguments.push(dockerCmd); + } + const command = `docker run ${dockerArguments.join(' ')}`; const code = await exec(command);