Skip to content

[infra] Add reusable release branch freshness check - #1998

Draft
sai6855 wants to merge 4 commits into
mui:masterfrom
sai6855:codex/release-up-to-date
Draft

sai6855 wants to merge 4 commits into
mui:masterfrom
sai6855:codex/release-up-to-date

Conversation

@sai6855

@sai6855 sai6855 commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Adds a reusable GitHub Actions check that passes PRs without the release label and fails labeled PRs that are behind their base branch. Repositories can call it for PR updates and base-branch pushes.

Opened PR in material-ui repo, once this is merged, we can merge this. mui/material-ui#49589

@code-infra-dashboard

code-infra-dashboard Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Deploy preview

https://deploy-preview-1998--mui-internal.netlify.app/
QR code for https://deploy-preview-1998--mui-internal.netlify.app/

Bundle size

Total Size Change: 0B(0.00%) - Total Gzip Change: 0B(0.00%)
Files: 79 total (0 added, 0 removed, 0 changed)

Show details for 79 more bundles

@mui/internal-docs-infra/abstractCreateDemo parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/abstractCreateDemoClient parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/abstractCreateStream parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/abstractCreateTypes parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/ChunkProvider parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/cli parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/CodeControllerContext parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/CodeExternalsContext parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/CodeHighlighter parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/CodeHighlighter/errors parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/CodeHighlighter/types parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/CodeProvider parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/CoordinatedLazy parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/CoordinatedLazy/types parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/createDemoData parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/createDemoData/types parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/createSitemap parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/createSitemap/types parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/resolvePageUrl parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/routeGroups parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useCode parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useCodeWindow parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useCoordinated parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useCopier parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useDemo parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useDemoController parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useErrors parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useLocalStorageState parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/usePreference parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useScrollAnchor parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useSearch parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useSearch/types parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useStream parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useStream/types parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useType parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useTypes parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/useUrlHashState parsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/internal-docs-infra/withDocsInfra parsed: 0B(0.00%) gzip: 0B(0.00%)
addLineGutters parsed: 0B(0.00%) gzip: 0B(0.00%)
applyCodeTransformWithComments parsed: 0B(0.00%) gzip: 0B(0.00%)
BuildEngine parsed: 0B(0.00%) gzip: 0B(0.00%)
CodeEditor parsed: 0B(0.00%) gzip: 0B(0.00%)
CodeHighlighterChunk parsed: 0B(0.00%) gzip: 0B(0.00%)
CodeHighlighterClient parsed: 0B(0.00%) gzip: 0B(0.00%)
CodeInitialSourceLoader parsed: 0B(0.00%) gzip: 0B(0.00%)
CodeSourceLoader parsed: 0B(0.00%) gzip: 0B(0.00%)
compileCssWithPostcss parsed: 0B(0.00%) gzip: 0B(0.00%)
computeHastDeltas parsed: 0B(0.00%) gzip: 0B(0.00%)
createFrame parsed: 0B(0.00%) gzip: 0B(0.00%)
createParseSourceWorkerClient parsed: 0B(0.00%) gzip: 0B(0.00%)
embedTransforms parsed: 0B(0.00%) gzip: 0B(0.00%)
enhanceCodeEmphasis parsed: 0B(0.00%) gzip: 0B(0.00%)
findExpandingRanges parsed: 0B(0.00%) gzip: 0B(0.00%)
frameVisibility parsed: 0B(0.00%) gzip: 0B(0.00%)
getHastTextContent parsed: 0B(0.00%) gzip: 0B(0.00%)
grammarCache parsed: 0B(0.00%) gzip: 0B(0.00%)
grammarLoaders parsed: 0B(0.00%) gzip: 0B(0.00%)
grammarMaps parsed: 0B(0.00%) gzip: 0B(0.00%)
grammars parsed: 0B(0.00%) gzip: 0B(0.00%)
hastUtils parsed: 0B(0.00%) gzip: 0B(0.00%)
isFrameSpan parsed: 0B(0.00%) gzip: 0B(0.00%)
loadCodeFallback parsed: 0B(0.00%) gzip: 0B(0.00%)
loadIsomorphicCodeVariant parsed: 0B(0.00%) gzip: 0B(0.00%)
parseSource parsed: 0B(0.00%) gzip: 0B(0.00%)
rolldown-runtime parsed: 0B(0.00%) gzip: 0B(0.00%)
source.css parsed: 0B(0.00%) gzip: 0B(0.00%)
source.diff parsed: 0B(0.00%) gzip: 0B(0.00%)
source.js parsed: 0B(0.00%) gzip: 0B(0.00%)
source.json parsed: 0B(0.00%) gzip: 0B(0.00%)
source.mdx parsed: 0B(0.00%) gzip: 0B(0.00%)
source.shell parsed: 0B(0.00%) gzip: 0B(0.00%)
source.ts parsed: 0B(0.00%) gzip: 0B(0.00%)
source.tsx parsed: 0B(0.00%) gzip: 0B(0.00%)
source.yaml parsed: 0B(0.00%) gzip: 0B(0.00%)
SourceEditingEngine parsed: 0B(0.00%) gzip: 0B(0.00%)
text.html.basic parsed: 0B(0.00%) gzip: 0B(0.00%)
text.md parsed: 0B(0.00%) gzip: 0B(0.00%)
TransformEngine parsed: 0B(0.00%) gzip: 0B(0.00%)
transpileSource parsed: 0B(0.00%) gzip: 0B(0.00%)

