chiark / gitweb /
make-release: Add a checklist entry to run with --dry-run
[otter.git] / make-release
1 #!/bin/bash
2 #
3 # usage:
4 #    ./make-release --dry-run|--real <branch>
5 # eg
6 #    ./make-release --dry-run main
7
8
9 # Overall release steps:
10 #
11 #  - update dependencies (cargo update, cargo upgrades)
12 #  - edit CHANGELOG.md
13 #  - update versions
14 #  - ensure pretest == tested == main
15 #  - make deploy and test that chiark still works
16 #  - make-release --dry-run
17 #  - make-release
18 #  - release announcement to mailing list
19 #  - blog post
20
21 #---------- argument parsing and options ----------
22
23 set -e
24 set -o pipefail
25
26 fail () { echo >&2 "${0##*/}: error: $*"; exit 12; }
27
28 dryrun=x-dry-run-unset
29 cargo_dryrun=--not-a-cargo-option-please-crash
30
31 case "$#.$1" in
32 2.--real)    dryrun=x     ; cargo_dryrun=''         ; ;;
33 2.--dry-run) dryrun=dryrun; cargo_dryrun='--dry-run'; ;;
34 *)           fail "bad usage" ;;
35 esac
36
37 keyid=0x559AE46C2D6B6D3265E7CBA1E3E3392348B50D39
38
39 cratesio_raw_url=\
40 https://raw.githubusercontent.com/rust-lang/crates.io-index/master
41
42 branch="$2"
43
44 dryrun () { echo "WOULD  $*"; }
45 x () { echo >&2 "+ $*"; "$@"; }
46
47 trouble=false
48 trouble () { echo >&2 "***TROUBLE***: $*"; trouble=true; }
49
50 #---------- checks ----------
51
52 version=$(perl <Cargo.toml -ne '
53     next unless m{^version\s*=\s*\"([0-9.]+)\"\s*$};
54     print "$1\n" or die $!;
55     exit 0;
56 ')
57
58 case "$version" in
59 '') fail "no version?" ;;
60 esac
61
62 echo "version $version"
63
64 equals () {
65     diff <(git rev-parse refs/heads/$1) <(git rev-parse HEAD) \
66         || trouble "HEAD not equal to $1"
67 }
68
69 equals $branch
70 equals tested
71
72 bad=$(git status --porcelain)
73 if [ "x$bad" != x ]; then
74     printf >&2 '%s\n' "$bad"
75     trouble 'tree is dirty'
76 fi
77
78 tag="otter-$version"
79 tag_exists=$(git for-each-ref "[r]efs/tags/$tag")
80 if [ "x$tag_exists" != x ]; then trouble "tag $tag already exists"; fi
81
82 head -1 CHANGELOG.md | grep "^Version $version" \
83 || trouble "CHANGELOG.md not updated"
84
85 cargo_order='base support . cli daemon wasm apitest wdriver jstest'
86 missing=(git ls-files :\*/Cargo.toml :Cargo.toml)
87 for x in $cargo_order; do missing+=(:!$x/Cargo.toml); done
88 missing=$( "${missing[@]}" )
89 if [ "x$missing" != x ]; then trouble "missing cargo package(s) $missing"; fi
90
91 #---------- end of checks ----------
92
93 if $trouble; then
94     $dryrun fail "trouble! checks failed!"
95 else
96     echo 'checks passed'
97 fi
98
99 #---------- actually do the work ----------
100
101 $dryrun git push chiark $branch
102 $dryrun git push origin $branch
103
104 #---------- non-idempotent things ----------
105
106 $dryrun make -j12 PUBLISH_VERSION=$version publish
107 $dryrun make -j12 PUBLISH_VERSION=$version publish-make-current
108
109 $dryrun git tag -s -u "$keyid" -m "Otter v$version" $tag
110 $dryrun git push chiark $tag
111 $dryrun git push origin $tag
112
113 #---------- oh woe cargo ----------
114
115 # https://github.com/rust-lang/cargo/issues/9507
116 wait_for_crates_io () {
117     local p=$1
118     local delay=1
119     local url="$cratesio_raw_url/${p:0:2}/${p:2:2}/$p"
120     printf >&2 "waiting for upload of %s to take effect" "$p"
121     while sleep $delay; do
122         printf >&2 .
123         local got=$(
124             curl -sS "$url" | jq '.vers | select(. == "'"$version"'")'
125         )
126         if [ "x$got" != x ]; then break; fi
127         delay=$(( $delay * 11 / 10 + 1 ))
128     done
129     echo >&2 'done'
130 }
131
132 for cargo_dir in $cargo_order; do
133     $dryrun_no_more_cargo \
134     nailing-cargo --no-nail --preclean-build=src --git --- \
135         sh -xec "
136           cd $cargo_dir; cargo publish $cargo_dryrun
137         "
138
139     cargo_package=$(
140         sed -n '/^name *=/ { s/^name *= *"\(.*\)" *$/\1/; p; q }' \
141             <$cargo_dir/Cargo.toml
142     )
143
144     wait_for_crates_io "$cargo_package"
145
146     dryrun_no_more_cargo=$dryrun
147
148 done
149
150 #---------- finish ----------
151
152 $dryrun cat <<END
153
154
155 Successfully released to
156   - git tags
157   - all git branches
158   - cargo publish
159
160 Consider
161   - make deploy
162
163 You need to write release announcements
164   - sgo-software-announce
165   - blog
166
167 END