mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-10-30 09:31:30 +01:00
249 lines
7.8 KiB
YAML
249 lines
7.8 KiB
YAML
# This reusable workflow sets the milestone based on the
|
|
# current PR labels.
|
|
|
|
name: PR Milestone
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
pr_number:
|
|
required: true
|
|
type: number
|
|
|
|
permissions:
|
|
pull-requests: write
|
|
contents: read
|
|
|
|
jobs:
|
|
set-milestone:
|
|
name: Set PR milestone
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Determine target milestone
|
|
id: determine-milestone
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const prNumber = ${{ inputs.pr_number }};
|
|
|
|
/*
|
|
* Get the base branch of the PR.
|
|
*/
|
|
const { data: pullRequest } =
|
|
await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: prNumber
|
|
});
|
|
const baseBranch = pullRequest.base.ref;
|
|
|
|
/*
|
|
* 1. Return early if base is main branch. Milestone is already
|
|
* managed and probably done when merging to main.
|
|
*/
|
|
if (baseBranch === 'main') {
|
|
core.info('PR targets main. Milestone is managed separately.');
|
|
core.setOutput('target_milestone', '');
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Helper function to set the target milestone output.
|
|
*/
|
|
const setTargetMilestoneOutput = (targetMilestone) => {
|
|
core.info(`Target milestone: ${targetMilestone}`);
|
|
core.setOutput('target_milestone', targetMilestone);
|
|
};
|
|
|
|
/*
|
|
* 2. If PR targets a release-candidate branch (for example 9.1.0.rc),
|
|
* set milestone to the release version prefix (for example 9.1.0)
|
|
* and return early.
|
|
*/
|
|
if (baseBranch.endsWith('.rc')) {
|
|
const targetMilestone = baseBranch.replace(/\.rc$/, '');
|
|
|
|
core.info(
|
|
`PR targets release-candidate branch "${baseBranch}". ` +
|
|
`Using milestone "${targetMilestone}".`
|
|
);
|
|
|
|
setTargetMilestoneOutput(targetMilestone);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* 3. If PR targets a branch that is not developer, do nothing.
|
|
*/
|
|
if (baseBranch !== 'developer') {
|
|
core.info('PR does not target developer branch. Skipping milestone management.');
|
|
core.setOutput('target_milestone', '');
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* 4. If PR targets developer, check "Equivalent PRs" in the PR body.
|
|
* If an equivalent PR targets an RC branch (for example 9.1.0.rc),
|
|
* use the corresponding release milestone (for example 9.1.0).
|
|
*/
|
|
if (baseBranch === 'developer') {
|
|
const equivalentPrSectionMatch = pullRequest.body?.match(
|
|
/(^|\n)#{1,6}\s*Equivalent PRs\s*\n([\s\S]*?)(?=\n#{1,6}\s+\S|\s*$)/i
|
|
);
|
|
|
|
const equivalentPrNumbers =
|
|
equivalentPrSectionMatch?.[2]
|
|
? Array.from(
|
|
equivalentPrSectionMatch[2].matchAll(/#(\d+)/g),
|
|
match => Number(match[1])
|
|
)
|
|
: [];
|
|
|
|
for (const equivalentPrNumber of equivalentPrNumbers) {
|
|
if (equivalentPrNumber === prNumber) {
|
|
continue;
|
|
}
|
|
|
|
const { data: equivalentPr } =
|
|
await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: equivalentPrNumber
|
|
});
|
|
|
|
const equivalentBaseBranch = equivalentPr.base.ref;
|
|
|
|
if (!equivalentBaseBranch.endsWith('.rc')) {
|
|
continue;
|
|
}
|
|
|
|
const targetMilestone =
|
|
equivalentBaseBranch.replace(/\.rc$/, '');
|
|
|
|
core.info(
|
|
`Developer PR references RC PR #${equivalentPrNumber} ` +
|
|
`(${equivalentBaseBranch}). Using milestone "${targetMilestone}".`
|
|
);
|
|
|
|
setTargetMilestoneOutput(targetMilestone);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 5. Read release targets through the GitHub API
|
|
* from the base branch of PR.
|
|
*/
|
|
const { data: file } =
|
|
await github.rest.repos.getContent({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
path: '.github/release-targets.yaml',
|
|
ref: baseBranch
|
|
});
|
|
|
|
const releaseTargetsFile =
|
|
Buffer.from(file.content, 'base64').toString('utf8');
|
|
|
|
const getTarget = (name) => {
|
|
const match = releaseTargetsFile.match(
|
|
new RegExp(`^${name}:\\s*["']?([^"'\\s]+)["']?`, 'm')
|
|
);
|
|
|
|
if (!match) {
|
|
core.setFailed(
|
|
`Release target "${name}" was not found.`
|
|
);
|
|
return null;
|
|
}
|
|
|
|
return match[1];
|
|
};
|
|
|
|
const major = getTarget('major');
|
|
const minor = getTarget('minor');
|
|
const bugFix = getTarget('bug_fix');
|
|
|
|
if (!major || !minor || !bugFix) {
|
|
core.setFailed(
|
|
'Required release targets (major, minor, bug_fix) could not be resolved from yaml file.'
|
|
);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Get current PR labels.
|
|
*/
|
|
const { data: labels } =
|
|
await github.rest.issues.listLabelsOnIssue({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber
|
|
});
|
|
|
|
const labelNames =
|
|
labels.map(label => label.name);
|
|
|
|
/*
|
|
* Determine the milestone.
|
|
*
|
|
* Breaking API has highest priority.
|
|
*/
|
|
let targetMilestone;
|
|
|
|
if (labelNames.includes('Breaking API')) {
|
|
targetMilestone = major;
|
|
} else if (labelNames.includes('Feature')) {
|
|
targetMilestone = minor;
|
|
} else if (
|
|
labelNames.includes('Bug Fix') ||
|
|
labelNames.includes('Infrastructure')
|
|
) {
|
|
targetMilestone = bugFix;
|
|
} else {
|
|
core.setFailed(
|
|
'No milestone-related labels found.'
|
|
);
|
|
return;
|
|
}
|
|
|
|
setTargetMilestoneOutput(targetMilestone);
|
|
|
|
- name: Set milestone
|
|
if: steps.determine-milestone.outputs.target_milestone != ''
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const prNumber = ${{ inputs.pr_number }};
|
|
const targetMilestone = '${{ steps.determine-milestone.outputs.target_milestone }}';
|
|
|
|
const { data: milestones } =
|
|
await github.rest.issues.listMilestones({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
state: 'open'
|
|
});
|
|
|
|
const milestone = milestones.find(
|
|
milestone => milestone.title === targetMilestone
|
|
);
|
|
|
|
if (!milestone) {
|
|
core.setFailed(
|
|
`Milestone "${targetMilestone}" was not found.`
|
|
);
|
|
return;
|
|
}
|
|
|
|
await github.rest.issues.update({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
milestone: milestone.number
|
|
});
|
|
|
|
core.info(
|
|
`Milestone set to "${targetMilestone}".`
|
|
);
|