Skip to content

feat(ui): add OrganizationProfileApiKeysPanel mosaic component #133490

feat(ui): add OrganizationProfileApiKeysPanel mosaic component

feat(ui): add OrganizationProfileApiKeysPanel mosaic component #133490

name: Major Version Check
on:
pull_request:
types: [opened, edited, synchronize, reopened]
issue_comment:
types: [created, edited, deleted]
permissions:
contents: read
issues: read
pull-requests: read
statuses: write
jobs:
check-major-bump:
if: ${{ github.event_name == 'pull_request' || github.event.issue.pull_request }}
runs-on: ubuntu-latest
steps:
- name: Check for unapproved major changesets
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
with:
script: |
const STATUS_CONTEXT = 'Major Version Check';
const prNumber = context.payload?.pull_request?.number || context.payload?.issue?.number;
// Resolve the PR so we have its head SHA. issue_comment runs are tied to the
// default branch, so the implicit job check-run lands on main rather than the PR
// head. We post an explicit commit status to the PR head instead, so the required
// context updates correctly no matter which event triggered the run (e.g. the
// re-run after an "!allow-major" comment).
let pullRequest = context.payload.pull_request;
if (!pullRequest) {
const { data } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
pullRequest = data;
}
const headSha = pullRequest.head.sha;
const setStatus = async (state, description) => {
try {
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: headSha,
context: STATUS_CONTEXT,
state,
description,
target_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
});
} catch (error) {
// Fork PRs get a read-only token and can't post statuses; don't fail the job over it
// (such PRs need an internal re-run or admin bypass). Re-throw anything else.
if (error.status === 403) {
core.warning(`Could not post the "${STATUS_CONTEXT}" status (read-only token, likely a fork PR): ${error.message}`);
return;
}
throw error;
}
};
// Check if any changeset files indicate a major bump.
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
per_page: 100,
});
let hasMajorChangeset = false;
for (const file of files) {
if (file.filename.startsWith('.changeset/') && file.status !== 'removed') {
const { data: changesetContent } = await github.rest.repos.getContent({
owner: context.repo.owner,
repo: context.repo.repo,
path: file.filename,
ref: headSha,
});
const content = Buffer.from(changesetContent.content, changesetContent.encoding).toString();
// Only check for "major" in the YAML frontmatter section (between --- markers)
// This avoids false positives from descriptive text mentioning "major"
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\s*$/m);
if (frontmatterMatch && /:\s*["']?major["']?/.test(frontmatterMatch[1])) {
hasMajorChangeset = true;
break;
}
}
}
if (!hasMajorChangeset) {
await setStatus('success', 'No major version bump detected.');
console.log('No major changeset detected.');
return;
}
// A major bump is present: require an "!allow-major" comment from an org member.
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
per_page: 100,
});
// The GITHUB_TOKEN (github-actions[bot]) isn't an org member, so checkMembershipForUser
// only confirms PUBLIC members; approvers must have public "clerk" org membership.
let approvalFound = false;
for (const comment of comments) {
if (comment.body?.trim().toLowerCase() === '!allow-major') {
try {
const { status } = await github.rest.orgs.checkMembershipForUser({
org: context.repo.owner,
username: comment.user.login,
});
if (status === 204) {
approvalFound = true;
break;
}
} catch (error) {
// 404 = not a public org member; rethrow transient 403/5xx so a hiccup can't drop a valid approval.
if (error?.status === 404) continue;
throw error;
}
}
}
if (approvalFound) {
await setStatus('success', 'Major version bump approved by an organization member.');
console.log('Major version bump approved by an organization member.');
} else {
// The red "Major Version Check" commit status on the PR head is the gate. We keep
// the job itself green so that the success status posted by a later "!allow-major"
// re-run (an issue_comment run, whose implicit check-run lands on main, not the PR
// head) isn't shadowed by a stale red job check-run that never clears.
await setStatus('failure', 'Major bump needs an "!allow-major" comment from an org member.');
core.warning('Major version bump requires approval from an organization member by commenting "!allow-major" on the PR.');
}