• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env bash
2USAGE="Publish a new release of a tokio crate
3
4USAGE:
5    $(basename "$0") [OPTIONS] [CRATE] [VERSION]
6
7OPTIONS:
8    -v, --verbose   Use verbose Cargo output
9    -d, --dry-run   Perform a dry run (do not publish or tag the release)
10    -h, --help      Show this help text and exit"
11
12set -euo pipefail
13
14cd "$(dirname "$0")"/..
15
16DRY_RUN=""
17VERBOSE=""
18
19err() {
20    echo -e "\e[31m\e[1merror:\e[0m" "$@" 1>&2;
21}
22
23status() {
24    WIDTH=12
25    printf "\e[32m\e[1m%${WIDTH}s\e[0m %s\n" "$1" "$2"
26}
27
28verify() {
29    status "Verifying" "if $CRATE v$VERSION can be released"
30    ACTUAL=$(cargo pkgid | sed -n 's/.*#\(.*\)/\1/p')
31
32    if [ "$ACTUAL" != "$VERSION" ]; then
33        err "expected to release version $VERSION, but Cargo.toml contained $ACTUAL"
34        exit 1
35    fi
36
37    if ! cargo --list | grep -q "hack"; then
38        err "missing cargo-hack executable"
39        read -r -p "install it? [Y/n] " INPUT
40
41        case "$INPUT" in
42            [yY][eE][sS]|[yY])
43                status "Installing" "cargo-hack"
44                cargo install cargo-hack
45                ;;
46            [nN][oO]|[nN])
47                echo "okay, exiting"
48                exit 1
49                ;;
50            *)
51                err "invalid input $INPUT"
52                exit 1
53                ;;
54        esac
55    fi
56
57    status "Checking" "if $CRATE builds across feature combinations"
58
59    CARGO_HACK=(cargo hack check --feature-powerset  --no-dev-deps)
60
61    if [[ "$VERBOSE" ]]; then
62        CARGO_HACK+=("$VERBOSE")
63    fi
64
65    case "$CRATE" in
66        tracing-subscriber)
67            # for tracing-subscriber, don't test a complete powerset because
68            # there are lots of feature flags
69            INCLUDE_FEATURES=(fmt ansi json registry env-filter)
70            "${CARGO_HACK[@]}" --include-features "${INCLUDE_FEATURES[*]}"
71            CARGO_HACK_STATUS="$?"
72            ;;
73        tracing)
74            # checking the full feature powerset for `tracing` will take
75            # *forever* because of the `max_level_XXX` and
76            # `release_max_level_XXX` features
77            EXCLUDE_FEATURES=(
78                max_level_off max_level_error max_level_warn max_level_info
79                max_level_debug max_level_trace release_max_level_off
80                release_max_level_error release_max_level_warn
81                release_max_level_info release_max_level_debug
82                release_max_level_trace
83            )
84            "${CARGO_HACK[@]}" --exclude-features "${EXCLUDE_FEATURES[*]}"
85            CARGO_HACK_STATUS="$?"
86            ;;
87        *)
88            "${CARGO_HACK[@]}"
89            CARGO_HACK_STATUS="$?"
90            ;;
91    esac
92
93    if [[ "$CARGO_HACK_STATUS" != "0" ]] ; then
94        err "$CRATE did not build with all feature combinations (cargo hack exited with $CARGO_HACK_STATUS)!"
95        exit 1
96    fi
97
98
99    if git tag -l | grep -Fxq "$TAG" ; then
100        err "git tag \`$TAG\` already exists"
101        exit 1
102    fi
103}
104
105release() {
106    status "Releasing" "$CRATE v$VERSION"
107    local CARGO_PACKAGE=(cargo package)
108    local CARGO_PUBLISH=(cargo publish)
109
110    if [[ "$VERBOSE" ]]; then
111        CARGO_PACKAGE+=("$VERBOSE")
112        CARGO_PUBLISH+=("$VERBOSE")
113    fi
114
115    if [[ "$DRY_RUN" ]]; then
116        CARGO_PUBLISH+=("$DRY_RUN")
117    fi
118
119    "${CARGO_PACKAGE[@]}"
120    "${CARGO_PUBLISH[@]}"
121
122    status "Tagging" "$TAG"
123    if [[ "$DRY_RUN" ]]; then
124        echo "# git tag $TAG && git push --tags"
125    else
126        git tag "$TAG" && git push --tags
127    fi
128}
129
130while [[ $# -gt 0 ]]
131do
132
133case "$1" in
134    -v|--verbose)
135    VERBOSE="--verbose"
136    set -x
137    shift
138    ;;
139    -d|--dry-run)
140    DRY_RUN="--dry-run"
141    shift
142    ;;
143    -*)
144    err "unknown flag \"$1\""
145    echo "$USAGE"
146    exit 1
147    ;;
148    *) # crate or version
149    if [[ -z "${CRATE+crate}" ]]; then
150        CRATE="$1"
151    elif [[ -z "${VERSION+version}" ]]; then
152        VERSION="$1"
153    else
154        err "unknown positional argument \"$1\""
155        echo "$USAGE"
156        exit 1
157    fi
158    shift
159    ;;
160esac
161done
162# set -- "${POSITIONAL[@]}"
163
164if [[ -z "${VERSION+version}" ]]; then
165    err "no version specified!"
166    HELP=1
167fi
168
169if [[ "${CRATE+crate}" ]]; then
170    TAG="$CRATE-$VERSION"
171else
172    err "no crate specified!"
173    HELP=1
174fi
175
176if [[ "${HELP+help}" ]]; then
177    echo "$USAGE"
178    exit 1
179fi
180
181if [ -d "$CRATE" ]; then
182    (cd "$CRATE" && verify && release )
183else
184    err "no such crate \"$CRATE\""
185    exit 1
186fi
187