chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import fs from "fs";
|
||||
import { Octokit } from "octokit";
|
||||
import { parseReleases } from "auto-changelog/src/releases.js";
|
||||
import { fetchTags } from "auto-changelog/src/tags.js";
|
||||
import { fetchRemote } from "auto-changelog/src/remote.js";
|
||||
import * as toml from "@iarna/toml";
|
||||
|
||||
import "zx/globals";
|
||||
|
||||
// if (!process.env.GITHUB_TOKEN) {
|
||||
// throw new Error("Missing GITHUB_TOKEN");
|
||||
// }
|
||||
|
||||
const IS_NIGHTLY = process.argv.indexOf("--nightly") > -1;
|
||||
|
||||
const PKG_VERSION = JSON.parse(fs.readFileSync("./package.json")).version.match(
|
||||
/[0-9]+\.[0-9]+\.[0-9]+/,
|
||||
)[0];
|
||||
|
||||
const GIT_REV = await $`git show --no-patch --format=%ct HEAD`;
|
||||
|
||||
console.log();
|
||||
|
||||
const NEW_VERSION = IS_NIGHTLY
|
||||
? `${PKG_VERSION}-dev${+new Date(parseInt(GIT_REV.toString()))}`
|
||||
: PKG_VERSION;
|
||||
|
||||
/**
|
||||
* A Github data fetching cache designed to run in parallel with changelog formatting.
|
||||
* When a SHA is requested, it is looked up in a local cache, and if it isn't there,
|
||||
* the next Github API page is awaited. Requests are always triggered in advance.
|
||||
*/
|
||||
class GithubPRCache {
|
||||
constructor() {
|
||||
this.prs = new Map();
|
||||
this.page = 1;
|
||||
this.octokit = new Octokit({
|
||||
auth: process.env.GITHUB_TOKEN,
|
||||
});
|
||||
this.next();
|
||||
}
|
||||
async next() {
|
||||
let ret;
|
||||
if (this._next_req) {
|
||||
ret = await this._next_req;
|
||||
}
|
||||
console.log(
|
||||
`Fetching Github commits ${(this.page - 1) * 100} - ${
|
||||
this.page * 100 - 1
|
||||
}`,
|
||||
);
|
||||
this._next_req = this.octokit.request(
|
||||
"GET /repos/{owner}/{repo}/pulls?state=closed&per_page={per_page}&page={page}",
|
||||
{
|
||||
owner: "perspective-dev",
|
||||
repo: "perspective",
|
||||
per_page: 100,
|
||||
page: this.page++,
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
async get(sha) {
|
||||
while (!this.prs.has(sha) && !this.failed) {
|
||||
const resp = await this.next();
|
||||
if (resp.data.length == 0) {
|
||||
this.failed = true;
|
||||
}
|
||||
for (const pr of resp.data) {
|
||||
this.prs.set(pr.merge_commit_sha, pr);
|
||||
}
|
||||
}
|
||||
return this.prs.get(sha);
|
||||
}
|
||||
}
|
||||
function template_group(label, rows, prs) {
|
||||
if (rows.length > 0) {
|
||||
const group_prs = rows
|
||||
.map((merge) => `- ${merge.message} [#${merge.id}](${merge.href})`)
|
||||
.join("\n");
|
||||
return `${label}\n\n${group_prs}\n`;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
function template_release(args) {
|
||||
const prs = Object.keys(args.row)
|
||||
.map((label) => template_group(label, args.row[label]))
|
||||
.filter((x) => x.length > 0)
|
||||
.join("\n");
|
||||
return `# [${args.release.title}](https://github.com/perspective-dev/perspective/releases/tag/${args.release.title})
|
||||
|
||||
_${args.release.niceDate}_ ([Full changelog](${args.release.href}))
|
||||
|
||||
${prs}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the changelog text from the output of `auto-changelog`, iteratively calling
|
||||
* Github's API when necessary to get label information for grouping.
|
||||
*
|
||||
* @param {*} json the output data from `auto-changelog`
|
||||
* @returns
|
||||
*/
|
||||
async function template(json) {
|
||||
const cache = new GithubPRCache();
|
||||
let changelog = "";
|
||||
for (const release of json) {
|
||||
const row = {
|
||||
"**Breaking**": [],
|
||||
Features: [],
|
||||
Fixes: [],
|
||||
Misc: [],
|
||||
};
|
||||
for (const merge of release.merges) {
|
||||
const pr = await cache.get(merge.commit.hash);
|
||||
merge.pr = pr;
|
||||
if (pr) {
|
||||
const labels = pr.labels.map((x) => x.name);
|
||||
if (labels.indexOf("breaking") > -1) {
|
||||
row["**Breaking**"].push(merge);
|
||||
} else if (labels.indexOf("enhancement") > -1) {
|
||||
row.Features.push(merge);
|
||||
} else if (labels.indexOf("bug") > -1) {
|
||||
row.Fixes.push(merge);
|
||||
} else {
|
||||
row.Misc.push(merge);
|
||||
}
|
||||
} else {
|
||||
row.Misc.push(merge);
|
||||
}
|
||||
}
|
||||
changelog += template_release({
|
||||
row,
|
||||
release,
|
||||
});
|
||||
}
|
||||
return changelog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the `CHANGELOG.md` file from Github API.
|
||||
*/
|
||||
async function update_changelog() {
|
||||
let options = {
|
||||
remote: "origin",
|
||||
commitLimit: 10000,
|
||||
backfillLimit: 10000,
|
||||
tagPrefix: "",
|
||||
sortCommits: "relevance",
|
||||
appendGitLog: "",
|
||||
appendGitTag: "",
|
||||
latestVersion: NEW_VERSION,
|
||||
};
|
||||
const remote = await fetchRemote(options);
|
||||
options = {
|
||||
...options,
|
||||
...remote,
|
||||
};
|
||||
console.log("Fetching tags…");
|
||||
const tags = await fetchTags(options);
|
||||
console.log(`${tags.length} version tags found…`);
|
||||
const onParsed = ({ title }) => console.log(`Fetched ${title}…`);
|
||||
const json = await parseReleases(tags, options, onParsed);
|
||||
const changelog = await template(json);
|
||||
fs.writeFileSync("./CHANGELOG.md", changelog);
|
||||
$.sync`git add CHANGELOG.md`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all project `package.json` files.
|
||||
*/
|
||||
async function update_package_jsons() {
|
||||
const pkg = JSON.parse(fs.readFileSync("./package.json"));
|
||||
pkg.version = NEW_VERSION;
|
||||
const pkg_json = `${JSON.stringify(pkg, undefined, 4)}\n`;
|
||||
fs.writeFileSync("./package.json", pkg_json);
|
||||
const packages = {};
|
||||
for (const ws of pkg.workspaces) {
|
||||
if (ws === "packages/jupyterlab" && IS_NIGHTLY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const path of glob.sync(`${ws}/package.json`, {
|
||||
sync: true,
|
||||
})) {
|
||||
const pkg = JSON.parse(fs.readFileSync(path));
|
||||
pkg.version = NEW_VERSION;
|
||||
fs.writeFileSync(path, JSON.stringify(pkg, undefined, 4) + "\n");
|
||||
packages[pkg.name] = {
|
||||
pkg,
|
||||
path,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const cargo = toml.parse(fs.readFileSync("./Cargo.toml"));
|
||||
for (const pkg of cargo.workspace.members) {
|
||||
const crate = toml.parse(fs.readFileSync(`./${pkg}/Cargo.toml`));
|
||||
if (crate?.package.version) {
|
||||
crate.package.version = NEW_VERSION;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(crate?.dependencies)) {
|
||||
if (key.startsWith("perspective")) {
|
||||
crate.dependencies[key].version = NEW_VERSION;
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(`./${pkg}/Cargo.toml`, toml.stringify(crate));
|
||||
}
|
||||
|
||||
// if (!IS_NIGHTLY) {
|
||||
const pyproject = toml.parse(
|
||||
fs.readFileSync(`./rust/perspective-python/pyproject.toml`),
|
||||
);
|
||||
|
||||
pyproject.tool.maturin.data = `perspective_python-${NEW_VERSION}.data`;
|
||||
fs.writeFileSync(
|
||||
`./rust/perspective-python/pyproject.toml`,
|
||||
toml.stringify(pyproject),
|
||||
);
|
||||
// }
|
||||
}
|
||||
|
||||
if (!IS_NIGHTLY) {
|
||||
if (!process.env.GITHUB_TOKEN) {
|
||||
throw new Error("Missing GITHUB_TOKEN");
|
||||
}
|
||||
|
||||
await update_changelog();
|
||||
}
|
||||
|
||||
await update_package_jsons();
|
||||
Reference in New Issue
Block a user