UNPKG

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