set -e
set -o pipefail
fail () { echo >&2 "${0##*/}: error: $*"; exit 12; }
dryrun=x-dry-run-unset
cargo_dryrun=--not-a-cargo-option-please-crash
case "$#.$1" in
2.--real) dryrun=x ; cargo_dryrun='' ; ;;
2.--dry-run) dryrun=dryrun; cargo_dryrun='--dry-run'; ;;
*) fail "bad usage" ;;
esac
keyid=0x559AE46C2D6B6D3265E7CBA1E3E3392348B50D39
cratesio_raw_url=\
https://raw.githubusercontent.com/rust-lang/crates.io-index/master
branch="$2"
dryrun () { echo "WOULD $*"; }
x () { echo >&2 "+ $*"; "$@"; }
trouble=false
trouble () { echo >&2 "***TROUBLE***: $*"; trouble=true; }
version=$(perl <Cargo.toml -ne '
next unless m{^version\s*=\s*\"([0-9.]+)\"\s*$};
print "$1\n" or die $!;
exit 0;
')
case "$version" in
'') fail "no version?" ;;
esac
echo "version $version"
equals () {
diff <(git rev-parse refs/heads/$1) <(git rev-parse HEAD) \
|| trouble "HEAD not equal to $1"
}
equals $branch
equals tested
bad=$(git status --porcelain)
if [ "x$bad" != x ]; then
printf >&2 '%s\n' "$bad"
trouble 'tree is dirty'
fi
tag="otter-$version"
tag_exists=$(git for-each-ref "[r]efs/tags/$tag")
if [ "x$tag_exists" != x ]; then trouble "tag $tag already exists"; fi
head -1 CHANGELOG.md | grep "^Version $version" \
|| trouble "CHANGELOG.md not updated"
cargo_order='base . cli daemon wasm apitest wdriver'
missing=(git ls-files :\*/Cargo.toml :Cargo.toml)
for x in $cargo_order; do missing+=(:!$x/Cargo.toml); done
missing=$( "${missing[@]}" )
if [ "x$missing" != x ]; then trouble "missing cargo package(s) $missing"; fi
if $trouble; then
$dryrun fail "trouble! checks failed!"
else
echo 'checks passed'
fi
$dryrun git push chiark $branch
$dryrun git push origin $branch
$dryrun make -j12 publish
$dryrun git tag -s -u "$keyid" -m "Otter v$version" $tag
$dryrun git push chiark $tag
$dryrun git push origin $tag
wait_for_crates_io () {
local p=$1
local delay=1
local url="$cratesio_raw_url/${p:0:2}/${p:2:2}/$p"
printf >&2 "waiting for upload of %s to take effect" "$p"
while sleep $delay; do
printf >&2 .
local got=$(
curl -sS "$url" | jq '.vers | select(. == "'"$version"'")'
)
if [ "x$got" != x ]; then break; fi
delay=$(( $delay * 11 / 10 + 1 ))
done
echo >&2 'done'
}
for cargo_dir in $cargo_order; do
$dryrun_no_more_cargo \
nailing-cargo --no-nail --linkfarm=git --- \
sh -xec "
find . ! -type l ! -type d ! -path './target/*' -print0 \
| xargs -0r rm --
cd $cargo_dir; cargo publish $cargo_dryrun
"
cargo_package=$(
sed -n '/^name *=/ { s/^name *= *"\(.*\)" *$/\1/; p; q }' \
<$cargo_dir/Cargo.toml
)
wait_for_crates_io "$cargo_package"
dryrun_no_more_cargo=$dryrun
done
$dryrun cat <<END
Successfully released to
- git tags
- all git branches
- cargo publish
Consider
- make deploy
You need to write release announcements
- sgo-software-announce
- blog
END