Details of bundle changes

Performance

No regressions in 8 benchmarks · ran 56s · details


Check out the code infra dashboard for more information about this PR.

@sai6855
sai6855 marked this pull request as ready for review October 27, 2026 13:10
Copilot AI balanced review requested due to automatic review settings October 27, 2026 13:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Preparation failures can preserve stale passing statuses, and repeated bucket refreshes can exhaust the per-head status quota.

2 open issues
What changed in this PR

Adds a reusable release-branch freshness check for consuming repositories, including the linked Material UI caller. It publishes a required commit status that enforces base-branch freshness for release-labeled PRs.

Changes:

  • Adds event-based PR selection and serialized, whole-bucket status updates.
  • Tests freshness checks, shared heads, API failures, pagination, and initialization.
  • Documents caller setup, deployment order, and branch protection requirements.
File Description
AGENTS.md Documents freshness-check conventions and updates the Node.js prerequisite.
.github/​workflows/​scripts/​prs/​release-up-to-date.md Explains adoption and required-status configuration.
.github/​workflows/​scripts/​prs/​checkReleaseUpToDate.test.js Tests PR selection and status reconciliation.
.github/​workflows/​scripts/​prs/​checkReleaseUpToDate.js Implements SHA buckets, freshness comparisons, and commit statuses.
.github/​workflows/​prs_check-release-up-to-date.yml Adds reusable preparation and serialized checking jobs.

Review effort: Balanced

@sai6855
sai6855 marked this pull request as draft October 27, 2026 13:25
@sai6855
sai6855 requested a balanced review from Copilot October 27, 2026 13:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Head transitions and API failures can leave stale required statuses that incorrectly block or permit merging.

2 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Refresh both old and new heads after PR synchronization

.github/​workflows/​scripts/​prs/​checkReleaseUpToDate.js:44

On a synchronize event, pull_request.head.sha is already the new head; the previous SHA is in payload.before. If a release PR advances into another bucket, an unlabeled PR sharing its old head can retain the failing required status even though freshness no longer applies. Include payload.before in the selected batches so both affected buckets are refreshed.

2 resolved since last review

Review effort: Balanced

Comment on lines +52 to +56
const open = await github.paginate(github.rest.pulls.list, {
...context.repo,
state: 'open',
base: baseBranch,
per_page: 100,

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The release gate requires validation in an adopting repository with its real GITHUB_TOKEN and required-status rules, because HTTP-level tests cannot establish enforcement guarantees for fork PRs and overlapping PR/base-push runs.

1 open issue
1 resolved since last review

Review effort: Balanced

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants