Add staged rollout to the pull request dashboard - #214
Conversation
Dashboard changes currently reach all 17 configured repositories the moment they merge, because every run resolves the reusable workflow and its scripts at the caller's commit. Split each entry path into a canary job and a stable job. Canary repositories run from the triggering commit; every other repository runs from the promoted rollout ref. `jobs.<id>.uses` cannot take an expression, so the channel has to be a separate job rather than a matrix value. The reusable workflow gains an optional `code_ref` input so a stable job can pin the scripts to the same ref it calls the workflow at. Repository configuration stays live: `repositories.json` is read from a sparse checkout of the triggering commit, so onboarding and settings changes take effect immediately in both channels. Both channels still call the local workflow, so this change is behaviorally a no-op. The first promotion is a follow-up pull request that pins the stable jobs to a release commit, which cannot be written before that commit exists. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 718f1d98-a0cd-453e-8512-6bb56a772289
Pull request dashboard statusWaiting on reviewers · refreshed 2026-08-01 17:59 UTC Review the latest changes. Status above doesn't look right?
|
There was a problem hiding this comment.
Pull request overview
Adds staged canary/stable rollout channels for the pull request dashboard.
Changes:
- Splits all dashboard entry paths into canary and stable jobs.
- Pins workflow scripts while keeping repository configuration live.
- Adds rollout validation tests and operational documentation.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
pull-request-dashboard/README.md |
Documents rollout and promotion procedures. |
.github/workflows/pull-request-dashboard.yml |
Implements canary/stable routing. |
.github/workflows/pull-request-dashboard-repo.yml |
Adds pinned code checkout with live configuration. |
.github/scripts/pull-request-dashboard/test_rollout.py |
Validates rollout wiring consistency. |
.github/scripts/pull-request-dashboard/RATIONALE.md |
Records rollout design rationale. |
Suppressed comments (1)
.github/scripts/pull-request-dashboard/RATIONALE.md:54
- This is the second place in the rationale that describes
code_refas a tag, although promotion passes the commit SHA used byuses. Update it as well so the rationale does not continue to prescribe a ref that violates the repository's hash-pinning policy.
- The stable jobs pass the tag they are called at as `code_ref`, and the
reusable workflow checks that ref out. Without it the workflow YAML would come
from the tag while the scripts came from `main`, so any change to their
interface would break the pinned repositories.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…e canary max-parallel comment
…the rollout ref as a hash pinned release commit
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (2)
.github/scripts/pull-request-dashboard/test_rollout.py:69
- This global search does not verify that both targeted jobs still contain the duplicated canary condition. If one job drops its
fromJSON(...)check, the literal in the other job keeps this test green; it will also start treating unrelated futurefromJSONarrays as canary lists. Assert the expected literal in each targeted job block explicitly so this remains an effective drift guard.
def test_inline_canary_lists_match_the_workflow_env(self) -> None:
inline = re.findall(r"fromJSON\('(\[[^']*\])'\)", self.text)
self.assertTrue(inline, "expected the targeted jobs to inline the canary list")
for literal in inline:
self.assertEqual(json.loads(literal), self.canary)
pull-request-dashboard/README.md:250
- The implementation checks this file out at
github.sha, which is the commit that triggered the caller, not necessarilymain(for example, a manual dispatch can select another ref). This also conflicts with the rationale's accurate “commit that triggered the run” wording. Document the actual source ref so operators do not assume configuration is always loaded from the latest default branch.
Repository configuration is never staged. `repositories.json` is always read
from `main`, so opting a repository in, or changing its settings, takes effect
on the next run in both channels.
… inline canary list in each targeted job
…ve the targeted stable job from the canary skip
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (3)
.github/scripts/pull-request-dashboard/RATIONALE.md:55
- Without
code_ref,actions/checkoutdefaults togithub.sha, so the scripts come from the triggering commit rather than unconditionally frommain. Keep this explanation aligned with the actual fallback behavior.
come from that commit while the scripts came from `main`, so any change to
.github/scripts/pull-request-dashboard/RATIONALE.md:41
- The canary checkout follows the triggering commit, not necessarily
main(manual dispatches can target another ref). Describing it asmainconflicts with the workflow and the README; use the triggering-commit wording here.
This issue also appears on line 55 of the same file.
the workflow and its scripts from `main`; every other repository runs them
pull-request-dashboard/README.md:251
- The live-config checkout uses
${{ github.sha }}, which is the triggering commit and can be a non-mainref for a manual dispatch. Saying the file is always read frommainoverstates the behavior; document the triggering-commit snapshot instead.
Repository configuration is never staged. `repositories.json` is always read
from `main`, so opting a repository in, or changing its settings, takes effect
on the next run in both channels.
… from the triggering commit
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (1)
.github/scripts/pull-request-dashboard/test_rollout.py:114
- This substring check can pass when
code_refis commented out (for example,# code_ref: <sha>) or has extra suffix text, so the guard can miss the half-applied promotion it is intended to reject. Anchor the match to an active YAML line and require only the expected SHA plus an optional tag comment.
self.assertIn(f"code_ref: {ref}", body, f"{job} runs scripts from a different ref")
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (3)
.github/scripts/pull-request-dashboard/test_rollout.py:108
- The local-fallback check is also only a substring search, so a commented-out local call can hide an active unexpected workflow call. Require an active job-level
useskey here as well.
self.assertIn(LOCAL_USES, body, f"{job} calls an unexpected workflow")
.github/scripts/pull-request-dashboard/test_rollout.py:93
- This substring assertion can be satisfied by a commented-out local
usesline, allowing a canary job to call a pinned/remote workflow without failing the rollout guard. Match an active four-space job-level key instead.
self.assertIn(LOCAL_USES, body)
.github/scripts/pull-request-dashboard/test_rollout.py:27
STABLE_USES.search()is not anchored to an active job-level key, so it also matches a commented-out# uses: ...@sha. A half-reverted stable job could therefore call the local workflow while retainingcode_ref, yet this guard would pass. Anchor the pattern to the four-space job-levelusesline so comments cannot satisfy it.
This issue also appears in the following locations of the same file:
- line 93
- line 108
STABLE_USES = re.compile(
r"uses:\s*open-telemetry/shared-workflows/" + re.escape(REPO_WORKFLOW_PATH) + r"@(\S+)"
)
Closes #108.
Dashboard changes currently reach all 17 configured repositories the moment they merge, because every run resolves the reusable workflow and its scripts at the caller's commit.
This splits each entry path into a canary job and a stable job. Canary repositories (
CANARY_REPOSITORIES, currentlyopentelemetry-java-instrumentationandshared-workflows) run the workflow and scripts from the triggering commit; every other repository runs them from the promoted rollout ref.pull-request-dashboard-repo.ymlgains an optionalcode_refinput so a stable job pins the scripts to the same commit it calls the workflow at, andtest_rollout.pyrejects a half-applied promotion. Repository configuration stays live, so onboarding and settings changes still take effect immediately in both channels.Both channels still call the local workflow, so this is behaviorally a no-op today. The first promotion is a follow-up PR that cuts a release and points the stable jobs at
...@<sha> # vX.Y.Zwith a matchingcode_ref.