Skip to content

Commit

Permalink
Merge pull request myoung34#140 from joeyparrish/ephemeral
Browse files Browse the repository at this point in the history
feat: Ephemeral mode
  • Loading branch information
myoung34 authored Sep 10, 2021
2 parents fdd8a7d + 53089f4 commit b11f137
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 2 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ RUN chmod +x /actions-runner/install_actions.sh \
&& /actions-runner/install_actions.sh ${GH_RUNNER_VERSION} ${TARGETPLATFORM} \
&& rm /actions-runner/install_actions.sh

COPY token.sh entrypoint.sh /
RUN chmod +x /token.sh /entrypoint.sh
COPY token.sh entrypoint.sh ephemeral-runner.sh /
RUN chmod +x /token.sh /entrypoint.sh /ephemeral-runner.sh

ENTRYPOINT ["/entrypoint.sh"]
CMD ["/actions-runner/bin/runsvc.sh"]
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,56 @@ docker run -d --restart always --name github-runner \
-v /tmp/github-runner-your-repo:/tmp/github-runner-your-repo \
myoung34/github-runner:latest
```

## Ephemeral mode

GitHub's hosted runners are completely ephemeral. You can remove all its data without breaking all future jobs.

To achieve the same resilience in a self-hosted runner:
1. override the command for your runner with `/ephemeral-runner.sh` (which will terminate after one job executes)
2. don't mount a local folder into `RUNNER_WORKDIR` (to ensure no filesystem persistence)
3. run the container with `--rm` (to delete it after termination)
4. wrap the container execution in a system service that restarts (to start a fresh container after each job)

Here's an example service definition for systemd:

```
# Install with:
# sudo install -m 644 ephemeral-github-actions-runner.service /etc/systemd/system/
# sudo systemctl daemon-reload
# sudo systemctl enable ephemeral-github-actions-runner
# Run with:
# sudo systemctl start ephemeral-github-actions-runner
# Stop with:
# sudo systemctl stop ephemeral-github-actions-runner
# See live logs with:
# journalctl -f -u ephemeral-github-actions-runner.service --no-hostname --no-tail
[Unit]
Description=Ephemeral GitHub Actions Runner Container
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
Restart=always
ExecStartPre=-/usr/bin/docker stop %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStartPre=-/usr/bin/docker pull myoung34/github-runner:latest
ExecStart=/usr/bin/docker run --rm --env-file /etc/ephemeral-github-actions-runner.env --name %n myoung34/ephemeral-github-actions-runner:latest /ephemeral-runner.sh
[Install]
WantedBy=multi-user.target
```

And an example of the corresponding env file that the service reads from:

```
# Install with:
# sudo install -m 600 ephemeral-github-actions-runner.env /etc/
REPO_URL=https://github.com/your-org/your-repo
RUNNER_NAME=your-runner-name-here
ACCESS_TOKEN=foo-access-token
RUNNER_WORKDIR=/tmp/runner/work
LABELS=any-custom-labels-go-here
```
36 changes: 36 additions & 0 deletions ephemeral-runner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash

echo "*** Starting ephemeral runner. ***"
/actions-runner/run.sh --once
rv=$?

# See exit code constants in the runner source here:
# https://github.com/actions/runner/blob/be96323/src/Runner.Common/Constants.cs#L135
if [[ $rv == 4 ]]; then
# The runner software was updated.
echo "*** Software update detected. ***"

echo "*** Waiting for update to complete. ***"
# Hard-coded sleep. Without some delay, the update is still in progress in
# the background, leading to failures when we re-launch.
sleep 10

# Now add an adaptive delay, where we loop and check if the Runner is usable
# yet. As soon as it is, break.
for i in $(seq 10); do
if /actions-runner/bin/Runner.Listener --version &>/dev/null; then
break
fi

echo "*** Update still in progress... ***"
sleep 5
done

# Now re-launch the script.
echo "*** Re-launching runner. ***"
exec "$0"
fi

# For any other return value, let the script and the Docker container terminate.
echo "*** Exit code $rv ***"
exit $rv

0 comments on commit b11f137

Please sign in to comment.