Skip to content

ci: a pull request that changes CI shows its CI impact: CI workflow job-minutes, runner-pool usage and time to green, and runner classes of what changed (AST-030 FR19) - #9187

Merged
cixzhang merged 30 commits into
mainfrom
ci/ci-impact
Nov 1, 2026

Conversation

@cixzhang

@cixzhang cixzhang commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Maintainer impact

A pull request that changes CI can make every later pull request slower or put more load on the shared runner pool. Today nothing on the pull request shows that, so reviewers judge workflow changes blind. This adds a CI impact section to the PR report for CI changes, measured from data the comment job can already read, and asks such pull requests for a one-line CI impact: in their description (AST-030 FR19).

CI impact: standard runners only. No CI job is added or changed. The PR Comment job gains three short artifact steps (seconds per report). Job-minutes per PR update, runner-pool usage and time to green are unchanged.

Intended invariant

  • A pull request that changes a workflow, a composite action or a CI script gets one collapsed CI impact section. Its summary line is visible and holds the job-minute, pool and time-to-green changes and the runner class. The table under it gives before and after for:
    • job-minutes per PR update;
    • runner pool, runner-minutes a day;
    • average concurrent jobs;
    • time to green;
    • runs a day.
  • It also lists each changed job (added, removed or changed) with its runner class: standard GitHub-hosted, non-standard, standard or non-standard by event, or unknown (an expression this report can't resolve, such as a variable with a default). Labels are read through the same helper as the free-runner contract (lib/runner-labels.cjs). Jobs that share a name share one entry with their classes merged.
  • A changed job counts this run's minutes only as often as it ran in the sampled runs, so testing a label-gated suite with its label doesn't read as if every later PR runs it. Time to green compares with sampled runs that ran the same jobs, or isn't compared.
  • A node-tooling pull request (AST-030 FR8) gets no PR comment, so FR19 asks only for its description line.
  • Only ci.yml is measured. Other changed workflows, composite actions and CI scripts are named as not measured, both in the section and in FR19 and CONTRIBUTING.
  • pr-preview.mjs loads the YAML parser lazily, because the PR Comment workflow's resolve and spec-only jobs import it without installing dependencies. A contract test (pr-preview-imports.test.mjs) pins that it, and everything it loads at the top level, imports only Node built-ins and relative files.
  • Before is read at the merge base. Other changed workflows are listed with their triggers and runner classes. The summary line names them as changed but not measured.
  • A CI change whose impact can't be read gets one line saying so.
  • Every job, workflow, trigger and runner name from the pull request's files is rendered as literal text.
  • Flags (⚠️ in the summary): a job moving onto a non-standard runner (decided per job), more than 10% added runner-pool usage, more than 2 minutes added to time to green, and a trigger change. A flag asks the reviewer to weigh the cost; it fails nothing.
  • One line states the assumptions. The section reports runner usage only, never prices.
  • Any other pull request's report is unchanged.

Change

  • lib/ci-impact.js (new) covers:
    • the CI-path test and runner classes (a literal, or the strings a runs-on expression can yield);
    • a job-by-job diff of ci.yml at the merge base and the head;
    • the history summary (each job's average runner minutes per run, median time to green, runs a day);
    • the estimate, and the section.
  • lib/pr-preview.mjs:
    • gatherCiImpact reads the changed files, ci.yml at the merge base and head, and the source run.
    • ciHistory samples the last 20 successful pull-request CI runs' jobs and counts 7 days of runs that did work.
  • pr-comment.yml: the comment job keeps the history as a ci-history-<date> artifact, so later CI-changing pull requests that day reuse it. It looks the artifact up, downloads it, and keeps it when it computed a new one. There is no new job. Every report adds one file-list read. A CI change adds the merge-base, workflow-file and run reads, plus about 23 history reads once a day.
  • The maintenance PR template gains a CI impact evidence line, CONTRIBUTING describes it, and AST-030 gains FR19 with its verification row.

Evidence

  • Failure before the change: a pull request that adds a job, moves one to a larger runner, or slows the critical path shows nothing about it on the pull request.
  • Success after the change: rendered from ci: per-suite ci:run-visual, ci:run-a11y and ci:run-rtl labels replace ci:heavy-lanes #9165's real CI run with this head's code. That PR added the run-labels job and changed the visual, accessibility and RTL jobs. The report shows +0.3 job-minutes per update and pool +0.4% (+156 of 37,532 runner-minutes a day, at 467 runs a day). Time to green goes 15.5 → 15.9 min, with no flags. Every changed job but the new standard run-labels reads "standard or non-standard by event" (the release-check pool), so the summary reads "some runners chosen by event or unknown".
  • Product/runtime behavior verified unchanged: CI report and contributor docs only.

Scope

  • No intended public API, product behavior, visual direction, or policy change beyond the AST-030 FR19 record below.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Writing rubric results

Run over docs/specs/AST-030/spec.md: FR19 and its verification row.

  • R1 narration: none (re-run after FR19 gained the weighting, comparison and node-tooling sentences). FR19 states what a CI-changing pull request carries and what the comment measures and flags.
  • R2 research in the record: none.
  • R3 evidence naming a change: none. The verification row names the tests that hold the claim (ci-impact.test.mjs, pr-preview.test.mjs), not this pull request.
  • R4 rejected alternatives over one line or outside a decision: none.
  • R5 pull request or issue references remaining: none.
  • R6 ruled open questions still listing options: none.

Testing

  • vitest run --project node .github/scripts: all pass except one Chromium-launch test this machine cannot run (rtl-audit-cli, unrelated). scripts/check-knowledge.mjs passes.
  • New lib/ci-impact.test.mjs covers:
    • the CI-change test;
    • runner classes (standard, non-standard, expression);
    • the workflow diff;
    • history averages, with skipped jobs counting zero;
    • before and after (unchanged jobs keep their history, changed jobs use this run);
    • every flag;
    • the section, which names no price.
    • literal rendering of names from the pull request;
    • per-job non-standard flags, unknown runners, and other workflows compared job by job;
    • the could-not-measure line.
  • pr-preview.test.mjs: a CI change reaches the comment with the merge base as before; a non-CI change passes no impact.
  • Mutation checks, each caught:
    • a 20% pool threshold;
    • changed jobs ignoring this run;
    • skipped jobs counted.

…h PR, in the build job

Measures every published package's npm download and unpacked size in
build-storybook, after its build, and compares it with the merge base's
measurement that Main now keeps for 14 days. Adds a Published Package Size
section to the PR report and the job summary, and fails the job when a
package's download grows more than 5% (and at least 1 KB) unless the PR
description has a 'Size budget:' line.
…e ci:heavy-lanes

Each label opts a pull request into one heavy suite. A run-labels gate job
reads the event's labels and, for each suite label, the newest labeler's
role (write, maintain or admin; fail closed), from a decision script in the
merge commit's sparse checkout; each suite's owners need it and run only on
their own suite's output. A label still takes effect on the next push or
reopen, ci:run stays the fork gate, and the release check is unchanged.
The pull-request comment names the label for a suite that did not run.
AST-030, CONTRIBUTING and the visual and RTL docs name the new labels.
…ize, visual, accessibility, RTL, perf when it ran, and the CI jobs; touched components link their docs and stories
…helper; the check also follows root build inputs

- A package over its budget is flagged (job summary, PR report, a workflow
  warning) and fails nothing, like the component touch-only flags; the
  'Size budget:' line and the enforce step are gone.
- The package-size merge-base step deepens once when the 50-commit fetch
  holds no merge base, as size-base does.
- Report counts render through num().
- tsconfig.json and scripts/ are in the check's paths scope.
- size-base and the package-size lookup share lib/main-artifact.cjs.
…ied-components table (name links docs, Storybook, size, LoC, Visual · A11y · RTL marks), collapsed visual thumbnails, package size lines, one not-run hint

Changed shots' frames are published to the PR's assets branch by
publish-frames.mjs so the report can show before/after/diff thumbnails;
the touched-components report (wide-change flag included) is read from its
own artifact.
…s/pr-<n>, and the daily pruner removes that branch once its PR closes
…rked .pr-report-frames); hand-pushed assets branches keep the existing rule
…lass per changed job, job-minutes per update, runner-pool usage, time to green and runs a day, before and after (AST-030 FR18)

The comment job measures it from the workflow change and the last 20
successful pull-request runs, kept as a daily artifact so later CI-changing
pull requests that day reuse it. It reports runner usage, never prices. The
maintenance template and CONTRIBUTING ask for a one-line 'CI impact:'.
@vercel

vercel Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 1, 2026 4:54am UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 1, 2026, 5:10 AM UTC

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 31, 2026
@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Oct 31, 2026
@cixzhang cixzhang changed the title ci: a pull request that changes CI shows its CI impact: runner class, job-minutes, runner-pool usage and time to green, before and after (AST-030 FR18) ci: a pull request that changes CI shows its CI impact: runner class, job-minutes, runner-pool usage and time to green, before and after (AST-030 FR19) Oct 31, 2026
@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec 2686b26

@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Oct 31, 2026
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · bb1fbb6

Storybook · Sandbox · built from this PR's head

Package size: measured; main has no measurement of the merge base to compare yet.

API changes: core +2 · ~1 · −0 (report stale: run pnpm api:report)

3 API changes (advisory)
Package Where Signature Usage
+ core . · Types · interface SearchContext interface SearchContext<T extends SearchableItem = SearchableItem> import type {SearchContext} from '@astryxdesign/core'
+ core ./Typeahead · Also exported from an earlier entry point · SearchContext SearchContext (.) import {SearchContext} from '@astryxdesign/core/Typeahead'
~ core . · Types · interface SearchSource search: (query: string) => Promise<T[]> | T[] → search: (query: string, context?: SearchContext<T>) => Promise<T[]> | T[] import type {SearchSource} from '@astryxdesign/core'; const x: SearchSource = {search: …}

Not run on this PR: add ci:run-visual, ci:run-a11y or ci:run-rtl to run them.


Generated by PR Enrichment workflow | View full report

…r runners) and compares time to green only for a successful run
@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec 967ec74

