/ maint / cargo-publish
cargo-publish
  1  #!/usr/bin/env bash
  2  #
  3  # usage:
  4  #   maint/cargo-publish [<OPTIONS>] VERSION
  5  #
  6  # options:
  7  #   --dry-run
  8  #   --force                go ahead even if problems detected
  9  #   --branch BRANCH        expect to be releasing origin/BRANCH, not HEAD
 10  #   --origin ORIGIN        replace repo URL to look for BRANCH on
 11  #
 12  # Preconditions:
 13  #   See doc/Release.md
 14  #
 15  # Running a different version to the one in the arti.git being published:
 16  # You can invoke this as ../PATH/TO/maint/cargo-publish.
 17  # That maint/ directory must contain compatible versions of the support
 18  # utilities, but it need not match the one in the CWD.
 19  # The version that is published is the one from the CWD.
 20  
 21  set -e
 22  
 23  origin='git@gitlab.torproject.org:tpo/core/arti'
 24  branch='main'
 25  maint="$(dirname "$0")"
 26  : "${CARGO:=cargo}"
 27  
 28  # Note for users of nailing-cargo: use this setting:
 29  #   CARGO='nailing-cargo --preclean=full --no-nail --git -o'
 30  
 31  # shellcheck source=maint/crates-io-utils.sh
 32  source "$maint/crates-io-utils.sh"
 33  
 34  #===== utilities =====
 35  
 36  all_ok=true
 37  
 38  problem () {
 39      echo >&2 "problem: $*"
 40      all_ok=false
 41  }
 42  
 43  check_equal () {
 44      local a="$1"
 45      local b="$2"
 46      local a_what="$3"
 47      local b_what="$4"
 48      if [ "x$a" != "x$b" ]; then
 49  	problem "mismatch: $a_what ($a) != $b_what ($b)"
 50      fi
 51  }
 52  
 53  #===== temporary files =====
 54  
 55  tmp_trap_exit_setup
 56  
 57  #===== argument parsing =====
 58  
 59  dry_run=false
 60  force=false
 61  
 62  while [ $# != 0 ]; do
 63      case "$1" in
 64  	--) break;;
 65  	-*) ;;
 66  	*) break;;
 67      esac
 68      arg="$1"; shift
 69      case "$arg" in
 70  	--dry-run) dry_run=true ;;
 71  	--force) force=true ;;
 72  	--branch|--origin)
 73  	    eval "${arg#--}=\$1"
 74  	    shift || fail "$arg takes an argument"
 75  	;;
 76  	*) fail "unknown option: $1";;
 77      esac
 78  done
 79  
 80  case $# in
 81      1) version=$1 ;;
 82      *) fail "bad usage, needs arti version"
 83  esac
 84  
 85  #===== checks and preparation =====
 86  
 87  jq </dev/null . || fail "jq is not installed, try   apt install jq"
 88  
 89  #----- check that we are identical to our main repo's `main`
 90  
 91  git fetch --quiet "$origin" "$branch"
 92  
 93  origin_head=$(git rev-parse FETCH_HEAD~0)
 94  our_head=$(git rev-parse HEAD~0)
 95  
 96  check_equal "$our_head" "$origin_head" \
 97  	    "our HEAD commit" "origin commit $origin"
 98  
 99  # TODO somehow check that CI failed there!
100  
101  #----- check that arti version matches
102  
103  arti=$("$maint"/list_crates -p arti --version)
104  arti=${arti##* }
105  
106  check_equal "$arti" "$version" \
107  	    "version of the arti crate, in-tree" \
108  	    "specified version to release"
109  
110  #----- compare already-published versions -----
111  
112  "$maint"/list_crates --version >"$tmp/all-crates"
113  
114  exec 3<"$tmp/all-crates"
115  
116  # shellcheck disable=SC2162 # we don't need -r, it has no backslashes
117  while <&3 read p v; do
118      printf "checking status of %-30s %10s ..." "$p" "$v"
119  
120      crates_io_api_call "v1/crates/$p/$v" .version.crate "$tmp/$p.json"
121  
122      case "$http_code" in
123  	200) echo ' already published.';;
124  	404)
125  	    echo ' needs publishing.'
126  	    to_publish+=" $p"
127  	    ;;
128      esac
129  done
130  
131  #===== commitment point =====
132  
133  prefix=xxxx
134  
135  running () {
136      echo "    $*"
137      "$@"
138  }
139  
140  if $dry_run; then
141      if $all_ok; then
142  	echo 'all seems OK, would run the following commands:'
143  	prefix='echo'
144      elif $force; then
145  	echo 'PROBLEMS, but --force passed, would run:'
146  	prefix='echo'
147      else
148  	echo 'PROBLEMS - would not run!'
149  	prefix='echo false'
150      fi
151  else
152      if $all_ok; then
153  	echo 'all OK, running publication!'
154  	prefix='running'
155      elif $force; then
156  	echo 'PROBLEMS, but --force passed, going ahead!'
157  	prefix='running'
158      else
159  	fail 'problems (see above), stopping'
160      fi
161  fi
162  
163  for p in $to_publish; do
164      # shellcheck disable=SC2086 # we want to split on spaces in $prefix and $CARGO
165      $prefix $CARGO publish -p "$p"
166  done
167  
168  echo 'all published.'
169  
170  tmp_trap_exit_finish_ok
171