Simplified and more comprehensive changelog generation (#3042)

This commit is contained in:
Joe Schmitt 2022-12-09 09:29:45 -08:00 коммит произвёл GitHub
Родитель dd2ec0c9e0
Коммит 812d15c4ba
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 47 добавлений и 32 удалений

Просмотреть файл

@ -16,9 +16,6 @@ inputs:
branch_name:
description: 'The branch to generate release notes for.'
required: true
additional_branch:
description: "Include PRs from an additional branch"
required: false
runs:
using: 'node16'

Просмотреть файл

@ -24,7 +24,6 @@ async function run() {
const buildDescription = core.getInput("build_description", { required: true });
const lastReleaseDate = core.getInput("last_release_date", { required: true });
const branch = core.getInput("branch_name", { required: true });
const additional_branch = core.getInput("additional_branch", { required: false });
const repoOwner = github.context.payload.repository.owner.login;
const repoName = github.context.payload.repository.name;
@ -44,7 +43,7 @@ async function run() {
inChangelog: false
}
];
const changelog = await generateChangelog(octokit, branch, additional_branch, repoOwner, repoName, lastReleaseDate, significantLabels);
const changelog = await generateChangelog(octokit, branch, repoOwner, repoName, lastReleaseDate, significantLabels);
const monikerDescriptions = generateMonikerDescriptions(significantLabels);
const releaseNotes = await generateReleaseNotes(path.join(__dirname, "releaseNotes.template.md"), buildDescription, changelog, monikerDescriptions);
@ -67,12 +66,13 @@ function generateMonikerDescriptions(significantLabels) {
return descriptions.join(" \\\n");
}
async function generateChangelog(octokit, branchName, additionalBranch, repoOwner, repoName, minMergeDate, significantLabels) {
let prs = await getPRs(octokit, branchName, additionalBranch, repoOwner, repoName, minMergeDate, UpdateReleaseNotesLabel);
async function getPrsToMention(octokit, branch, repoOwner, repoName, minMergeDate) {
// Identify potential PRs to mention the release notes.
let candidatePrs = await getPRs(octokit, repoOwner, repoName, minMergeDate, UpdateReleaseNotesLabel);
// Resolve the backport PRs to their origin PRs
const maxRecursion = 3;
const backportPrs = await getPRs(octokit, branchName, additionalBranch, repoOwner, repoName, minMergeDate, BackportLabel);
const backportPrs = await getPRs(octokit, repoOwner, repoName, minMergeDate, BackportLabel);
for (const pr of backportPrs) {
const originPr = await resolveBackportPrToReleaseNotePr(octokit, pr, repoOwner, repoName, minMergeDate, maxRecursion);
if (originPr !== undefined) {
@ -81,10 +81,48 @@ async function generateChangelog(octokit, branchName, additionalBranch, repoOwne
// the information from the origin PR.
originPr.number = pr.number;
originPr.html_url = pr.html_url;
prs.push(originPr);
candidatePrs.push(originPr);
}
}
// Create a lookup table for every commit hash this release includes.
const commitObjects = await octokit.paginate(octokit.rest.repos.listCommits, {
owner: repoOwner,
repo: repoName,
sha: branch, // To filter by branch, set the sha field to the branch name.
since: minMergeDate
});
let commitHashesInRelease = new Set();
for (const commit of commitObjects) {
commitHashesInRelease.add(commit.sha);
}
let prs = [];
for (const pr of candidatePrs) {
// Get a fully-qualified version of the pr that has all of the relevant information,
// including the merge/squash/rebase commit.
const fqPr = (await octokit.rest.pulls.get({
owner: repoOwner,
repo: repoName,
pull_number: pr.number
}))?.data;
if (commitHashesInRelease.has(fqPr.merge_commit_sha)) {
console.log(`Including: #${fqPr.number}`);
prs.push(pr);
} else {
console.log(`Skipping: #${fqPr.number} --- ${fqPr.merge_commit_sha}`);
}
}
return prs;
}
async function generateChangelog(octokit, branch, repoOwner, repoName, minMergeDate, significantLabels) {
const prs = await getPrsToMention(octokit, branch, repoOwner, repoName, minMergeDate);
let changelog = [];
for (const pr of prs) {
let labelIndicesSeen = [];
@ -130,11 +168,8 @@ async function generateReleaseNotes(templatePath, buildDescription, changelog, m
return releaseNotes.trim();
}
async function getPRs(octokit, branchName, additionalBranch, repoOwner, repoName, minMergeDate, labelFilter) {
let searchQuery = `is:pr is:merged label:${labelFilter} repo:${repoOwner}/${repoName} base:${branchName} merged:>=${minMergeDate}`;
if (additionalBranch !== undefined) {
searchQuery += ` base:${additionalBranch}`
}
async function getPRs(octokit, repoOwner, repoName, minMergeDate, labelFilter) {
let searchQuery = `is:pr is:merged label:${labelFilter} repo:${repoOwner}/${repoName} merged:>=${minMergeDate}`;
console.log(searchQuery);
return await octokit.paginate(octokit.rest.search.issuesAndPullRequests, {

17
.github/workflows/generate-release-notes.yml поставляемый
Просмотреть файл

@ -3,11 +3,6 @@ run-name: '[${{ github.ref_name }}] Generate release notes'
on:
workflow_dispatch:
inputs:
include_main_prs:
description: 'Include PRs that were merged into main?'
required: true
type: boolean
permissions:
contents: write
@ -69,7 +64,6 @@ jobs:
ref: main
- name: Generate release notes
if: ${{ inputs.include_main_prs != true }}
uses: ./.github/actions/generate-release-notes
with:
output: ${{ env.release_note_path }}
@ -78,17 +72,6 @@ jobs:
auth_token: ${{ secrets.GITHUB_TOKEN }}
branch_name: ${{ github.ref_name }}
- name: Generate release notes (main merged)
if: ${{ inputs.include_main_prs }}
uses: ./.github/actions/generate-release-notes
with:
output: ${{ env.release_note_path }}
last_release_date: ${{ env.last_release_date }}
build_description: ${{ env.friendly_release_name }}
auth_token: ${{ secrets.GITHUB_TOKEN }}
branch_name: ${{ github.ref_name }}
additional_branch: 'main'
- name: Open PR
uses: ./.github/actions/open-pr
with:

Просмотреть файл

@ -96,7 +96,7 @@ The nightly image is `mcr.microsoft.com/dotnet/nightly/monitor`. The tag list is
## Release to nuget.org and Add GitHub Release
1. Run the [Generate release notes](https://github.com/dotnet/dotnet-monitor/actions/workflows/generate-release-notes.yml) workflow, setting `Use workflow from` to the release branch and checking `Include PRs that were merged into main?` if you merged `main` into the release branch. Review and merge in the PR created by this workflow.
1. Run the [Generate release notes](https://github.com/dotnet/dotnet-monitor/actions/workflows/generate-release-notes.yml) workflow, setting `Use workflow from` to the release branch. Review and merge in the PR created by this workflow.
1. Start [release pipeline](https://dev.azure.com/dnceng/internal/_release?_a=releases&view=mine&definitionId=105). Allow the stages to trigger automatically (do not check the boxes in the associated dropdown). During creation of the release you must select the dotnet-monitor build to release from the list of available builds. This must be a build with the tag `MonitorRelease` and the associated `MonitorRelease` artifact (set `dotnet-monitor_build` to the pipeline run of `dotnet monitor` that is being released; set `dotnet-monitor_source` to the latest commit from `main`).
1. The release will start the stage "Pre-Release Verification"; this will check that the above steps were done as expected. The name of the release will be updated automatically.
1. Approve the sign-off step the day before the release after 8:45 AM PDT, when ready to publish.