Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 39 additions & 16 deletions .github/workflows/validate-milestone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: validate-milestone

permissions:
contents: read
pull-requests: read

on:
pull_request:
Expand All @@ -12,24 +13,46 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Validate milestone matches VERSION
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
MILESTONE: ${{ github.event.pull_request.milestone.title }}
with:
sparse-checkout: VERSION
script: |
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
});
core.info(`Modified files: ${files.map(f => f.filename).join(', ')}`);

- name: Validate milestone matches VERSION
run: |
expected=$(cat VERSION)
milestone="${{ github.event.pull_request.milestone.title }}"
const touchesVersion = files.some(f => f.filename === 'VERSION');
core.info(`Touches VERSION: ${touchesVersion}`);

// Use the PR's version when it bumps the file, base branch otherwise.
// It's fine to trust the author in this case, it's not meant to be
// a security gate, just a helpful check for maintainers.
const ref = touchesVersion
? context.payload.pull_request.head.sha
: context.payload.pull_request.base.ref;

if [[ -z "$milestone" ]]; then
echo "::error::PR must have a milestone set (expected: $expected)"
exit 1
fi
core.info(`Base ref: ${ref}`);

if [[ "$milestone" != "$expected" ]]; then
echo "::error::Milestone '$milestone' does not match VERSION '$expected'"
exit 1
fi
const resp = await github.rest.repos.getContent({
owner: context.repo.owner,
repo: context.repo.repo,
path: 'VERSION',
ref,
});
const expected = Buffer.from(resp.data.content, resp.data.encoding).toString('utf8').trim();
const milestone = process.env.MILESTONE;

echo "Milestone: $milestone ✓"
if (!milestone) {
core.setFailed(`PR must have a milestone set (expected: ${expected})`);
return;
}
if (milestone !== expected) {
core.setFailed(`Milestone '${milestone}' does not match VERSION '${expected}'`);
return;
}
core.info(`Milestone: ${milestone} ✓`);