@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Nov 1, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: FR19 is owner-approved and the earlier runner-label, summary-line and title fixes hold, but three things need fixing before this can land.

  • Merge main and start the new "Find today's CI history" script with the shared rate-limit wait (installRateLimitBackoff({github, core})), because without it the required test check fails in rate-limit-backoff.test.mjs ("pr-comment.yml comment installs the wait before its first request").
  • Look the history artifact up through mainArtifactRunId in .github/scripts/lib/main-artifact.cjs, with its sha made optional, instead of copying its trust filter into the workflow.
  • When same-named jobs merge, report a variant that always runs on a larger runner as non-standard rather than "standard or non-standard by event", with a test on the rendered line.

[Automated review]

Comment thread .github/workflows/pr-comment.yml Outdated
Comment on lines +471 to +472
const name = `ci-history-${new Date().toISOString().slice(0, 10)}`;
const {data} = await github.rest.actions.listArtifactsForRepo({...context.repo, name, per_page: 20});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once main is merged, rate-limit-backoff.test.mjs requires every github-script step in this job to start with the shared wait, and this one makes an API call without it, so the required test check fails. Start the script with:

// Wait out the repository's shared API rate limit (lib/rate-limit-backoff.cjs).
require(require('node:path').join(process.env.GITHUB_WORKSPACE, '.github/scripts/lib/rate-limit-backoff.cjs'))
  .installRateLimitBackoff({github, core});

