Let workflow env override runner defaults; run sync and live test on GitHub only (#14)
Workflow and step env now override the runner's CI and DIFFINERY defaults, as on GitHub; GITHUB_* and RUNNER_* stay fixed. The DIFFINERY=true default had replaced the workflows' DIFFINERY URL when they ran on Diffinery. Claude-Session: https://claude.ai/code/session_01AizKXSsengXZRegJxRATkL Co-authored-by: Claude <noreply@anthropic.com>
Canberk Demirci authored · GitHub committed signed1 parent cb1fccacommit 7a1eadcb27f569dc3122a8365f3b3e5ba0979552Browse files
5 files changed+27−4
Files (5)
modified.github/workflows/deploy.yml+1−1View file
| @@ -19,7 +19,7 @@ | ||
| 19 | 19 | deploy: |
| 20 | 20 | name: Deploy to Cloudflare |
| 21 | 21 | # Production deploys from one host only. This repository is mirrored to |
| 22 | - # diffinery.com (see move-to-diffinery.yml); switch this to | |
| 22 | + # diffinery.com (see sync-to-diffinery.yml); switch this to | |
| 23 | 23 | # 'https://diffinery.com' to make Diffinery the one that deploys. |
| 24 | 24 | if: ${{ github.server_url == 'https://github.com' }} |
| 25 | 25 | runs-on: ubuntu-latest |
modified.github/workflows/live-test.yml+2−1View file
| @@ -24,7 +24,8 @@ | ||
| 24 | 24 | jobs: |
| 25 | 25 | live: |
| 26 | 26 | name: Containers, sandboxes, webhooks, schedules and LFS |
| 27 | - if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} | |
| 27 | + # Runs on the host that deploys production (see the gate in deploy.yml). | |
| 28 | + if: ${{ github.server_url == 'https://github.com' && (github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success') }} | |
| 28 | 29 | runs-on: ubuntu-latest |
| 29 | 30 | timeout-minutes: 30 |
| 30 | 31 | env: |
modified.github/workflows/sync-to-diffinery.yml+2−0View file
| @@ -26,6 +26,8 @@ | ||
| 26 | 26 | jobs: |
| 27 | 27 | move: |
| 28 | 28 | name: Copy code, secrets and variables, then check Actions on Diffinery |
| 29 | + # Runs on GitHub only; the copy on Diffinery has nothing to sync to. | |
| 30 | + if: ${{ github.server_url == 'https://github.com' }} | |
| 29 | 31 | runs-on: ubuntu-latest |
| 30 | 32 | timeout-minutes: 90 |
| 31 | 33 | environment: production |
modifiedcontainers/runner/src/job.ts+12−2View file
| @@ -411,9 +411,19 @@ | ||
| 411 | 411 | return evaluate(expr, ctx, this.statusFns(scope), this.extra()); |
| 412 | 412 | } |
| 413 | 413 | |
| 414 | + /** | |
| 415 | + * Layers workflow env over the runner's defaults. Like GitHub, workflows can | |
| 416 | + * override defaults such as CI or DIFFINERY, but not GITHUB_* or RUNNER_*. | |
| 417 | + */ | |
| 418 | + withDefaults(envCtx: Record<string, string>): Record<string, string> { | |
| 419 | + const env = { ...this.defaultEnv, ...envCtx }; | |
| 420 | + for (const [k, v] of Object.entries(this.defaultEnv)) if (/^(GITHUB|RUNNER)_/.test(k)) env[k] = v; | |
| 421 | + return env; | |
| 422 | + } | |
| 423 | + | |
| 414 | 424 | /** Builds the environment for a child process. */ |
| 415 | 425 | processEnv(envCtx: Record<string, string>, extra: Record<string, string> = {}): NodeJS.ProcessEnv { |
| 416 | - const env: NodeJS.ProcessEnv = { ...this.baseEnv, ...envCtx, ...this.defaultEnv, ...extra }; | |
| 426 | + const env: NodeJS.ProcessEnv = { ...this.baseEnv, ...this.withDefaults(envCtx), ...extra }; | |
| 417 | 427 | const basePath = envCtx.PATH ?? this.baseEnv.PATH ?? "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; |
| 418 | 428 | env.PATH = [...this.pathAccum, basePath].filter(Boolean).join(path.delimiter); |
| 419 | 429 | return env; |
| @@ -580,7 +590,7 @@ | ||
| 580 | 590 | let cmd = argv; |
| 581 | 591 | let cwd = o.cwd; |
| 582 | 592 | let env = this.processEnv(o.envCtx, { ...(o.extraEnv ?? {}), ...files }); |
| 583 | - if (o.wrap) ({ argv: cmd, cwd, env } = o.wrap(argv, { ...o.envCtx, ...this.defaultEnv, ...(o.extraEnv ?? {}), ...files }, o.cwd)); | |
| 593 | + if (o.wrap) ({ argv: cmd, cwd, env } = o.wrap(argv, { ...this.withDefaults(o.envCtx), ...(o.extraEnv ?? {}), ...files }, o.cwd)); | |
| 584 | 594 | const res = await exec(cmd[0]!, cmd.slice(1), { |
| 585 | 595 | cwd, |
| 586 | 596 | env, |
modifiedcontainers/runner/test/job.test.ts+10−0View file
| @@ -547,6 +547,16 @@ | ||
| 547 | 547 | expect(c.conclusion).toBe("success"); |
| 548 | 548 | expect(api.logText(0)).toMatch(/wd=pkg shell=\S+\.sh e=var-inp-out/); |
| 549 | 549 | }); |
| 550 | + | |
| 551 | + it("lets workflow env override CI and DIFFINERY but not GITHUB_* or RUNNER_*", async () => { | |
| 552 | + const c = await run( | |
| 553 | + makeSpec(api, [{ env: { CI: "step" }, run: 'echo "d=$DIFFINERY ci=$CI sha=$GITHUB_SHA os=$RUNNER_OS"' }], { | |
| 554 | + env: { DIFFINERY: "https://diffinery.example", GITHUB_SHA: "nope", RUNNER_OS: "nope" }, | |
| 555 | + }), | |
| 556 | + ); | |
| 557 | + expect(c.conclusion).toBe("success"); | |
| 558 | + expect(api.logText(0)).toMatch(/d=https:\/\/diffinery\.example ci=step sha=[0-9a-f]{40} os=Linux/); | |
| 559 | + }); | |
| 550 | 560 | }); |
| 551 | 561 | |
| 552 | 562 | describe("agent binary (esbuild bundle)", () => { |