commit 8dd161d4b2c280e4d27ed67dfbac480002a92d08
parent a5e38d3b8a0da5660e4d5fea003d367f4648f95b
Author: Kevin Barabash <kevinb7@gmail.com>
Date: Sat, 21 Jan 2017 17:49:15 -0500
Merge pull request #615 from gagern/release
Improve release script and bower support
Diffstat:
4 files changed, 161 insertions(+), 25 deletions(-)
diff --git a/bower.json b/bower.json
@@ -1,9 +1,8 @@
{
- "name": "KaTeX",
- "version": "0.8.0-pre",
+ "name": "katex",
"main": [
- "dist/katex.min.js",
- "dist/katex.min.css"
+ "dist/katex.js",
+ "dist/katex.css"
],
"homepage": "http://khan.github.io/KaTeX/",
"description": "Fast math typesetting for the web.",
diff --git a/package.json b/package.json
@@ -32,6 +32,7 @@
"nomnom": "^1.8.1",
"pako": "1.0.4",
"selenium-webdriver": "^2.48.2",
+ "sri-toolbox": "^0.2.0",
"uglify-js": "~2.7.5"
},
"bin": "cli.js",
diff --git a/release.sh b/release.sh
@@ -1,51 +1,125 @@
#!/usr/bin/env bash
set -e -o pipefail
+shopt -s extglob
-if [ $# -lt 1 ]; then
+VERSION=
+NEXT_VERSION=
+BRANCH=$(git rev-parse --abbrev-ref HEAD)
+NARGS=0
+DRY_RUN=
+INSANE=0
+
+# usage [ERROR-MESSAGES...] EXIT-STATUS
+usage() {
+ while [[ $# -gt 1 ]]; do
+ echo "$1" >&2
+ shift
+ done
echo "Usage:"
- echo "./release.sh <VERSION_TO_RELEASE> [NEXT_VERSION]"
+ echo "./release.sh [OPTIONS] <VERSION_TO_RELEASE> [NEXT_VERSION]"
+ echo ""
+ echo "Options:"
+ echo " --dry-run|-n: only print commands, do not execute them."
echo ""
echo "Examples:"
echo " When releasing a new point release:"
echo " ./release.sh 0.6.3"
echo " When releasing a new major version:"
echo " ./release.sh 0.7.0 0.8.0"
- exit
+ exit $1
+}
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --dry-run|-n|--just-print)
+ DRY_RUN=true
+ git() { echo "git $*"; }
+ npm() { echo "npm $*"; }
+ ;;
+ -h|-\?|--help)
+ usage 0
+ ;;
+ -*)
+ usage "Unknown option: $1" "" 1
+ ;;
+ *)
+ case "$NARGS" in
+ 0)
+ VERSION="$1"
+ NARGS=1
+ ;;
+ 1)
+ NEXT_VERSION="$1"
+ NARGS=2
+ ;;
+ *)
+ usage "Too many arguments: $1" "" 1
+ ;;
+ esac
+ ;;
+ esac
+ shift
+done
+
+if [[ $NARGS = 0 ]]; then
+ usage "Missing argument: version number" "" 1
fi
-VERSION=$1
-NEXT_VERSION=$2
+# Some sanity checks up front
+if ! command git diff --stat --exit-code HEAD; then
+ echo "Please make sure you have no uncommitted changes" >&2
+ : $((++INSANE))
+fi
+if ! command npm owner ls katex | grep -q "^$(command npm whoami) <"; then
+ echo "You don't seem do be logged into npm, use \`npm login\`" >&2
+ : $((++INSANE))
+fi
+if [[ $BRANCH != @(v*|master) ]]; then
+ echo "'$BRANCH' does not like a release branch to me" >&2
+ : $((++INSANE))
+fi
-if [ -z "$NEXT_VERSION" ]; then
- PROMPT="About to release $VERSION. Look good? [y/n] "
+if [[ -z "$NEXT_VERSION" ]]; then
+ echo "About to release $VERSION from $BRANCH. "
else
- PROMPT="About to release $VERSION and bump master to $NEXT_VERSION-pre. Look good? [y/n] "
+ echo "About to release $VERSION from $BRANCH and bump to $NEXT_VERSION-pre."
fi
-
-read -r -p "$PROMPT" CONFIRM
-if [ "$CONFIRM" != "y" ]; then
- exit
+if [[ $INSANE != 0 ]]; then
+ read -r -p "$INSANE sanity check(s) failed, really proceed? [y/n] " CONFIRM
+else
+ read -r -p "Look good? [y/n] " CONFIRM
+fi
+if [[ "$CONFIRM" != "y" ]]; then
+ exit 1
fi
# Make a new detached HEAD
-git checkout master
+git checkout "$BRANCH"
git pull
git checkout --detach
+
+# Build generated files and add them to the repository (for bower)
+git clean -fdx build dist
make setup dist
-git add dist/
+sed -i.bak -E '/^\/dist\/$/d' .gitignore
+rm -f .gitignore.bak
+git add .gitignore dist/
# Edit package.json and bower.json to the right version (see
# http://stackoverflow.com/a/22084103 for why we need the .bak file to make
# this mac & linux compatible)
sed -i.bak -E 's|"version": "[^"]+",|"version": "'$VERSION'",|' package.json
-sed -i.bak -E 's|"version": "[^"]+",|"version": "'$VERSION'",|' bower.json
-rm -f package.json.bak bower.json.bak
+rm -f package.json.bak
+
+# Update the version number in CDN URLs included in the README files,
+# and regenerate the Subresource Integrity hash for these files.
+node update-sri.js "${VERSION}" README.md contrib/*/README.md
# Make the commit and tag, and push them.
git add package.json bower.json
git commit -n -m "v$VERSION"
-git tag "v$VERSION"
+git tag -a "v$VERSION" -m "v$VERSION"
git push origin "v$VERSION"
# Update npm (bower and cdnjs update automatically)
@@ -53,22 +127,35 @@ npm publish
if [ ! -z "$NEXT_VERSION" ]; then
# Go back to master to bump
- git checkout master
+ git checkout "$BRANCH"
# Edit package.json and bower.json to the right version
sed -i.bak -E 's|"version": "[^"]+",|"version": "'$NEXT_VERSION'-pre",|' package.json
- sed -i.bak -E 's|"version": "[^"]+",|"version": "'$NEXT_VERSION'-pre",|' bower.json
- rm -f package.json.bak bower.json.bak
+ rm -f package.json.bak
+
+ # Refer to the just-released version in the documentation of the
+ # development branch, too. Most people will read docs on master.
+ node update-sri.js "${VERSION}" README.md contrib/*/README.md
git add package.json bower.json
git commit -n -m "Bump master to v$NEXT_VERSION-pre"
- git push origin master
+ git push origin "$BRANCH"
# Go back to the tag which has build/katex.tar.gz and build/katex.zip
git checkout "v$VERSION"
fi
+echo ""
echo "The automatic parts are done!"
echo "Now all that's left is to create the release on github."
echo "Visit https://github.com/Khan/KaTeX/releases/new?tag=v$VERSION to edit the release notes"
echo "Don't forget to upload build/katex.tar.gz and build/katex.zip to the release!"
+
+if [[ ${DRY_RUN} ]]; then
+ echo ""
+ echo "This was a dry run."
+ echo "Operations using git or npm were printed not executed."
+ echo "Some files got modified, though, so you might want to undo "
+ echo "these changes now, e.g. using \`git checkout -- .\` or similar."
+ echo ""
+fi
diff --git a/update-sri.js b/update-sri.js
@@ -0,0 +1,49 @@
+const fs = require("fs");
+const path = require("path");
+const sriToolbox = require("sri-toolbox");
+
+const version = process.argv[2];
+
+function read(file, encoding) {
+ return new Promise((resolve, reject) =>
+ fs.readFile(file, encoding, (err, body) =>
+ err ? reject(err) : resolve(body)));
+}
+
+function write(file, data) {
+ return new Promise((resolve, reject) =>
+ fs.writeFile(file, data, (err) =>
+ err ? reject(err) : resolve()));
+}
+
+Promise.all(process.argv.slice(3).map(file =>
+ read(file, "utf8")
+ .then(body => {
+ // 1 - url prefix: "http…/KaTeX/
+ // 2 - opening quote: "
+ // 3 - preserved suffix: /katex.min.js" integrity="…"
+ // 4 - file name: katex.min.js
+ // 5 - integrity opening quote: "
+ // 6 - old hash: sha384-…
+ // 7 - integrity hash algorithm: sha384
+ const re = /((["'])https?:\/\/cdnjs.cloudflare.com\/ajax\/libs\/KaTeX\/)[^\/"']+(\/([^"']+)\2(?:\s+integrity=(["'])(([^-]+)-[^"']+)\5)?)/g;
+ const hashes = {};
+ body = body.replace(re, (m, pre, oq1, post, file, oq2, old, algo) => {
+ if (old) {
+ hashes[old] = { file, algo };
+ }
+ return pre + version + post;
+ });
+ return Promise.all(Object.keys(hashes).map(hash =>
+ read(path.join("dist", hashes[hash].file), null)
+ .then(data => {
+ body = body.replace(hash, sriToolbox.generate({
+ algorithms: [hashes[hash].algo],
+ }, data));
+ })
+ )).then(() => write(file, body));
+ })
+)).then(() => process.exit(0), err => {
+ console.error(err.stack);
+ process.exit(1);
+});