Chore: update changelog workflow (#90608)
* try integrating * pass tags * change section order * use better terminology * one more attempt * keep delimiters * attempt to patch changelog * quotes, bash quotes... * use proper content file * parens around date * time for a pr * first checkout, then create user * add latest input * git push * use square brackets * formatting * update release-pr * fix typo * try sparse checkout * fetch depth zero * clean up after changelog generator
This commit is contained in:
1 parent
8f54e3bfb7
commit
f8b092aba6
4 files changed
+171
-51
No files matched your search
@@ -1,13 +1,13 @@
|
||||
name: Changelog generator
|
||||
description: Generates and publishes a changelog for the given release version
|
||||
inputs:
|
||||
version:
|
||||
description: Version number
|
||||
target:
|
||||
description: Target tag, branch or commit hash for the changelog
|
||||
required: true
|
||||
prev_version:
|
||||
description: Previous version number
|
||||
previous:
|
||||
description: Previous tag, branch or commit hash to start changelog from
|
||||
required: false
|
||||
token:
|
||||
github_token:
|
||||
description: GitHub token with read/write access to all necessary repositories
|
||||
required: true
|
||||
output_file:
|
||||
|
||||
@@ -52,17 +52,20 @@ const getPreviousVersion = async (version) => {
|
||||
.filter((tag) => tag)
|
||||
.sort(semverCompare)
|
||||
.find((tag) => semverCompare(tag, semverParse(version)) > 0);
|
||||
return prev;
|
||||
if (!prev) {
|
||||
throw `Could not find previous git tag for ${version}`;
|
||||
}
|
||||
return prev[4];
|
||||
};
|
||||
|
||||
// A helper for Github GraphQL API endpoint
|
||||
const graphql = async (token, query, variables) => {
|
||||
const graphql = async (ghtoken, query, variables) => {
|
||||
const { env } = process;
|
||||
const results = await fetch('https://api.github.com/graphql', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
Authorization: `Bearer ${ghtoken}`,
|
||||
},
|
||||
body: JSON.stringify({ query, variables }),
|
||||
});
|
||||
@@ -76,7 +79,7 @@ const graphql = async (token, query, variables) => {
|
||||
// "commitish" items and get a list of PRs in between them.
|
||||
const getCommitishDate = async (name, owner, target) => {
|
||||
const result = await graphql(
|
||||
token,
|
||||
ghtoken,
|
||||
`
|
||||
query getCommitDate($owner: String!, $name: String!, $target: String!) {
|
||||
repository(owner: $owner, name: $name) {
|
||||
@@ -96,9 +99,8 @@ const getCommitishDate = async (name, owner, target) => {
|
||||
// Using Github GraphQL API get a list of PRs between the two "commitish" items.
|
||||
// This resoves the "since" item's timestamp first and iterates over all PRs
|
||||
// till "target" using naïve pagination.
|
||||
const getHistory = async (name, owner, target, since) => {
|
||||
const sinceDate = await getCommitishDate(name, owner, since);
|
||||
LOG(`Fetching ${owner}/${name} PRs since ${since} (${sinceDate}) till ${target}`);
|
||||
const getHistory = async (name, owner, target, sinceDate) => {
|
||||
LOG(`Fetching ${owner}/${name} PRs since ${sinceDate} till ${target}`);
|
||||
const query = `
|
||||
query findCommitsWithAssociatedPullRequests(
|
||||
$name: String!
|
||||
@@ -150,7 +152,7 @@ const getHistory = async (name, owner, target, since) => {
|
||||
let cursor;
|
||||
let nodes = [];
|
||||
for (;;) {
|
||||
const result = await graphql(token, query, {
|
||||
const result = await graphql(ghtoken, query, {
|
||||
name,
|
||||
owner,
|
||||
target,
|
||||
@@ -173,11 +175,11 @@ const getHistory = async (name, owner, target, since) => {
|
||||
// feature, deprecation, breaking change and plugin fixes/enhancements).
|
||||
//
|
||||
// PR grouping relies on Github labels only, not on the PR contents.
|
||||
const getChangeLogItems = async (name, owner, from, to) => {
|
||||
const getChangeLogItems = async (name, owner, sinceDate, to) => {
|
||||
// check if a node contains a certain label
|
||||
const hasLabel = ({ labels }, label) => labels.nodes.some(({ name }) => name === label);
|
||||
// get all the PRs between the two "commitish" items
|
||||
const history = await getHistory(name, owner, to, from);
|
||||
const history = await getHistory(name, owner, to, sinceDate);
|
||||
|
||||
const items = history.flatMap((node) => {
|
||||
// discard PRs without a "changelog" label
|
||||
@@ -216,20 +218,26 @@ const getChangeLogItems = async (name, owner, from, to) => {
|
||||
// ======================================================
|
||||
|
||||
LOG(`Changelog action started`);
|
||||
const version = process.argv[2] || process.env.INPUT_VERSION;
|
||||
LOG(`Target version: ${version}`);
|
||||
const prevVersion = process.argv[3] || process.env.INPUT_PREV_VERSION || (await getPreviousVersion(version));
|
||||
LOG(`Previous version: ${prevVersion}`);
|
||||
const token = process.env.GITHUB_TOKEN || process.env.INPUT_TOKEN;
|
||||
|
||||
if (!token) {
|
||||
throw 'GITHUB_TOKEN is not set and "token" input is empty';
|
||||
const ghtoken = process.env.GITHUB_TOKEN || process.env.INPUT_GITHUB_TOKEN;
|
||||
if (!ghtoken) {
|
||||
throw 'GITHUB_TOKEN is not set and "github_token" input is empty';
|
||||
}
|
||||
|
||||
const target = process.argv[2] || process.env.INPUT_TARGET;
|
||||
LOG(`Target tag/branch/commit: ${target}`);
|
||||
|
||||
const previous = process.argv[3] || process.env.INPUT_PREVIOUS || (await getPreviousVersion(target));
|
||||
|
||||
LOG(`Previous tag/commit: ${previous}`);
|
||||
|
||||
const sinceDate = await getCommitishDate('grafana', 'grafana', previous);
|
||||
LOG(`Previous tag/commit timestamp: ${sinceDate}`);
|
||||
|
||||
// Get all changelog items from Grafana OSS
|
||||
const oss = await getChangeLogItems('grafana', 'grafana', prevVersion, version);
|
||||
const oss = await getChangeLogItems('grafana', 'grafana', sinceDate, target);
|
||||
// Get all changelog items from Grafana Enterprise
|
||||
const entr = await getChangeLogItems('grafana-enterprise', 'grafana', prevVersion, version);
|
||||
const entr = await getChangeLogItems('grafana-enterprise', 'grafana', sinceDate, target);
|
||||
|
||||
LOG(`Found OSS PRs: ${oss.length}`);
|
||||
LOG(`Found Enterprise PRs: ${entr.length}`);
|
||||
@@ -251,13 +259,10 @@ const changelog = [...oss, ...entr]
|
||||
return changelog;
|
||||
},
|
||||
{
|
||||
version,
|
||||
breaking: [],
|
||||
plugins: [],
|
||||
bugfixes: [],
|
||||
features: [],
|
||||
// looks like JS doesn't have a nicer way to format date as YYYY-MM-DD
|
||||
releaseDate: new Date().toISOString().split('T')[0],
|
||||
}
|
||||
);
|
||||
|
||||
@@ -287,12 +292,10 @@ ${items
|
||||
`;
|
||||
|
||||
// Render all present sections for the given changelog
|
||||
return `# ${changelog.version} (${changelog.releaseDate})
|
||||
|
||||
${section('Breaking changes', changelog.breaking)}
|
||||
return `${section('Features and enhancements', changelog.features)}
|
||||
${section('Bug fixes', changelog.bugfixes)}
|
||||
${section('Breaking changes', changelog.breaking)}
|
||||
${section('Plugin development fixes & changes', changelog.plugins)}
|
||||
${section('Features and enhancements', changelog.features)}
|
||||
`;
|
||||
};
|
||||
|
||||
@@ -314,4 +317,3 @@ if (process.env.INPUT_OUTPUT_FILE) {
|
||||
LOG(`Output to ${process.env.INPUT_OUTPUT_FILE}`);
|
||||
writeFileSync(process.env.INPUT_OUTPUT_FILE, md);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user