Comment thread .github/workflows/pr-comment.yml Outdated
Comment on lines +473 to +477
// Only this repository's own runs on main keep the history.
const artifact = data.artifacts.find(candidate =>
!candidate.expired &&
candidate.workflow_run?.head_branch === 'main' &&
candidate.workflow_run?.head_repository_id === candidate.workflow_run?.repository_id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the trust filter mainArtifactRunId in .github/scripts/lib/main-artifact.cjs already owns (unexpired, head_branch === 'main', same repository). Making its sha optional and calling it here keeps one filter for every lookup of an artifact Main keeps, so a later trust fix cannot miss this one.

Comment on lines +68 to +72
function mergeClasses(a, b) {
if (!a) return b;
if (!b) return a;
return classifyLabels([...a.labels, ...b.labels]);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reclassifying the union of labels turns a variant on ubuntu-latest beside one on 4-core-ubuntu into mixed, so the per-id fixture in ci-impact.test.mjs renders pr-a11y changed: standard or non-standard by event (4-core-ubuntu) and the summary says "some runners chosen by event or unknown". Merging by rank (a wholly non-standard variant makes the entry non-standard) and asserting the rendered line would fix it.

…runs through main-artifact.cjs (commit now optional); a variant always on a larger runner makes its job non-standard
@cixzhang

cixzhang commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 9dba1d1

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: FR19 is owner-approved and the rate-limit, shared-lookup and merged-runner fixes are in, but the CI impact section still misreports two cases.

  • A pull request that changes only a composite action or a CI script, with ci.yml unchanged, reads 0 job-min per update · pool 0% and never trips the pool flag; count jobs that use a changed local action as changed, or print "not measured" for those changes, and add a fixture for it.
  • Runs a day counts 7 to 8 days of runs and divides by 7, so runner-minutes a day and concurrent jobs read up to 14% high; query the seven whole days before today.

[Automated review]

*/
function estimateImpact({diff, history, currentJobs, currentWallMinutes}) {
const current = runMinutes(currentJobs);
const changed = new Set(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed holds only jobs whose ci.yml definition changed, so a pull request that changes only a composite action (such as ./.github/actions/setup, which most ci.yml jobs call) or a CI script keeps every job at its history average and reads 0 job-min per update · pool 0% with no pool flag, even when this run took several minutes more per job. Counting a job as changed when a step uses: a changed local action, and printing "not measured" for changes the report cannot attribute (as the other-workflow note already does), would keep FR19's pool flag honest.

Comment thread .github/scripts/lib/pr-preview.mjs Outdated
now = new Date(),
}) {
if (cached?.runs) return cached;
const since = new Date(now.getTime() - 7 * 24 * 3600 * 1000)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Truncating to a date makes created: >=<date> cover 7 to 8 days depending on the time of day, and summarizeHistory divides by 7, so runs a day, runner-minutes a day and concurrent jobs read up to 14% high late in a UTC day. Querying the seven whole days before today (created: <today-7>..<today-1>) matches the Assumptions line.

…sured, and counts runs a day over the seven whole days before today
@cixzhang

cixzhang commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 07adc33

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: FR19 is owner-approved and the earlier not-measured and runs-a-day fixes are in, but the CI impact section still misreports two cases.

  • A changed job's minutes and time to green come from this one run, so an edit to a label-gated suite tested with its label reads pool +16% · time to green +10 min and trips both flags although later pull requests run nothing new; weight changed jobs by how often they ran in the sampled runs, compare time to green only with runs that ran the same jobs, and add a fixture for it.
  • A pull request that changes only crowdin-upload.yml is routed as tooling-only and gets no CI impact section; post the section from that path, or scope FR19 and the description to leave FR8's tooling admissions out.

[Automated review]

Comment thread .github/scripts/lib/ci-impact.js Outdated
const before = sum(diff.names.before, name => history.jobMinutes[name] ?? 0);
const after = sum(diff.names.after, name =>
changed.has(name)
? (current[name] ?? history.jobMinutes[name] ?? 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This run's minutes stand in for every later pull request, but a label-gated suite the author opts into (ci:run-visual and friends) runs here while almost every sampled run skips it, so its full minutes are compared with an average that counts those skips as zero. On the real ci.yml, an env-only edit to pr-visual tested under its label reads +13.3 job-min per update · pool +16% · time to green +10 min ⚠️. Weighting a changed job's minutes by the share of sampled runs in which it ran (when its if: is unchanged), and comparing time to green only with runs that ran the same jobs, would keep both flags to real added load.

…time to green with runs of the same jobs; FR19 states the node-tooling lane gets no comment
@cixzhang

cixzhang commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 50559d3

@github-actions github-actions Bot added needs:spec-owner-review Current knowledge records await owner approval and removed needs:spec-owner-review Current knowledge records await owner approval labels Nov 1, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: FR19 is owner-approved, but the new top-level yaml import in .github/scripts/lib/pr-preview.mjs cannot load in the PR Comment workflow's resolve and spec-only-reconcile jobs, which run without a dependency install, so every pull request would lose its report and get a failing PR Comment status. Loading the parser where it is used (inside workflowAt) and adding a test that pr-preview.mjs imports only Node built-ins and relative files would fix it.

  • A changed job that ran in none of the 20 sampled runs is counted as if every later pull request ran it (share in ci-impact.js), which FR19's "counts as often as it ran in those runs" rules out.
  • FR19 and CONTRIBUTING.md say the comment measures any workflow change, but only ci.yml is measured; naming other workflows as not measured in both would match the code.

A new commit will need a fresh /approve-spec for its head.

[Automated review]

Comment thread .github/scripts/lib/pr-preview.mjs Outdated
import process from 'node:process';
import {createRequire} from 'node:module';
import {fileURLToPath} from 'node:url';
import yaml from 'yaml';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR Comment workflow's resolve and spec-only-reconcile jobs import this module from a main checkout with no setup step, so there is no node_modules; loaded that way this line throws ERR_MODULE_NOT_FOUND Cannot find package 'yaml' (the base module loads). Every pull request would then lose its report and get a failing PR Comment status. Loading it inside workflowAt (const {parse} = await import('yaml')), which only the installed comment job reaches, and adding a test that this module imports only node: built-ins and relative files would fix it.

Comment thread .github/scripts/lib/ci-impact.js Outdated
Comment on lines +258 to +261
const share = name =>
history.sampled > 0 && history.jobMinutes[name] !== undefined
? (history.jobRuns?.[name] ?? 0) / history.sampled
: 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A changed job absent from the sampled runs gets a share of 1, so a label-gated suite that ran in none of the 20 runs, edited and tested under its label, reads as fully added (+12 job-min per update · pool +27% ⚠️ in a probe with pr-rtl skipped in every sampled run). FR19 says a changed job "counts as often as it ran in those runs", which is zero here. A share of 1 only for added jobs, 0 for a changed job with no sampled runs, and a fixture for it would match.

Comment thread docs/specs/AST-030/spec.md Outdated
Comment on lines +330 to +333
pull-request comment measures these from the workflow change and recent
pull-request runs, without starting a job: a changed job counts as often as
it ran in those runs, time to green compares with runs that ran the same
jobs, and a changed composite action or CI script is named as not measured.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only ci.yml is measured; gatherCiImpact names every other changed workflow "not measured", including pull-request workflows such as lint.yml. Adding "or workflow other than ci.yml" to the not-measured clause here and in CONTRIBUTING.md keeps the record to what the comment does.

…ports only built-ins and relative files, pinned), a changed job that never ran counts zero, and FR19 and CONTRIBUTING say only ci.yml is measured
@cixzhang

cixzhang commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 7950582

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: FR19 is owner-approved and the earlier fixes hold, but two things need fixing before reviewers can rely on the CI impact section.

  • Renaming a ci.yml job makes its minutes read as removed (a job that grows from 10 to 14 minutes shows −10 job-min per update · pool −83% with no flag), because its share of the sampled runs is looked up under the new name; take it under the base-side name and add a rename fixture.
  • pr-preview-imports.test.mjs only sees require( on the same line as const, so a multi-line require like the one in ci-impact.js slips past it; import pr-preview.mjs where no node_modules resolves, or match requires across lines.

A new commit will need a fresh /approve-spec for its head.

[Automated review]

Comment thread .github/scripts/lib/ci-impact.js Outdated
Comment on lines +262 to +265
const share = name =>
added.has(name) || history.sampled === 0
? 1
: (history.jobRuns?.[name] ?? 0) / history.sampled;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A renamed job (same id, new name:) is looked up here under its head-side name, which no sampled run has, so it counts zero while before keeps its minutes under the old name. A job that grew from 10 to 14 minutes reads −10 job-min per update · pool −83% with no flag, though FR19 says a changed job counts as often as it ran. Carrying the base-side name on each change in diffWorkflow, taking the share under it, and a rename fixture would fix it.

// Top-level requires only (not inside a function body): column 0 or a
// top-level const.
for (const match of source.matchAll(
/^(?:const|let|var)[^\n]*?\brequire\(\s*['"]([^'"]+)['"]\s*\)/gm,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs require( on the same line as const, so the multi-line destructured require at ci-impact.js:21-25 is never seen and runner-labels.cjs is never visited: prepending a multi-line require('yaml') to ci-impact.js keeps this test green, though the uninstalled resolve job would then fail to load the module. Importing pr-preview.mjs from a copy of .github/scripts where no node_modules resolves would test the real property.

…de name, and the import contract sees requires across lines
@cixzhang

cixzhang commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec bb1fbb6

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval recommended: FR19 is owner-approved at this head, and both earlier findings are fixed, each pinned by a test that fails without the fix. A renamed ci.yml job now keeps its history under its base-side name, and the import contract test catches multi-line requires. A new commit will need a fresh /approve-spec for its head.

[Automated review]

@cixzhang
cixzhang merged commit b094f93 into main Nov 1, 2026
51 checks passed
cixzhang added a commit that referenced this pull request Nov 1, 2026
…tails, the CI impact section stays outside the budget, and the placeholder shows as before
@github-actions
github-actions Bot deleted the ci/ci-impact branch November 1, 2026 06:05

This branch was successfully deployed

1 active deployment
Preview — bb1fbb6c Deployed Nov 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant