|
1 | | -#!/usr/bin/env bash |
| 1 | +#!/bin/sh |
2 | 2 |
|
3 | 3 | # To promote and sign a release that has been prepared by the build slaves, use: |
4 | 4 | # release.sh |
@@ -28,7 +28,7 @@ while getopts ":i:s:" option; do |
28 | 28 | echo "Invalid option -$OPTARG." |
29 | 29 | exit 1 |
30 | 30 | ;; |
31 | | - :) |
| 31 | + *) |
32 | 32 | echo "Option -$OPTARG takes a parameter." |
33 | 33 | exit 1 |
34 | 34 | ;; |
@@ -42,109 +42,107 @@ shift $((OPTIND-1)) |
42 | 42 | echo "# Selecting GPG key ..." |
43 | 43 |
|
44 | 44 | gpgkey=$(gpg --list-secret-keys --keyid-format SHORT | awk -F'( +|/)' '/^(sec|ssb)/{print $3}') |
45 | | -keycount=$(echo $gpgkey | wc -w) |
| 45 | +keycount=$(echo "$gpgkey" | wc -w) |
46 | 46 |
|
47 | | -if [ $keycount -eq 0 ]; then |
| 47 | +if [ "$keycount" -eq 0 ]; then |
| 48 | + # shellcheck disable=SC2016 |
48 | 49 | echo 'Need at least one GPG key, please make one with `gpg --gen-key`' |
49 | 50 | echo 'You will also need to submit your key to a public keyserver, e.g.' |
50 | 51 | echo ' https://sks-keyservers.net/i/#submit' |
51 | 52 | exit 1 |
52 | | -elif [ $keycount -ne 1 ]; then |
53 | | - echo -e 'You have multiple GPG keys:\n' |
| 53 | +elif [ "$keycount" -ne 1 ]; then |
| 54 | + printf "You have multiple GPG keys:\n\n" |
54 | 55 |
|
55 | 56 | gpg --list-secret-keys |
56 | 57 |
|
57 | | - while true; do |
58 | | - echo $gpgkey | awk '{ for(i = 1; i <= NF; i++) { print i ") " $i; } }' |
59 | | - echo -n 'Select a key: ' |
60 | | - read keynum |
61 | | - |
62 | | - if $(test "$keynum" -eq "$keynum" > /dev/null 2>&1); then |
63 | | - _gpgkey=$(echo $gpgkey | awk '{ print $'${keynum}'}') |
64 | | - keycount=$(echo $_gpgkey | wc -w) |
65 | | - if [ $keycount -eq 1 ]; then |
66 | | - echo "" |
67 | | - gpgkey=$_gpgkey |
68 | | - break |
69 | | - fi |
70 | | - fi |
| 58 | + keynum= |
| 59 | + while [ -z "${keynum##*[!0-9]*}" ] || [ "$keynum" -le 0 ] || [ "$keynum" -gt "$keycount" ]; do |
| 60 | + echo "$gpgkey" | awk '{ for(i = 1; i <= NF; i++) { print i ") " $i; } }' |
| 61 | + printf 'Select a key: ' |
| 62 | + read -r keynum |
71 | 63 | done |
| 64 | + echo "" |
| 65 | + gpgkey=$(echo "$gpgkey" | awk "{ print \$${keynum}}") |
72 | 66 | fi |
73 | 67 |
|
74 | | -gpgfing=$(gpg --keyid-format 0xLONG --fingerprint $gpgkey | grep 'Key fingerprint =' | awk -F' = ' '{print $2}' | tr -d ' ') |
| 68 | +gpgfing=$(gpg --keyid-format 0xLONG --fingerprint "$gpgkey" | grep 'Key fingerprint =' | awk -F' = ' '{print $2}' | tr -d ' ') |
| 69 | + |
| 70 | +grep "$gpgfing" README.md || (\ |
| 71 | + echo 'Error: this GPG key fingerprint is not listed in ./README.md' && \ |
| 72 | + exit 1 \ |
| 73 | +) |
75 | 74 |
|
76 | | -if ! test "$(grep $gpgfing README.md)"; then |
77 | | - echo 'Error: this GPG key fingerprint is not listed in ./README.md' |
78 | | - exit 1 |
79 | | -fi |
80 | 75 |
|
81 | 76 | echo "Using GPG key: $gpgkey" |
82 | 77 | echo " Fingerprint: $gpgfing" |
83 | 78 |
|
84 | | -function checktag { |
85 | | - local version=$1 |
| 79 | +checktag() { |
| 80 | + # local version=$1 |
86 | 81 |
|
87 | | - if ! git tag -v $version 2>&1 | grep "${gpgkey}" | grep key > /dev/null; then |
88 | | - echo "Could not find signed tag for \"${version}\" or GPG key is not yours" |
| 82 | + if ! git tag -v "$1" 2>&1 | grep "${gpgkey}" | grep key > /dev/null; then |
| 83 | + echo "Could not find signed tag for \"$1\" or GPG key is not yours" |
89 | 84 | exit 1 |
90 | 85 | fi |
91 | 86 | } |
92 | 87 |
|
93 | 88 | ################################################################################ |
94 | 89 | ## Create and sign checksums file for a given version |
95 | 90 |
|
96 | | -function sign { |
97 | | - echo -e "\n# Creating SHASUMS256.txt ..." |
| 91 | +sign() { |
| 92 | + printf "\n# Creating SHASUMS256.txt ...\n" |
98 | 93 |
|
99 | | - local version=$1 |
| 94 | + # local version=$1 |
100 | 95 |
|
101 | | - ghtaggedversion=$(curl -sL https://raw.githubusercontent.com/nodejs/node/${version}/src/node_version.h \ |
| 96 | + ghtaggedversion=$(curl -sL https://raw.githubusercontent.com/nodejs/node/"$1"/src/node_version.h \ |
102 | 97 | | awk '/define NODE_(MAJOR|MINOR|PATCH)_VERSION/{ v = v "." $3 } END{ v = "v" substr(v, 2); print v }') |
103 | | - if [ "${version}" != "${ghtaggedversion}" ]; then |
| 98 | + if [ "$1" != "${ghtaggedversion}" ]; then |
104 | 99 | echo "Could not find tagged version on github.com/nodejs/node, did you push your tag?" |
105 | 100 | exit 1 |
106 | 101 | fi |
107 | 102 |
|
108 | | - shapath=$(ssh ${customsshkey} ${webuser}@${webhost} $signcmd nodejs $version) |
| 103 | + # shellcheck disable=SC2029 |
| 104 | + shapath=$(ssh "${customsshkey}" "${webuser}@${webhost}" $signcmd nodejs "$1") |
109 | 105 |
|
110 | | - if ! [[ ${shapath} =~ ^/.+/SHASUMS256.txt$ ]]; then |
111 | | - echo 'Error: No SHASUMS file returned by sign!' |
| 106 | + echo "${shapath}" | grep -q '^/.*/SHASUMS256.txt$' || \ |
| 107 | + echo 'Error: No SHASUMS file returned by sign!' \ |
112 | 108 | exit 1 |
113 | | - fi |
114 | 109 |
|
115 | | - echo -e "\n# Signing SHASUMS for ${version}..." |
| 110 | + echo "" |
| 111 | + echo "# Signing SHASUMS for $1..." |
116 | 112 |
|
117 | | - shafile=$(basename $shapath) |
118 | | - shadir=$(dirname $shapath) |
| 113 | + shafile=$(basename "$shapath") |
| 114 | + shadir=$(dirname "$shapath") |
119 | 115 | tmpdir="/tmp/_node_release.$$" |
120 | 116 |
|
121 | 117 | mkdir -p $tmpdir |
122 | 118 |
|
123 | | - scp ${customsshkey} ${webuser}@${webhost}:${shapath} ${tmpdir}/${shafile} |
| 119 | + scp "${customsshkey}" "${webuser}@${webhost}:${shapath}" "${tmpdir}/${shafile}" |
124 | 120 |
|
125 | | - gpg --default-key $gpgkey --clearsign --digest-algo SHA256 ${tmpdir}/${shafile} |
126 | | - gpg --default-key $gpgkey --detach-sign --digest-algo SHA256 ${tmpdir}/${shafile} |
| 121 | + gpg --default-key "$gpgkey" --clearsign --digest-algo SHA256 ${tmpdir}/"${shafile}" |
| 122 | + gpg --default-key "$gpgkey" --detach-sign --digest-algo SHA256 ${tmpdir}/"${shafile}" |
127 | 123 |
|
128 | 124 | echo "Wrote to ${tmpdir}/" |
129 | 125 |
|
130 | | - echo -e "Your signed ${shafile}.asc:\n" |
| 126 | + echo "Your signed ${shafile}.asc:" |
| 127 | + echo "" |
131 | 128 |
|
132 | | - cat ${tmpdir}/${shafile}.asc |
| 129 | + cat "${tmpdir}/${shafile}.asc" |
133 | 130 |
|
134 | 131 | echo "" |
135 | 132 |
|
136 | 133 | while true; do |
137 | | - echo -n "Upload files? [y/n] " |
| 134 | + printf "Upload files? [y/n] " |
138 | 135 | yorn="" |
139 | | - read yorn |
| 136 | + read -r yorn |
140 | 137 |
|
141 | | - if [ "X${yorn}" == "Xn" ]; then |
| 138 | + if [ "X${yorn}" = "Xn" ]; then |
142 | 139 | break |
143 | 140 | fi |
144 | 141 |
|
145 | | - if [ "X${yorn}" == "Xy" ]; then |
146 | | - scp ${customsshkey} ${tmpdir}/${shafile} ${tmpdir}/${shafile}.asc ${tmpdir}/${shafile}.sig ${webuser}@${webhost}:${shadir}/ |
147 | | - ssh ${customsshkey} ${webuser}@${webhost} chmod 644 ${shadir}/${shafile}.asc ${shadir}/${shafile}.sig |
| 142 | + if [ "X${yorn}" = "Xy" ]; then |
| 143 | + scp "${customsshkey}" "${tmpdir}/${shafile}" "${tmpdir}/${shafile}.asc" "${tmpdir}/${shafile}.sig" "${webuser}@${webhost}:${shadir}/" |
| 144 | + #shellcheck disable=SC2029 |
| 145 | + ssh "${customsshkey}" "${webuser}@${webhost}" chmod 644 "${shadir}/${shafile}.asc" "${shadir}/${shafile}.sig" |
148 | 146 | break |
149 | 147 | fi |
150 | 148 | done |
@@ -154,8 +152,8 @@ function sign { |
154 | 152 |
|
155 | 153 |
|
156 | 154 | if [ -n "${signversion}" ]; then |
157 | | - checktag $signversion |
158 | | - sign $signversion |
| 155 | + checktag "$signversion" |
| 156 | + sign "$signversion" |
159 | 157 | exit 0 |
160 | 158 | fi |
161 | 159 |
|
|
164 | 162 | ################################################################################ |
165 | 163 | ## Look for releases to promote |
166 | 164 |
|
167 | | -echo -e "\n# Checking for releases ..." |
| 165 | +printf "\n# Checking for releases ...\n" |
168 | 166 |
|
169 | | -promotable=$(ssh ${customsshkey} ${webuser}@${webhost} $promotablecmd nodejs) |
| 167 | +promotable=$(ssh "${customsshkey}" "$webuser@$webhost" $promotablecmd nodejs) |
170 | 168 |
|
171 | | -if [ "X${promotable}" == "X" ]; then |
| 169 | +if [ "X${promotable}" = "X" ]; then |
172 | 170 | echo "No releases to promote!" |
173 | 171 | exit 0 |
174 | 172 | fi |
175 | 173 |
|
176 | | -echo -e "Found the following releases / builds ready to promote:\n" |
| 174 | +echo "Found the following releases / builds ready to promote:" |
| 175 | +echo "" |
177 | 176 | echo "$promotable" | sed 's/^/ * /' |
178 | 177 | echo "" |
179 | 178 |
|
@@ -184,28 +183,27 @@ versions=$(echo "$promotable" | cut -d: -f1) |
184 | 183 |
|
185 | 184 | for version in $versions; do |
186 | 185 | while true; do |
187 | | - files=$(echo "$promotable" | grep "^${version}" | sed 's/^'${version}': //') |
188 | | - echo -n "Promote ${version} files (${files})? [y/n] " |
| 186 | + files=$(echo "$promotable" | grep "^${version}" | sed 's/^'"${version}"': //') |
| 187 | + printf "Promote %s files (%s)? [y/n] " "${version}" "${files}" |
189 | 188 | yorn="" |
190 | | - read yorn |
| 189 | + read -r yorn |
191 | 190 |
|
192 | | - if [ "X${yorn}" == "Xn" ]; then |
| 191 | + if [ "X${yorn}" = "Xn" ]; then |
193 | 192 | break |
194 | 193 | fi |
195 | 194 |
|
196 | 195 | if [ "X${yorn}" != "Xy" ]; then |
197 | 196 | continue |
198 | 197 | fi |
199 | 198 |
|
200 | | - checktag $version |
201 | | - |
202 | | - echo -e "\n# Promoting ${version}..." |
| 199 | + checktag "$version" |
203 | 200 |
|
204 | | - ssh ${customsshkey} ${webuser}@${webhost} $promotecmd nodejs $version |
| 201 | + echo "" |
| 202 | + echo "# Promoting ${version}..." |
205 | 203 |
|
206 | | - if [ $? -eq 0 ];then |
207 | | - sign $version |
208 | | - fi |
| 204 | + # shellcheck disable=SC2029 |
| 205 | + ssh "${customsshkey}" "$webuser@$webhost" $promotecmd nodejs "$version" && \ |
| 206 | + sign "$version" |
209 | 207 |
|
210 | 208 | break |
211 | 209 | done |
|