Skip to content

Commit c9f88bf

Browse files
ci(INFRA-3631): dispatch Namespace shadow CI via workflow_dispatch
Replace workflow_call with gh workflow run so shadow jobs stay out of PR checks (ALLGREEN). Add optional pr_number/head_sha inputs and run-name for correlation. Skip ship-js-bundle-size-check on Namespace shadow to avoid duplicate pushes to mobile_bundlesize_stats. Secrets: wire ACTIONS_WRITE_TOKEN for dispatch; intended token is a fine-grained PAT on this repo with Actions: Read and write (plus Metadata: Read). Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 203f701 commit c9f88bf

2 files changed

Lines changed: 116 additions & 14 deletions

File tree

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
name: CI (Namespace shadow)
22

3+
# Fire-and-forget dispatcher for the Namespace shadow benchmark (INFRA-3631).
4+
#
5+
# This workflow does NOT use `workflow_call`. Instead, it dispatches `ci.yml`
6+
# as a separate `workflow_dispatch` run with `runner_provider=namespace`.
7+
#
8+
# Why a dispatch instead of a call:
9+
# - `workflow_call` nests the called workflow's jobs into THIS workflow's
10+
# check suite on the PR. With the repo's merge queue ALLGREEN policy,
11+
# any shadow flake would block merges.
12+
# - `workflow_dispatch` runs live in the Actions tab only -- invisible to
13+
# PR checks. The shadow can fail freely; it never blocks the queue,
14+
# never duplicates commit statuses, never posts PR comments.
15+
#
16+
# Correlation back to the originating PR:
17+
# - The dispatched run's display name is set via `run-name` in ci.yml to
18+
# `ci [shadow PR #<num> @ <sha>]`, so it's identifiable in the Actions
19+
# tab at a glance.
20+
# - The dispatcher job posts a GitHub Actions step summary linking the PR
21+
# to the dispatched shadow run URL, reachable from the PR Checks tab.
22+
323
on:
424
pull_request:
525
types: [opened, synchronize, reopened, ready_for_review]
@@ -17,17 +37,78 @@ concurrency:
1737
group: ns-shadow-${{ github.workflow }}-${{ github.ref }}
1838
cancel-in-progress: true
1939

