UNPKG

@vis.gl/dev-tools

Version:

Dev tools for vis.gl frameworks

104 lines (94 loc) 2.99 kB
// This script is designed to work with automated release workflow // Requires env var GITHUB_TOKEN // See https://github.com/visgl/.github/blob/main/workflow-templates/release.yml import {execSync} from 'child_process'; import {readFileSync} from 'fs'; /** GitHub token with release access */ const token = process.env.GITHUB_TOKEN; if (!token) { // Do not proceed if publish token is not provided console.warn('Environment variable GITHUB_TOKEN not found, skipping release'); process.exit(0); } /** GitHub repo path, e.g. visgl/deck.gl */ const repository = getRepoName(); if (!repository) { // Do not proceed if repository is not defined console.warn('repository.url not defined in package.json, skipping release'); process.exit(0); } /** Version tag, e.g. v1.0.0 */ const tag = getGitTag(); if (!tag) { console.error('TAG NOT FOUND'); process.exit(1); } /** Description of this release, parsed from CHANGELOG.md */ const releaseNotes = getReleaseNotes(tag); if (releaseNotes === null) { console.error('CHANGELOG NOT FOUND'); process.exit(1); } createRelease(); async function createRelease() { // Publish release notes to GitHub // https://docs.github.com/en/rest/reference/repos#create-a-release const url = `https://api.github.com/repos/${repository}/releases`; const resp = await fetch(url, { method: 'POST', headers: { Authorization: `token ${token}`, Accept: 'application/vnd.github.v3+json' }, body: JSON.stringify({ tag_name: tag, name: tag, body: releaseNotes, prerelease: tag!.search(/alpha|beta|rc/) > 0 }) }); if (!resp.ok) { let reason: string = `POST to ${url} failed with code ${resp.status}`; try { const details = await resp.text(); reason += `\n${details}`; } catch { // ignore } throw new Error(reason); } console.log(`Release created: https://github.com/${repository}/releases/tag/${tag}`); } function getRepoName(): string | null { const packageInfo = JSON.parse(readFileSync('package.json', 'utf-8')); const repoUrl = packageInfo.repository?.url as string; if (!repoUrl || !repoUrl.includes('github.com')) { return null; } const m = repoUrl.match(/([\w\.\-]+\/[\w\.\-]+?)(.git)?$/); return m?.[1] ?? null; } function getGitTag(): string | null { try { return execSync('git describe --tags --exact-match HEAD', { stdio: [null, 'pipe', null], encoding: 'utf-8' }).trim(); } catch (err) { // not tagged return null; } } function getReleaseNotes(version: string): string | null { let changelog = readFileSync('CHANGELOG.md', 'utf-8'); const header = changelog.match(new RegExp(`^##.*\\bv?${version.replace('v', '')}\\b.*$`, 'm')); if (!header) { return null; } changelog = changelog.slice(header.index! + header[0].length); const endIndex = changelog.search(/^#/m); if (endIndex > 0) { changelog = changelog.slice(0, endIndex); } return changelog.trim(); }