UNPKG

9.85 kBapplication/x-shView Raw
1#!/bin/bash
2#
3# Script to perform a release of matrix-js-sdk.
4#
5# Requires:
6# github-changelog-generator; install via:
7# pip install git+https://github.com/matrix-org/github-changelog-generator.git
8# jq; install from your distribution's package manager (https://stedolan.github.io/jq/)
9# hub; install via brew (OSX) or source/pre-compiled binaries (debian) (https://github.com/github/hub) - Tested on v2.2.9
10
11set -e
12
13jq --version > /dev/null || (echo "jq is required: please install it"; kill $$)
14if [[ `command -v hub` ]] && [[ `hub --version` =~ hub[[:space:]]version[[:space:]]([0-9]*).([0-9]*) ]]; then
15 HUB_VERSION_MAJOR=${BASH_REMATCH[1]}
16 HUB_VERSION_MINOR=${BASH_REMATCH[2]}
17 if [[ $HUB_VERSION_MAJOR -lt 2 ]] || [[ $HUB_VERSION_MAJOR -eq 2 && $HUB_VERSION_MINOR -lt 5 ]]; then
18 echo "hub version 2.5 is required, you have $HUB_VERSION_MAJOR.$HUB_VERSION_MINOR installed"
19 exit
20 fi
21else
22 echo "hub is required: please install it"
23 exit
24fi
25
26USAGE="$0 [-xz] [-c changelog_file] vX.Y.Z"
27
28help() {
29 cat <<EOF
30$USAGE
31
32 -c changelog_file: specify name of file containing changelog
33 -x: skip updating the changelog
34 -z: skip generating the jsdoc
35EOF
36}
37
38ret=0
39cat package.json | jq '.dependencies[]' | grep -q '#develop' || ret=$?
40if [ "$ret" -eq 0 ]; then
41 echo "package.json contains develop dependencies. Refusing to release."
42 exit
43fi
44
45if ! git diff-index --quiet --cached HEAD; then
46 echo "this git checkout has staged (uncommitted) changes. Refusing to release."
47 exit
48fi
49
50if ! git diff-files --quiet; then
51 echo "this git checkout has uncommitted changes. Refusing to release."
52 exit
53fi
54
55skip_changelog=
56skip_jsdoc=
57changelog_file="CHANGELOG.md"
58expected_npm_user="matrixdotorg"
59while getopts hc:u:xz f; do
60 case $f in
61 h)
62 help
63 exit 0
64 ;;
65 c)
66 changelog_file="$OPTARG"
67 ;;
68 x)
69 skip_changelog=1
70 ;;
71 z)
72 skip_jsdoc=1
73 ;;
74 u)
75 expected_npm_user="$OPTARG"
76 ;;
77 esac
78done
79shift `expr $OPTIND - 1`
80
81if [ $# -ne 1 ]; then
82 echo "Usage: $USAGE" >&2
83 exit 1
84fi
85
86if [ -z "$skip_changelog" ]; then
87 # update_changelog doesn't have a --version flag
88 update_changelog -h > /dev/null || (echo "github-changelog-generator is required: please install it"; exit)
89fi
90
91actual_npm_user=`npm whoami`;
92if [ $expected_npm_user != $actual_npm_user ]; then
93 echo "you need to be logged into npm as $expected_npm_user, but you are logged in as $actual_npm_user" >&2
94 exit 1
95fi
96
97# ignore leading v on release
98release="${1#v}"
99tag="v${release}"
100rel_branch="release-$tag"
101
102prerelease=0
103# We check if this build is a prerelease by looking to
104# see if the version has a hyphen in it. Crude,
105# but semver doesn't support postreleases so anything
106# with a hyphen is a prerelease.
107echo $release | grep -q '-' && prerelease=1
108
109if [ $prerelease -eq 1 ]; then
110 echo Making a PRE-RELEASE
111fi
112
113if [ -z "$skip_changelog" ]; then
114 if ! command -v update_changelog >/dev/null 2>&1; then
115 echo "release.sh requires github-changelog-generator. Try:" >&2
116 echo " pip install git+https://github.com/matrix-org/github-changelog-generator.git" >&2
117 exit 1
118 fi
119fi
120
121# we might already be on the release branch, in which case, yay
122# If we're on any branch starting with 'release', we don't create
123# a separate release branch (this allows us to use the same
124# release branch for releases and release candidates).
125curbranch=$(git symbolic-ref --short HEAD)
126if [[ "$curbranch" != release* ]]; then
127 echo "Creating release branch"
128 git checkout -b "$rel_branch"
129else
130 echo "Using current branch ($curbranch) for release"
131 rel_branch=$curbranch
132fi
133
134if [ -z "$skip_changelog" ]; then
135 echo "Generating changelog"
136 update_changelog -f "$changelog_file" "$release"
137 read -p "Edit $changelog_file manually, or press enter to continue " REPLY
138
139 if [ -n "$(git ls-files --modified $changelog_file)" ]; then
140 echo "Committing updated changelog"
141 git commit "$changelog_file" -m "Prepare changelog for $tag"
142 fi
143fi
144latest_changes=`mktemp`
145cat "${changelog_file}" | `dirname $0`/scripts/changelog_head.py > "${latest_changes}"
146
147set -x
148
149# Bump package.json and build the dist
150echo "npm version"
151# npm version will automatically commit its modification
152# and make a release tag. We don't want it to create the tag
153# because it can only sign with the default key, but we can
154# only turn off both of these behaviours, so we have to
155# manually commit the result.
156npm version --no-git-tag-version "$release"
157
158# commit package-lock.json if it exists, is versioned, and is modified
159if [[ -f package-lock.json && `git status --porcelain package-lock.json | grep '^ M'` ]];
160then
161 pkglock='package-lock.json'
162else
163 pkglock=''
164fi
165git commit package.json $pkglock -m "$tag"
166
167
168# figure out if we should be signing this release
169signing_id=
170if [ -f release_config.yaml ]; then
171 signing_id=`cat release_config.yaml | python -c "import yaml; import sys; print yaml.load(sys.stdin)['signing_id']"`
172fi
173
174
175# If there is a 'dist' script in the package.json,
176# run it in a separate checkout of the project, then
177# upload any files in the 'dist' directory as release
178# assets.
179# We make a completely separate checkout to be sure
180# we're using released versions of the dependencies
181# (rather than whatever we're pulling in from npm link)
182assets=''
183dodist=0
184jq -e .scripts.dist package.json 2> /dev/null || dodist=$?
185if [ $dodist -eq 0 ]; then
186 projdir=`pwd`
187 builddir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`
188 echo "Building distribution copy in $builddir"
189 pushd "$builddir"
190 git clone "$projdir" .
191 git checkout "$rel_branch"
192 npm install
193 # We haven't tagged yet, so tell the dist script what version
194 # it's building
195 DIST_VERSION="$tag" npm run dist
196
197 popd
198
199 for i in "$builddir"/dist/*; do
200 assets="$assets -a $i"
201 if [ -n "$signing_id" ]
202 then
203 gpg -u "$signing_id" --armor --output "$i".asc --detach-sig "$i"
204 assets="$assets -a $i.asc"
205 fi
206 done
207fi
208
209if [ -n "$signing_id" ]; then
210 # make a signed tag
211 # gnupg seems to fail to get the right tty device unless we set it here
212 GIT_COMMITTER_EMAIL="$signing_id" GPG_TTY=`tty` git tag -u "$signing_id" -F "${latest_changes}" "$tag"
213else
214 git tag -a -F "${latest_changes}" "$tag"
215fi
216
217# push the tag and the release branch
218git push origin "$rel_branch" "$tag"
219
220if [ -n "$signing_id" ]; then
221 # make a signature for the source tarball.
222 #
223 # github will make us a tarball from the tag - we want to create a
224 # signature for it, which means that first of all we need to check that
225 # it's correct.
226 #
227 # we can't deterministically build exactly the same tarball, due to
228 # differences in gzip implementation - but we *can* build the same tar - so
229 # the easiest way to check the validity of the tarball from git is to unzip
230 # it and compare it with our own idea of what the tar should look like.
231
232 # the name of the sig file we want to create
233 source_sigfile="${tag}-src.tar.gz.asc"
234
235 tarfile="$tag.tar.gz"
236 gh_project_url=$(git remote get-url origin |
237 sed -e 's#^git@github\.com:#https://github.com/#' \
238 -e 's#^git\+ssh://git@github\.com/#https://github.com/#' \
239 -e 's/\.git$//')
240 project_name="${gh_project_url##*/}"
241 curl -L "${gh_project_url}/archive/${tarfile}" -o "${tarfile}"
242
243 # unzip it and compare it with the tar we would generate
244 if ! cmp --silent <(gunzip -c $tarfile) \
245 <(git archive --format tar --prefix="${project_name}-${release}/" "$tag"); then
246
247 # we don't bail out here, because really it's more likely that our comparison
248 # screwed up and it's super annoying to abort the script at this point.
249 cat >&2 <<EOF
250!!!!!!!!!!!!!!!!!
251!!!! WARNING !!!!
252
253Mismatch between our own tarfile and that generated by github: not signing
254source tarball.
255
256To resolve, determine if $tarfile is correct, and if so sign it with gpg and
257attach it to the release as $source_sigfile.
258
259!!!!!!!!!!!!!!!!!
260EOF
261 else
262 gpg -u "$signing_id" --armor --output "$source_sigfile" --detach-sig "$tarfile"
263 assets="$assets -a $source_sigfile"
264 fi
265fi
266
267hubflags=''
268if [ $prerelease -eq 1 ]; then
269 hubflags='-p'
270fi
271
272release_text=`mktemp`
273echo "$tag" > "${release_text}"
274echo >> "${release_text}"
275cat "${latest_changes}" >> "${release_text}"
276hub release create $hubflags $assets -F "${release_text}" "$tag"
277
278if [ $dodist -eq 0 ]; then
279 rm -rf "$builddir"
280fi
281rm "${release_text}"
282rm "${latest_changes}"
283
284# publish to npmjs
285npm publish
286
287if [ -z "$skip_jsdoc" ]; then
288 echo "generating jsdocs"
289 npm run gendoc
290
291 echo "copying jsdocs to gh-pages branch"
292 git checkout gh-pages
293 git pull
294 cp -a ".jsdoc/matrix-js-sdk/$release" .
295 perl -i -pe 'BEGIN {$rel=shift} $_ =~ /^<\/ul>/ && print
296 "<li><a href=\"${rel}/index.html\">Version ${rel}</a></li>\n"' \
297 $release index.html
298 git add "$release"
299 git commit --no-verify -m "Add jsdoc for $release" index.html "$release"
300fi
301
302# if it is a pre-release, leave it on the release branch for now.
303if [ $prerelease -eq 1 ]; then
304 git checkout "$rel_branch"
305 exit 0
306fi
307
308# merge release branch to master
309echo "updating master branch"
310git checkout master
311git pull
312git merge "$rel_branch"
313
314# push master and docs (if generated) to github
315git push origin master
316if [ -z "$skip_jsdoc" ]; then
317 git push origin gh-pages
318fi
319
320# finally, merge master back onto develop
321git checkout develop
322git pull
323git merge master
324git push origin develop