Remove comment-on-release workflow (#2985)
This commit is contained in:
parent
587340279e
commit
e9cd1692b0
1 changed files with 0 additions and 229 deletions
229
.github/workflows/comment-on-release.yml
vendored
229
.github/workflows/comment-on-release.yml
vendored
|
|
@ -1,229 +0,0 @@
|
||||||
name: Comment on PRs in Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
comment-on-prs:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: Get previous release
|
|
||||||
id: previous_release
|
|
||||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
||||||
env:
|
|
||||||
CURRENT_TAG: ${{ github.event.release.tag_name }}
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const currentTag = process.env.CURRENT_TAG;
|
|
||||||
|
|
||||||
// Paginate: with two release lines publishing interleaved, the
|
|
||||||
// previous release on this line can sit far down the list.
|
|
||||||
const releases = await github.paginate(github.rest.repos.listReleases, {
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
per_page: 100
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!releases.some(r => r.tag_name === currentTag)) {
|
|
||||||
console.log('Current release not found in list');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const major = tag => (tag.match(/^v?(\d+)/) || [])[1];
|
|
||||||
|
|
||||||
if (major(currentTag) === undefined) {
|
|
||||||
console.log(`Cannot parse a major version from ${currentTag}; skipping comments`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The list is ordered by release creation date, which does not
|
|
||||||
// reliably reflect tag topology (for example, a release published
|
|
||||||
// from a long-lived draft keeps its draft creation date). Instead
|
|
||||||
// of trusting list order, compare every same-major release and
|
|
||||||
// pick the nearest ancestor of the current tag: the one the
|
|
||||||
// smallest number of commits behind it. The major check runs
|
|
||||||
// first so cross-line candidates cost no API calls; per_page=1
|
|
||||||
// because only status/ahead_by are needed here (the commits are
|
|
||||||
// fetched in the next step). For the first release of a new major
|
|
||||||
// line there is no same-line predecessor, and we skip commenting
|
|
||||||
// rather than compare across the entire new line's history.
|
|
||||||
let best = null;
|
|
||||||
for (const candidate of releases) {
|
|
||||||
if (candidate.tag_name === currentTag || candidate.draft) continue;
|
|
||||||
if (major(candidate.tag_name) !== major(currentTag)) continue;
|
|
||||||
|
|
||||||
let comparison;
|
|
||||||
try {
|
|
||||||
({ data: comparison } = await github.rest.repos.compareCommits({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
base: candidate.tag_name,
|
|
||||||
head: currentTag,
|
|
||||||
per_page: 1
|
|
||||||
}));
|
|
||||||
} catch (error) {
|
|
||||||
// Tolerate only candidates whose tag no longer resolves;
|
|
||||||
// anything else (rate limits, server errors) must fail the
|
|
||||||
// job rather than silently produce a wrong comparison base.
|
|
||||||
if (error.status === 404) {
|
|
||||||
console.log(`Skipping ${candidate.tag_name}: tag does not resolve`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'identical' covers a release re-cut on the same commit; it
|
|
||||||
// yields an empty commit range downstream, hence no comments.
|
|
||||||
if (comparison.status !== 'ahead' && comparison.status !== 'identical') {
|
|
||||||
console.log(`Skipping ${candidate.tag_name}: not an ancestor of ${currentTag} (status: ${comparison.status})`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best === null || comparison.ahead_by < best.aheadBy) {
|
|
||||||
best = { tagName: candidate.tag_name, aheadBy: comparison.ahead_by };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best === null) {
|
|
||||||
console.log(`No previous release found for ${currentTag} on its major line (it may be the first); skipping comments`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Found previous release: ${best.tagName} (${best.aheadBy} commits behind ${currentTag})`);
|
|
||||||
return best.tagName;
|
|
||||||
|
|
||||||
- name: Get merged PRs between releases
|
|
||||||
id: get_prs
|
|
||||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
||||||
env:
|
|
||||||
CURRENT_TAG: ${{ github.event.release.tag_name }}
|
|
||||||
PREVIOUS_TAG_JSON: ${{ steps.previous_release.outputs.result }}
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const currentTag = process.env.CURRENT_TAG;
|
|
||||||
const previousTag = JSON.parse(process.env.PREVIOUS_TAG_JSON);
|
|
||||||
|
|
||||||
if (!previousTag) {
|
|
||||||
console.log('No previous release found, skipping');
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Finding PRs between ${previousTag} and ${currentTag}`);
|
|
||||||
|
|
||||||
// Get commits between previous and current release. A single
|
|
||||||
// compare response caps the commit list, so paginate — but bound
|
|
||||||
// the total: a range this large means a mis-selected base, and
|
|
||||||
// commenting on hundreds of PRs is worse than commenting on none.
|
|
||||||
const MAX_COMMITS = 250;
|
|
||||||
const commits = [];
|
|
||||||
for (let page = 1; ; page++) {
|
|
||||||
const { data: comparison } = await github.rest.repos.compareCommits({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
base: previousTag,
|
|
||||||
head: currentTag,
|
|
||||||
per_page: 100,
|
|
||||||
page
|
|
||||||
});
|
|
||||||
commits.push(...comparison.commits);
|
|
||||||
if (commits.length > MAX_COMMITS) {
|
|
||||||
console.log(`Range ${previousTag}...${currentTag} exceeds ${MAX_COMMITS} commits; skipping comments`);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
if (comparison.commits.length < 100) break;
|
|
||||||
}
|
|
||||||
console.log(`Found ${commits.length} commits`);
|
|
||||||
|
|
||||||
// Get PRs associated with each commit using GitHub API
|
|
||||||
const prNumbers = new Set();
|
|
||||||
|
|
||||||
for (const commit of commits) {
|
|
||||||
try {
|
|
||||||
const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
commit_sha: commit.sha
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const pr of prs) {
|
|
||||||
if (pr.merged_at) {
|
|
||||||
prNumbers.add(pr.number);
|
|
||||||
console.log(`Found merged PR: #${pr.number}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(`Failed to get PRs for commit ${commit.sha}: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Found ${prNumbers.size} merged PRs`);
|
|
||||||
return Array.from(prNumbers);
|
|
||||||
|
|
||||||
- name: Comment on PRs
|
|
||||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
||||||
env:
|
|
||||||
PR_NUMBERS_JSON: ${{ steps.get_prs.outputs.result }}
|
|
||||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
||||||
RELEASE_URL: ${{ github.event.release.html_url }}
|
|
||||||
RELEASE_IS_PRERELEASE: ${{ github.event.release.prerelease }}
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const prNumbers = JSON.parse(process.env.PR_NUMBERS_JSON);
|
|
||||||
const releaseTag = process.env.RELEASE_TAG;
|
|
||||||
const releaseUrl = process.env.RELEASE_URL;
|
|
||||||
// Trust the tag as well as the flag, in case the release manager
|
|
||||||
// forgets to tick the pre-release checkbox.
|
|
||||||
const isPrerelease = process.env.RELEASE_IS_PRERELEASE === 'true' || /\d(a|b|rc)\d/.test(releaseTag);
|
|
||||||
const releaseKind = isPrerelease ? 'pre-release' : 'release';
|
|
||||||
|
|
||||||
const comment = `This pull request is included in ${releaseKind} [${releaseTag}](${releaseUrl})`;
|
|
||||||
|
|
||||||
let commentedCount = 0;
|
|
||||||
|
|
||||||
for (const prNumber of prNumbers) {
|
|
||||||
try {
|
|
||||||
// Check if we've already commented on this PR for this
|
|
||||||
// release. Paginate: comments are returned oldest-first, so
|
|
||||||
// on a busy PR an earlier bot comment is exactly what would
|
|
||||||
// fall off a single page.
|
|
||||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: prNumber,
|
|
||||||
per_page: 100
|
|
||||||
});
|
|
||||||
|
|
||||||
const alreadyCommented = comments.some(c =>
|
|
||||||
c.user.type === 'Bot' && c.body.includes(`[${releaseTag}]`)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (alreadyCommented) {
|
|
||||||
console.log(`Skipping PR #${prNumber} - already commented for ${releaseTag}`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: prNumber,
|
|
||||||
body: comment
|
|
||||||
});
|
|
||||||
commentedCount++;
|
|
||||||
console.log(`Successfully commented on PR #${prNumber}`);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Failed to comment on PR #${prNumber}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Commented on ${commentedCount} of ${prNumbers.length} PRs`);
|
|
||||||
Loading…
Reference in a new issue