diff --git a/docker/runner-entrypoint.sh b/docker/runner-entrypoint.sh index aec807e..c3b6b43 100755 --- a/docker/runner-entrypoint.sh +++ b/docker/runner-entrypoint.sh @@ -10,6 +10,10 @@ runner_configured="false" runner_exit_code=0 runner_exec_mode="runner" RUNNER_AUDIT_DEREGISTER_EVENT="runner_deregistered" +github_token_for_cleanup="" +github_app_id_for_cleanup="" +github_app_installation_id_for_cleanup="" +github_app_private_key_for_cleanup="" run_runner_bash() { local command="$1" @@ -33,6 +37,35 @@ run_actions_runner() { -u GITHUB_APP_PRIVATE_KEY } +run_runner_job_bash() { + local command="$1" + shift || true + + if [[ "${runner_exec_mode}" == "root" ]]; then + env \ + -u GITHUB_PAT \ + -u GITHUB_TOKEN \ + -u GH_TOKEN \ + -u GITHUB_APP_ID \ + -u GITHUB_APP_INSTALLATION_ID \ + -u GITHUB_APP_PRIVATE_KEY \ + RUNNER_ALLOW_RUNASROOT=1 \ + RUNNER_EXECUTION_MODE="${runner_exec_mode}" \ + "$@" bash -lc "${command}" + return + fi + + env \ + -u GITHUB_PAT \ + -u GITHUB_TOKEN \ + -u GH_TOKEN \ + -u GITHUB_APP_ID \ + -u GITHUB_APP_INSTALLATION_ID \ + -u GITHUB_APP_PRIVATE_KEY \ + RUNNER_EXECUTION_MODE="${runner_exec_mode}" \ + "$@" gosu runner bash -lc "${command}" +} + cleanup_local_state() { rm -f \ "${RUNNER_HOME}/.runner" \ @@ -66,7 +99,23 @@ prepare_runner_home() { } cleanup_runner() { + export GITHUB_PAT="${github_token_for_cleanup}" + export GITHUB_APP_ID="${github_app_id_for_cleanup}" + export GITHUB_APP_INSTALLATION_ID="${github_app_installation_id_for_cleanup}" + export GITHUB_APP_PRIVATE_KEY="${github_app_private_key_for_cleanup}" cleanup_runner_registration "run_runner_bash \"cd '${RUNNER_HOME}' && ./config.sh remove --token \\\"\\\${RUNNER_REMOVE_TOKEN}\\\"\"" + unset GITHUB_PAT GITHUB_APP_ID GITHUB_APP_INSTALLATION_ID GITHUB_APP_PRIVATE_KEY +} + +stash_github_auth_for_cleanup() { + github_token_for_cleanup="${GITHUB_PAT:-}" + github_app_id_for_cleanup="${GITHUB_APP_ID:-}" + github_app_installation_id_for_cleanup="${GITHUB_APP_INSTALLATION_ID:-}" + github_app_private_key_for_cleanup="${GITHUB_APP_PRIVATE_KEY:-}" +} + +scrub_github_auth_env() { + unset GITHUB_PAT GITHUB_TOKEN GH_TOKEN GITHUB_APP_ID GITHUB_APP_INSTALLATION_ID GITHUB_APP_PRIVATE_KEY } prepare_runtime_dirs() { @@ -150,6 +199,7 @@ trap on_exit EXIT trap 'log "termination requested"; RUNNER_AUDIT_DEREGISTER_EVENT="runner_evicted"; export RUNNER_AUDIT_DEREGISTER_EVENT; exit 0' TERM INT require_github_auth +stash_github_auth_for_cleanup require_env GITHUB_ORG require_env RUNNER_NAME require_env RUNNER_LABELS @@ -264,4 +314,6 @@ runner_configured="true" audit_event runner_registered log "starting runner ${RUNNER_NAME}" -run_actions_runner 2>&1 | tee -a "${RUNNER_LOG_DIR}/runner.log" +scrub_github_auth_env +run_runner_job_bash "cd '${RUNNER_HOME}' && exec ./run.sh" \ + 2>&1 | tee -a "${RUNNER_LOG_DIR}/runner.log" diff --git a/scripts/smoke-test.sh b/scripts/smoke-test.sh index 13dbc4c..735ae00 100755 --- a/scripts/smoke-test.sh +++ b/scripts/smoke-test.sh @@ -181,6 +181,8 @@ run_smoke_case() { grep -q -- "--runnergroup synology-private --ephemeral --disableupdate" "${state_dir}/config-invocations.log" grep -q "config path: /tmp/runner-state/runner-home" "${state_dir}/config-context.log" grep -q "run path: /tmp/runner-state/runner-home" "${state_dir}/run-context.log" + grep -q "github auth: unset" "${state_dir}/run-context.log" + grep -q "process github auth: unset" "${state_dir}/run-context.log" grep -q "runner writable home: /tmp/runner-state/runner-home" "${runner_stdout}" grep -q "^job output$" "${state_dir}/logs/runner.log" grep -q "run.sh stub executed" "${state_dir}/run.log" diff --git a/scripts/smoke/actions-runner/run.sh b/scripts/smoke/actions-runner/run.sh index 8a02658..e3032c5 100755 --- a/scripts/smoke/actions-runner/run.sh +++ b/scripts/smoke/actions-runner/run.sh @@ -4,12 +4,14 @@ set -euo pipefail printf '%s run.sh stub executed\n' "$(date -Iseconds)" >> "${RUNNER_STATE_DIR}/run.log" printf 'run path: %s\n' "$(pwd)" >> "${RUNNER_STATE_DIR}/run-context.log" printf 'run mode: %s\n' "${RUNNER_EXECUTION_MODE:-unknown}" >> "${RUNNER_STATE_DIR}/run-context.log" -for credential_name in GITHUB_PAT GITHUB_APP_ID GITHUB_APP_INSTALLATION_ID GITHUB_APP_PRIVATE_KEY; do +for credential_name in GITHUB_PAT GITHUB_TOKEN GH_TOKEN GITHUB_APP_ID GITHUB_APP_INSTALLATION_ID GITHUB_APP_PRIVATE_KEY; do if [[ -n "${!credential_name:-}" ]]; then printf 'leaked credential: %s\n' "${credential_name}" >> "${RUNNER_STATE_DIR}/run-context.log" exit 1 fi done +printf 'github auth: unset\n' >> "${RUNNER_STATE_DIR}/run-context.log" +printf 'process github auth: unset\n' >> "${RUNNER_STATE_DIR}/run-context.log" mkdir -p "${RUNNER_WORK_DIR}/workspace" touch "${RUNNER_WORK_DIR}/workspace/job.txt" echo "job output" diff --git a/test/smoke-harness.test.ts b/test/smoke-harness.test.ts index 3662db2..9ba2e67 100644 --- a/test/smoke-harness.test.ts +++ b/test/smoke-harness.test.ts @@ -214,7 +214,8 @@ describe("runner registration smoke harness", () => { expect(linuxEntrypoint).toContain(`-u ${name}`); expect(windowsEntrypoint).toContain(`\"${name}\"`); } - expect(linuxEntrypoint).toContain("run_actions_runner 2>&1"); + expect(linuxEntrypoint).toContain("scrub_github_auth_env"); + expect(linuxEntrypoint).toContain("run_runner_job_bash"); expect(windowsEntrypoint).toContain("Out-Null"); expect(windowsEntrypoint).toContain("$runnerExitCode = Invoke-ActionsRunner"); expect(windowsEntrypoint).toContain("exit $runnerExitCode"); diff --git a/test/workflow.test.ts b/test/workflow.test.ts index 2f32bd1..5699678 100644 --- a/test/workflow.test.ts +++ b/test/workflow.test.ts @@ -245,11 +245,12 @@ describe("CI workflow", () => { "github.event.pull_request.head.repo.full_name == github.repository" ); } - expect( - (workflow.jobs["fast-checks"].steps as Array>).some( - (step) => step.uses === "./actions/setup-shell-safe-node" - ) - ).toBe(true); + const fastCheckSetupNodeStep = ( + workflow.jobs["fast-checks"].steps as Array> + ).find((step) => step.uses === "./actions/setup-shell-safe-node"); + expect(fastCheckSetupNodeStep?.with).toMatchObject({ + "node-version": "24.14.1" + }); expect(workflow.jobs.changes["runs-on"]).toEqual(shellSafePublicRunner); expect(workflow.jobs["hosted-fork-fast-checks"]["runs-on"]).toBe(