40+
permissions:
41+
contents: read
42+
2043
jobs:
21-
shadow-ci:
22-
name: '[shadow] CI'
23-
permissions:
24-
actions: read
25-
contents: read
26-
id-token: write
27-
issues: write
28-
pull-requests: write
29-
statuses: write
30-
uses: ./.github/workflows/ci.yml
31-
with:
32-
runner_provider: namespace
33-
secrets: inherit
44+
dispatch-shadow:
45+
name: '[shadow] Dispatch'
46+
runs-on: ubuntu-latest
47+
# Skip dispatch for fork PRs: ACTIONS_WRITE_TOKEN is not exposed to forks,
48+
# and we don't want untrusted PRs consuming Namespace capacity.
49+
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
50+
steps:
51+
- name: Dispatch ci.yml on Namespace
52+
id: dispatch
53+
env:
54+
GH_TOKEN: ${{ secrets.ACTIONS_WRITE_TOKEN }}
55+
REPO: ${{ github.repository }}
56+
REF: ${{ github.head_ref || github.ref_name }}
57+
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
58+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
59+
run: |
60+
set -euo pipefail
61+
echo "Dispatching ci.yml on ref='${REF}' (PR='${PR_NUMBER:-none}', sha='${HEAD_SHA}')"
62+
gh workflow run ci.yml \
63+
--repo "$REPO" \
64+
--ref "$REF" \
65+
-f runner_provider=namespace \
66+
-f pr_number="$PR_NUMBER" \
67+
-f head_sha="$HEAD_SHA"
68+
69+
# gh workflow run returns immediately with no run ID. Find the run
70+
# we just created so we can link to it from the step summary.
71+
# Best-effort: poll briefly for a queued/in_progress dispatch on this ref.
72+
RUN_URL=""
73+
for _ in $(seq 1 10); do
74+
RUN_URL=$(gh run list \
75+
--repo "$REPO" \
76+
--workflow ci.yml \
77+
--event workflow_dispatch \
78+
--branch "$REF" \
79+
--limit 1 \
80+
--json url,createdAt \
81+
--jq '.[0].url' 2>/dev/null || true)
82+
if [ -n "$RUN_URL" ] && [ "$RUN_URL" != "null" ]; then
83+
break
84+
fi
85+
sleep 2
86+
done
87+
echo "run_url=${RUN_URL}" >> "$GITHUB_OUTPUT"
88+
89+
- name: Step summary
90+
env:
91+
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
92+
PR_URL: ${{ github.event.pull_request.html_url || '' }}
93+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
94+
REF: ${{ github.head_ref || github.ref_name }}
95+
RUN_URL: ${{ steps.dispatch.outputs.run_url }}
96+
run: |
97+
{
98+
echo "## Namespace shadow CI dispatched"
99+
echo
100+
echo "| Field | Value |"
101+
echo "|---|---|"
102+
if [ -n "$PR_NUMBER" ]; then
103+
echo "| PR | [#${PR_NUMBER}](${PR_URL}) |"
104+
fi
105+
echo "| Ref | \`${REF}\` |"
106+
echo "| Head SHA | \`${HEAD_SHA}\` |"
107+
if [ -n "${RUN_URL}" ]; then
108+
echo "| Shadow run | ${RUN_URL} |"
109+
else
110+
echo "| Shadow run | (not yet visible — check the Actions tab) |"
111+
fi
112+
echo
113+
echo "_Shadow CI runs **fire-and-forget**: it does not appear in this PR's checks and never blocks the merge queue. Benchmark data is collected by \`scripts/namespace-benchmark.sh\`._"
114+
} >> "$GITHUB_STEP_SUMMARY"

.github/workflows/ci.yml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
name: ci
22

3+
run-name: >-
4+
${{ inputs.pr_number && format('ci [shadow PR #{0} @ {1}]', inputs.pr_number, inputs.head_sha) || '' }}
5+
36
on:
47
push:
58
branches: [main]
@@ -19,6 +22,14 @@ on:
1922
type: string
2023
required: false
2124
default: current
25+
pr_number:
26+
description: "PR number (shadow correlation, optional)"
27+
type: string
28+
required: false
29+
head_sha:
30+
description: "PR head SHA (shadow correlation, optional)"
31+
type: string
32+
required: false
2233
workflow_dispatch:
2334
inputs:
2435
runner_provider:
@@ -29,6 +40,14 @@ on:
2940
- current
3041
- namespace
3142
default: current
43+
pr_number:
44+
description: "PR number (shadow correlation, optional)"
45+
required: false
46+
type: string
47+
head_sha:
48+
description: "PR head SHA (shadow correlation, optional)"
49+
required: false
50+
type: string
3251

3352
concurrency:
3453
group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.sha || github.ref }}
@@ -516,7 +535,9 @@ jobs:
516535
name: Ship JS bundle size check
517536
runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }}
518537
needs: [js-bundle-size-check]
519-
if: ${{ github.ref == 'refs/heads/main' }}
538+
# Skip on Namespace shadow runs: hourly cron against main would otherwise
539+
# push duplicate entries to the external mobile_bundlesize_stats repo.
540+
if: ${{ github.ref == 'refs/heads/main' && inputs.runner_provider != 'namespace' }}
520541
steps:
521542
- uses: namespacelabs/nscloud-checkout-action@938f5d2d403d6224d9a0c0dc559b1dae09c2ede4 # v8.1.1
522543
if: ${{ inputs.runner_provider == 'namespace' }}

0 commit comments

Comments
 (0)