Skip to content
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: 6 additions & 2 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105012,15 +105012,15 @@ function buildReusableUserData({ runnerVersion, owner, repo, label, githubRegist
'#!/bin/bash',
'set -euo pipefail',
...PHONE_HOME_HELPERS,
'GH_RUNNER_STEP=configuring',
'trap \'gh_runner_phone_home "failed:${GH_RUNNER_STEP}"\' ERR',
'IMDS_TOKEN=$(curl -fsS -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 120" 2>/dev/null || true)',
'UD=$(curl -fsS -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" "http://169.254.169.254/latest/user-data" 2>/dev/null || true)',
'GH_TOKEN=$(printf \'%s\\n\' "$UD" | sed -n "s/^GH_TOKEN=\'\\(.*\\)\'$/\\1/p" | head -n1)',
'GH_LABEL=$(printf \'%s\\n\' "$UD" | sed -n "s/^GH_LABEL=\'\\(.*\\)\'$/\\1/p" | head -n1)',
'GH_REPO_URL=$(printf \'%s\\n\' "$UD" | sed -n "s#^GH_REPO_URL=\'\\(.*\\)\'$#\\1#p" | head -n1)',
'cd /home/runner/actions-runner',
'rm -f .runner .credentials .credentials_rsaparams',
'GH_RUNNER_STEP=configuring',
'trap \'gh_runner_phone_home "failed:${GH_RUNNER_STEP}"\' ERR',
'gh_runner_phone_home configuring',
'sudo -u runner -H env DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 ./config.sh --url "$GH_REPO_URL" --token "$GH_TOKEN" --labels "$GH_LABEL" --ephemeral --unattended --disableupdate',
'GH_RUNNER_STEP=registered',
Expand Down Expand Up @@ -105070,6 +105070,10 @@ function buildReusableUserData({ runnerVersion, owner, repo, label, githubRegist
'trap - ERR',
"sudo -u runner -H bash <<'RUNNER_DOWNLOAD'",
'set -euo pipefail',
...PHONE_HOME_HELPERS,
'GH_RUNNER_STEP=downloading',
"trap 'gh_runner_phone_home \"failed:${GH_RUNNER_STEP}\"' ERR",
'gh_runner_phone_home downloading',
'cd "$HOME"',
'mkdir -p actions-runner && cd actions-runner',
'if [ ! -x ./run.sh ]; then',
Expand Down
8 changes: 6 additions & 2 deletions src/aws.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,15 +362,15 @@ function buildReusableUserData({ runnerVersion, owner, repo, label, githubRegist
'#!/bin/bash',
'set -euo pipefail',
...PHONE_HOME_HELPERS,
'GH_RUNNER_STEP=configuring',
'trap \'gh_runner_phone_home "failed:${GH_RUNNER_STEP}"\' ERR',
'IMDS_TOKEN=$(curl -fsS -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 120" 2>/dev/null || true)',
'UD=$(curl -fsS -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" "http://169.254.169.254/latest/user-data" 2>/dev/null || true)',
'GH_TOKEN=$(printf \'%s\\n\' "$UD" | sed -n "s/^GH_TOKEN=\'\\(.*\\)\'$/\\1/p" | head -n1)',
'GH_LABEL=$(printf \'%s\\n\' "$UD" | sed -n "s/^GH_LABEL=\'\\(.*\\)\'$/\\1/p" | head -n1)',
'GH_REPO_URL=$(printf \'%s\\n\' "$UD" | sed -n "s#^GH_REPO_URL=\'\\(.*\\)\'$#\\1#p" | head -n1)',
'cd /home/runner/actions-runner',
'rm -f .runner .credentials .credentials_rsaparams',
'GH_RUNNER_STEP=configuring',
'trap \'gh_runner_phone_home "failed:${GH_RUNNER_STEP}"\' ERR',
'gh_runner_phone_home configuring',
'sudo -u runner -H env DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 ./config.sh --url "$GH_REPO_URL" --token "$GH_TOKEN" --labels "$GH_LABEL" --ephemeral --unattended --disableupdate',
'GH_RUNNER_STEP=registered',
Expand Down Expand Up @@ -420,6 +420,10 @@ function buildReusableUserData({ runnerVersion, owner, repo, label, githubRegist
'trap - ERR',
"sudo -u runner -H bash <<'RUNNER_DOWNLOAD'",
'set -euo pipefail',
...PHONE_HOME_HELPERS,
'GH_RUNNER_STEP=downloading',
"trap 'gh_runner_phone_home \"failed:${GH_RUNNER_STEP}\"' ERR",
'gh_runner_phone_home downloading',
'cd "$HOME"',
'mkdir -p actions-runner && cd actions-runner',
'if [ ! -x ./run.sh ]; then',
Expand Down
41 changes: 41 additions & 0 deletions tests/warmpool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,47 @@ describe('getInstanceCycles / setInstanceCycles', () => {
describe('buildUserData — reuse: stop variant', () => {
const args = { runnerVersion: '2.335.1', owner: 'o', repo: 'r', label: 'l', githubRegistrationToken: 'TOK', shaX64: 'x', shaArm64: 'a' };

// Isolates the body of the sudo -u runner RUNNER_DOWNLOAD heredoc from the
// rest of the generated script, so assertions about what runs inside that
// runner-user shell can't be satisfied by matches elsewhere in the script
// (the outer root shell's own preparing trap, or the register script's
// configuring trap).
const extractRunnerDownloadHeredoc = (ud) => {
const startMarker = "sudo -u runner -H bash <<'RUNNER_DOWNLOAD'";
const start = ud.indexOf(startMarker);
expect(start).toBeGreaterThan(-1);
const bodyStart = start + startMarker.length;
const end = ud.indexOf('\nRUNNER_DOWNLOAD', bodyStart);
expect(end).toBeGreaterThan(bodyStart);
return ud.slice(bodyStart, end);
};

test('re-includes PHONE_HOME_HELPERS inside the RUNNER_DOWNLOAD heredoc (regression, #61)', () => {
const ud = aws.buildUserData({ ...args, reuse: 'stop' });
const heredoc = extractRunnerDownloadHeredoc(ud);
// Functions/traps set in the outer (root) shell do not survive the
// `sudo -u runner` boundary — the helpers must be redefined inside this
// heredoc, exactly as the plain-path RUNNER_BOOTSTRAP shell does.
expect(heredoc).toContain('gh_runner_imds() {');
expect(heredoc).toContain('gh_runner_phone_home() {');
expect(heredoc).toContain(`Key=${aws.BOOTSTRAP_TAG_KEY},Value=$1`);
});

test('arms an ERR trap for the downloading phase inside the RUNNER_DOWNLOAD heredoc (regression, #61)', () => {
const ud = aws.buildUserData({ ...args, reuse: 'stop' });
const heredoc = extractRunnerDownloadHeredoc(ud);
const trapLine = "trap 'gh_runner_phone_home \"failed:${GH_RUNNER_STEP}\"' ERR";
// Scoped to this heredoc alone: the outer shell's 'preparing' trap and
// the register script's 'configuring' trap live elsewhere in the script
// and must not be able to satisfy this assertion.
expect(heredoc).toContain(trapLine);
expect(heredoc).toContain('GH_RUNNER_STEP=downloading');
// The step must be (re)tagged, and the trap (re)armed, before any of the
// curl/sha256sum/tar commands that can actually fail inside this shell.
expect(heredoc.indexOf('GH_RUNNER_STEP=downloading')).toBeLessThan(heredoc.indexOf(trapLine));
expect(heredoc.indexOf(trapLine)).toBeLessThan(heredoc.indexOf('curl -fsSLo'));
});

test('installs a per-boot systemd service + IMDS-read re-registration hook', () => {
const ud = aws.buildUserData({ ...args, reuse: 'stop' });
expect(ud).toContain('/opt/gh-runner-register.sh');
Expand Down