Commit dba8aac6 authored by Robert Knight's avatar Robert Knight

Remove CHANGELOG from source tree

The client deployment process currently involves a commit to master to
update the CHANGELOG and version in package.json. This creates a problem
when trying to deploy a build that is not the latest release of master.
It also creates other failure modes that are not really necessary.

As a first step to resolving this problem, remove the changelog in the source
tree. The notes attached to the GitHub release will suffice, together
with any handwritten updates that developers post in #changelog in
Slack.

 - Remove CHANGELOG.md and scripts to generate it from source tree
 - Remove changelog references from build process
 - Change GitHub release script to generate the change list directly
   instead of reading it from CHANGELOG.md
 - Change the client's dev server to use the Code of Conduct instead of
   the changelog as a text source for the test page
parent dce31fdf
This diff is collapsed.
......@@ -145,16 +145,14 @@ node {
echo https://${env.GITHUB_USERNAME}:${env.GITHUB_TOKEN}@github.com >> \$HOME/.git-credentials
"""
// Fetch information about tags so that changelog generation script
// can produce diff since last tag. Also remove local tags that no
// longer exist on the remote.
// Update local information about tags to match the remote,
// including removing any local tags that no longer exist.
//
// The `--prune-tags` option is not supported in Git 2.11 so we
// use the workaround from https://github.com/git/git/commit/97716d217c1ea00adfc64e4f6bb85c1236d661ff
sh "git fetch --quiet --prune origin 'refs/tags/*:refs/tags/*' "
// Bump the package version, update the changelog and create the tag
// and GitHub release.
// Bump the package version and create the tag and GitHub release.
sh "yarn version --new-version ${newPkgVersion}"
// Publish the updated package to the npm registry.
......
......@@ -147,7 +147,7 @@
"lint": "eslint .",
"test": "gulp test",
"report-coverage": "codecov -f coverage/coverage-final.json",
"version": "make clean build/manifest.json && ./scripts/update-changelog.js && git add CHANGELOG.md",
"version": "make clean build/manifest.json",
"postversion": "./scripts/postversion.sh",
"prepublish": "yarn run build"
}
......
......@@ -9,59 +9,57 @@
* `v<VERSION>` where <VERSION> is the `version` field in package.json.
*/
const fs = require('fs');
const request = require('request');
const octokit = require('@octokit/rest')();
const pkg = require('../package.json');
const { changelistSinceTag } = require('./generate-change-list');
/**
* Extract the release notes for a given version from a markdown changelog in
* the format recommended by http://keepachangelog.com
*/
function extractReleaseNotes(changelog, version) {
const notes = changelog
.split(/(\n|^)## /)
.find(section => section.indexOf(`[${version}]`) === 0);
async function createGitHubRelease() {
// See https://github.com/docker/docker/issues/679
const GITHUB_ORG_REPO_PAT = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
if (!notes) {
throw new Error(`Failed to find release notes for v${pkg.version}`);
if (!pkg.repository || !pkg.repository.match(GITHUB_ORG_REPO_PAT)) {
throw new Error('package.json is missing a "repository" field of the form :owner/:repo');
}
return notes.split('\n').slice(1).join('\n');
}
if (!process.env.GITHUB_TOKEN) {
throw new Error('GITHUB_TOKEN env var is not set');
}
// See https://github.com/docker/docker/issues/679
const GITHUB_ORG_REPO_PAT = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
octokit.authenticate({
type: 'oauth',
token: process.env.GITHUB_TOKEN,
});
if (!pkg.repository || !pkg.repository.match(GITHUB_ORG_REPO_PAT)) {
throw new Error('package.json is missing a "repository" field of the form :owner/:repo');
}
const changes = await changelistSinceTag(octokit);
if (!process.env.GITHUB_TOKEN) {
throw new Error('GITHUB_TOKEN env var is not set');
}
const release = {
tag_name: `v${pkg.version}`,
name: `v${pkg.version}`,
body: changes,
draft: false,
prerelease: true,
};
const changelog = fs.readFileSync(require.resolve('../CHANGELOG.md')).toString();
const release = {
tag_name: `v${pkg.version}`,
name: `v${pkg.version}`,
body: extractReleaseNotes(changelog, pkg.version),
draft: false,
prerelease: true,
};
request.post({
uri: `https://api.github.com/repos/${pkg.repository}/releases`,
body: release,
json: true,
headers: {
Authorization: `token ${process.env.GITHUB_TOKEN}`,
'User-Agent': `${pkg.repository} Release Script`,
},
}, (err, rsp, body) => {
if (err || rsp.statusCode !== 201) {
const msg = err ? err.message : `${rsp.statusCode}: ${JSON.stringify(body)}`;
throw new Error(`Creating GitHub release failed: ${msg}`);
}
console.info(`Created GitHub release for v${pkg.version}`);
});
}
request.post({
uri: `https://api.github.com/repos/${pkg.repository}/releases`,
body: release,
json: true,
headers: {
Authorization: `token ${process.env.GITHUB_TOKEN}`,
'User-Agent': `${pkg.repository} Release Script`,
},
}, (err, rsp, body) => {
if (err || rsp.statusCode !== 201) {
const msg = err ? err.message : `${rsp.statusCode}: ${JSON.stringify(body)}`;
throw new Error(`Creating GitHub release failed: ${msg}`);
}
console.info(`Created GitHub release for v${pkg.version}`);
createGitHubRelease().catch(err => {
console.error('Failed to create release.', err);
process.exit(1);
});
......@@ -109,8 +109,7 @@ function formatChangeList(pullRequests) {
}
/**
* Return a markdown-formatted changelog of changes since a given Git tag,
* suitable for inclusion in a CHANGELOG.md file.
* Return a markdown-formatted changelog of changes since a given Git tag.
*
* If no Git tag is specified, default to the most recently created tag.
*
......
......@@ -15,8 +15,8 @@ function licenseText() {
return fs.readFileSync('./LICENSE', 'utf-8');
}
function changelogText() {
return fs.readFileSync('./CHANGELOG.md', 'utf-8');
function codeOfConductText() {
return fs.readFileSync('./CODE_OF_CONDUCT', 'utf-8');
}
/**
......@@ -58,15 +58,15 @@ function LiveReloadServer(port, config) {
</body>
</html>
`;
} else if (url.pathname === '/document/changelog') {
} else if (url.pathname === '/document/code_of_conduct') {
content = `
<html>
<head>
<meta charset="UTF-8">
<title>Hypothesis in-line frame document - Changelog</title>
<title>Hypothesis in-line frame document - Code of conduct</title>
</head>
<body>
<pre style="margin: 20px;">${changelogText()}</pre>
<pre style="margin: 20px;">${codeOfConductText()}</pre>
</body>
</html>
`;
......@@ -120,7 +120,7 @@ function LiveReloadServer(port, config) {
if (!iframeIsAdded) {
var iframe1 = document.querySelector('#iframe1');
var iframeNew = iframe1.cloneNode();
iframeNew.src = "/document/changelog";
iframeNew.src = "/document/code_of_conduct";
iframeNew.id = "iframe2";
iframeIsAdded = true;
document.querySelector('#iframe2-container').appendChild(iframeNew);
......
#!/usr/bin/env node
/**
* Replaces the "[Unreleased]" header for changes in the next release with the
* current package version from package.json
*/
'use strict';
const fs = require('fs');
const process = require('process');
const octokit = require('@octokit/rest')();
const pkg = require('../package.json');
const { changelistSinceTag } = require('./generate-change-list');
/**
* Update CHANGELOG.md with details of pull requests merged since the previous
* release.
*/
async function updateChangeLog() {
if (process.env.GITHUB_TOKEN) {
octokit.authenticate({
type: 'oauth',
token: process.env.GITHUB_TOKEN,
});
} else {
console.warn('GITHUB_TOKEN env var not set. API calls may hit rate limits.');
}
const dateStr = new Date().toISOString().slice(0,10);
const changelist = await changelistSinceTag(octokit);
const changelogPath = require.resolve('../CHANGELOG.md');
const changelog = fs.readFileSync(changelogPath).toString();
const updatedChangelog = changelog.replace(
'# Change Log',
`# Change Log
## [${pkg.version}] - ${dateStr}
### Changed
${changelist}
`);
fs.writeFileSync(changelogPath, updatedChangelog);
}
if (pkg.version.includes('-')) {
console.warn('Skipping changelog update for pre-release version');
return;
}
updateChangeLog();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment