release.sh (2246B)
1 #!/usr/bin/env bash 2 # Publish a release with goreleaser. 3 # 4 # release.sh [tag] releases a tag that already exists, by default the 5 # one at HEAD 6 # release.sh mint tag tags HEAD and releases that 7 # 8 # The tag reaches origin before goreleaser runs, because GitHub creates a 9 # missing tag at the default branch tip rather than at the commit released. 10 11 set -euo pipefail 12 13 usage="usage: release.sh [tag] | release.sh mint tag" 14 15 die() { 16 echo "$*" >&2 17 exit 1 18 } 19 20 mint=false 21 case ${1:-} in 22 mint) 23 mint=true 24 tag=${2:-} 25 [[ -n $tag && $# -eq 2 ]] || die "$usage" 26 ;; 27 *) 28 tag=${1:-} 29 [[ $# -le 1 ]] || die "$usage" 30 ;; 31 esac 32 33 mapfile -t at_head < <(git tag --points-at HEAD) 34 35 if $mint; then 36 [[ ${#at_head[@]} -eq 0 ]] || 37 die "HEAD already carries ${at_head[*]}; release it with: release.sh" 38 ! git rev-parse -q --verify "refs/tags/$tag" >/dev/null || 39 die "$tag already exists; release it with: release.sh $tag" 40 else 41 if [[ -z $tag ]]; then 42 case ${#at_head[@]} in 43 0) die "commit not tagged; mint one with: release.sh mint TAG" ;; 44 1) tag=${at_head[0]} ;; 45 *) die "HEAD carries ${at_head[*]}; name the one to release" ;; 46 esac 47 elif ! git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then 48 die "$tag is not a tag; mint it with: release.sh mint $tag" 49 fi 50 [[ $(git rev-parse "$tag^{}") == "$(git rev-parse HEAD)" ]] || 51 die "$tag is not at HEAD; check it out to release it" 52 fi 53 54 [[ -z $(git status --porcelain) ]] || die "working tree is not clean" 55 56 command -v goreleaser >/dev/null || die "goreleaser is not installed" 57 58 # Origin must already have the commit: tagging one it lacks would release 59 # something nobody can check out. 60 git fetch --quiet origin main 61 git merge-base --is-ancestor HEAD FETCH_HEAD || 62 die "HEAD is not on origin/main; push the branch first" 63 64 ! $mint || git tag -a "$tag" -m "$tag" 65 66 remote=$(git ls-remote --tags origin "refs/tags/$tag^{}" | cut -f1) 67 [[ -n $remote ]] || remote=$(git ls-remote --tags origin "refs/tags/$tag" | cut -f1) 68 here=$(git rev-parse "$tag^{}") 69 70 if [[ -z $remote ]]; then 71 git push origin "refs/tags/$tag" 72 elif [[ $remote != "$here" ]]; then 73 die "origin has $tag at $remote, not $here" 74 fi 75 76 GITHUB_TOKEN=$(pass goreleaser/github-token) goreleaser release --clean