github.com/raychaser/docker@v1.5.0/project/release.sh (about) 1 #!/usr/bin/env bash 2 set -e 3 4 # This script looks for bundles built by make.sh, and releases them on a 5 # public S3 bucket. 6 # 7 # Bundles should be available for the VERSION string passed as argument. 8 # 9 # The correct way to call this script is inside a container built by the 10 # official Dockerfile at the root of the Docker source code. The Dockerfile, 11 # make.sh and release.sh should all be from the same source code revision. 12 13 set -o pipefail 14 15 # Print a usage message and exit. 16 usage() { 17 cat >&2 <<'EOF' 18 To run, I need: 19 - to be in a container generated by the Dockerfile at the top of the Docker 20 repository; 21 - to be provided with the name of an S3 bucket, in environment variable 22 AWS_S3_BUCKET; 23 - to be provided with AWS credentials for this S3 bucket, in environment 24 variables AWS_ACCESS_KEY and AWS_SECRET_KEY; 25 - the passphrase to unlock the GPG key which will sign the deb packages 26 (passed as environment variable GPG_PASSPHRASE); 27 - a generous amount of good will and nice manners. 28 The canonical way to run me is to run the image produced by the Dockerfile: e.g.:" 29 30 docker run -e AWS_S3_BUCKET=test.docker.com \ 31 -e AWS_ACCESS_KEY=... \ 32 -e AWS_SECRET_KEY=... \ 33 -e GPG_PASSPHRASE=... \ 34 -i -t --privileged \ 35 docker ./hack/release.sh 36 EOF 37 exit 1 38 } 39 40 [ "$AWS_S3_BUCKET" ] || usage 41 [ "$AWS_ACCESS_KEY" ] || usage 42 [ "$AWS_SECRET_KEY" ] || usage 43 [ "$GPG_PASSPHRASE" ] || usage 44 [ -d /go/src/github.com/docker/docker ] || usage 45 cd /go/src/github.com/docker/docker 46 [ -x hack/make.sh ] || usage 47 48 RELEASE_BUNDLES=( 49 binary 50 cross 51 tgz 52 ubuntu 53 ) 54 55 if [ "$1" != '--release-regardless-of-test-failure' ]; then 56 RELEASE_BUNDLES=( 57 test-unit test-integration 58 "${RELEASE_BUNDLES[@]}" 59 test-integration-cli 60 ) 61 fi 62 63 VERSION=$(cat VERSION) 64 BUCKET=$AWS_S3_BUCKET 65 66 # These are the 2 keys we've used to sign the deb's 67 # release (get.docker.com) 68 # GPG_KEY="36A1D7869245C8950F966E92D8576A8BA88D21E9" 69 # test (test.docker.com) 70 # GPG_KEY="740B314AE3941731B942C66ADF4FD13717AAD7D6" 71 72 setup_s3() { 73 # Try creating the bucket. Ignore errors (it might already exist). 74 s3cmd mb s3://$BUCKET 2>/dev/null || true 75 # Check access to the bucket. 76 # s3cmd has no useful exit status, so we cannot check that. 77 # Instead, we check if it outputs anything on standard output. 78 # (When there are problems, it uses standard error instead.) 79 s3cmd info s3://$BUCKET | grep -q . 80 # Make the bucket accessible through website endpoints. 81 s3cmd ws-create --ws-index index --ws-error error s3://$BUCKET 82 } 83 84 # write_to_s3 uploads the contents of standard input to the specified S3 url. 85 write_to_s3() { 86 DEST=$1 87 F=`mktemp` 88 cat > $F 89 s3cmd --acl-public --mime-type='text/plain' put $F $DEST 90 rm -f $F 91 } 92 93 s3_url() { 94 case "$BUCKET" in 95 get.docker.com|test.docker.com) 96 echo "https://$BUCKET" 97 ;; 98 *) 99 s3cmd ws-info s3://$BUCKET | awk -v 'FS=: +' '/http:\/\/'$BUCKET'/ { gsub(/\/+$/, "", $2); print $2 }' 100 ;; 101 esac 102 } 103 104 build_all() { 105 if ! ./hack/make.sh "${RELEASE_BUNDLES[@]}"; then 106 echo >&2 107 echo >&2 'The build or tests appear to have failed.' 108 echo >&2 109 echo >&2 'You, as the release maintainer, now have a couple options:' 110 echo >&2 '- delay release and fix issues' 111 echo >&2 '- delay release and fix issues' 112 echo >&2 '- did we mention how important this is? issues need fixing :)' 113 echo >&2 114 echo >&2 'As a final LAST RESORT, you (because only you, the release maintainer,' 115 echo >&2 ' really knows all the hairy problems at hand with the current release' 116 echo >&2 ' issues) may bypass this checking by running this script again with the' 117 echo >&2 ' single argument of "--release-regardless-of-test-failure", which will skip' 118 echo >&2 ' running the test suite, and will only build the binaries and packages. Please' 119 echo >&2 ' avoid using this if at all possible.' 120 echo >&2 121 echo >&2 'Regardless, we cannot stress enough the scarcity with which this bypass' 122 echo >&2 ' should be used. If there are release issues, we should always err on the' 123 echo >&2 ' side of caution.' 124 echo >&2 125 exit 1 126 fi 127 } 128 129 upload_release_build() { 130 src="$1" 131 dst="$2" 132 latest="$3" 133 134 echo 135 echo "Uploading $src" 136 echo " to $dst" 137 echo 138 s3cmd --follow-symlinks --preserve --acl-public put "$src" "$dst" 139 if [ "$latest" ]; then 140 echo 141 echo "Copying to $latest" 142 echo 143 s3cmd --acl-public cp "$dst" "$latest" 144 fi 145 146 # get hash files too (see hash_files() in hack/make.sh) 147 for hashAlgo in md5 sha256; do 148 if [ -e "$src.$hashAlgo" ]; then 149 echo 150 echo "Uploading $src.$hashAlgo" 151 echo " to $dst.$hashAlgo" 152 echo 153 s3cmd --follow-symlinks --preserve --acl-public --mime-type='text/plain' put "$src.$hashAlgo" "$dst.$hashAlgo" 154 if [ "$latest" ]; then 155 echo 156 echo "Copying to $latest.$hashAlgo" 157 echo 158 s3cmd --acl-public cp "$dst.$hashAlgo" "$latest.$hashAlgo" 159 fi 160 fi 161 done 162 } 163 164 release_build() { 165 GOOS=$1 166 GOARCH=$2 167 168 binDir=bundles/$VERSION/cross/$GOOS/$GOARCH 169 tgzDir=bundles/$VERSION/tgz/$GOOS/$GOARCH 170 binary=docker-$VERSION 171 tgz=docker-$VERSION.tgz 172 173 latestBase= 174 if [ -z "$NOLATEST" ]; then 175 latestBase=docker-latest 176 fi 177 178 # we need to map our GOOS and GOARCH to uname values 179 # see https://en.wikipedia.org/wiki/Uname 180 # ie, GOOS=linux -> "uname -s"=Linux 181 182 s3Os=$GOOS 183 case "$s3Os" in 184 darwin) 185 s3Os=Darwin 186 ;; 187 freebsd) 188 s3Os=FreeBSD 189 ;; 190 linux) 191 s3Os=Linux 192 ;; 193 *) 194 echo >&2 "error: can't convert $s3Os to an appropriate value for 'uname -s'" 195 exit 1 196 ;; 197 esac 198 199 s3Arch=$GOARCH 200 case "$s3Arch" in 201 amd64) 202 s3Arch=x86_64 203 ;; 204 386) 205 s3Arch=i386 206 ;; 207 arm) 208 s3Arch=armel 209 # someday, we might potentially support mutliple GOARM values, in which case we might get armhf here too 210 ;; 211 *) 212 echo >&2 "error: can't convert $s3Arch to an appropriate value for 'uname -m'" 213 exit 1 214 ;; 215 esac 216 217 s3Dir=s3://$BUCKET/builds/$s3Os/$s3Arch 218 latest= 219 latestTgz= 220 if [ "$latestBase" ]; then 221 latest="$s3Dir/$latestBase" 222 latestTgz="$s3Dir/$latestBase.tgz" 223 fi 224 225 if [ ! -x "$binDir/$binary" ]; then 226 echo >&2 "error: can't find $binDir/$binary - was it compiled properly?" 227 exit 1 228 fi 229 if [ ! -f "$tgzDir/$tgz" ]; then 230 echo >&2 "error: can't find $tgzDir/$tgz - was it packaged properly?" 231 exit 1 232 fi 233 234 upload_release_build "$binDir/$binary" "$s3Dir/$binary" "$latest" 235 upload_release_build "$tgzDir/$tgz" "$s3Dir/$tgz" "$latestTgz" 236 } 237 238 # Upload the 'ubuntu' bundle to S3: 239 # 1. A full APT repository is published at $BUCKET/ubuntu/ 240 # 2. Instructions for using the APT repository are uploaded at $BUCKET/ubuntu/index 241 release_ubuntu() { 242 [ -e bundles/$VERSION/ubuntu ] || { 243 echo >&2 './hack/make.sh must be run before release_ubuntu' 244 exit 1 245 } 246 247 # Sign our packages 248 dpkg-sig -g "--passphrase $GPG_PASSPHRASE" -k releasedocker \ 249 --sign builder bundles/$VERSION/ubuntu/*.deb 250 251 # Setup the APT repo 252 APTDIR=bundles/$VERSION/ubuntu/apt 253 mkdir -p $APTDIR/conf $APTDIR/db 254 s3cmd sync s3://$BUCKET/ubuntu/db/ $APTDIR/db/ || true 255 cat > $APTDIR/conf/distributions <<EOF 256 Codename: docker 257 Components: main 258 Architectures: amd64 i386 259 EOF 260 261 # Add the DEB package to the APT repo 262 DEBFILE=bundles/$VERSION/ubuntu/lxc-docker*.deb 263 reprepro -b $APTDIR includedeb docker $DEBFILE 264 265 # Sign 266 for F in $(find $APTDIR -name Release); do 267 gpg -u releasedocker --passphrase $GPG_PASSPHRASE \ 268 --armor --sign --detach-sign \ 269 --output $F.gpg $F 270 done 271 272 # Upload keys 273 s3cmd sync $HOME/.gnupg/ s3://$BUCKET/ubuntu/.gnupg/ 274 gpg --armor --export releasedocker > bundles/$VERSION/ubuntu/gpg 275 s3cmd --acl-public put bundles/$VERSION/ubuntu/gpg s3://$BUCKET/gpg 276 277 local gpgFingerprint=36A1D7869245C8950F966E92D8576A8BA88D21E9 278 if [[ $BUCKET == test* ]]; then 279 gpgFingerprint=740B314AE3941731B942C66ADF4FD13717AAD7D6 280 fi 281 282 # Upload repo 283 s3cmd --acl-public sync $APTDIR/ s3://$BUCKET/ubuntu/ 284 cat <<EOF | write_to_s3 s3://$BUCKET/ubuntu/index 285 # Check that HTTPS transport is available to APT 286 if [ ! -e /usr/lib/apt/methods/https ]; then 287 apt-get update 288 apt-get install -y apt-transport-https 289 fi 290 291 # Add the repository to your APT sources 292 echo deb $(s3_url)/ubuntu docker main > /etc/apt/sources.list.d/docker.list 293 294 # Then import the repository key 295 apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys $gpgFingerprint 296 297 # Install docker 298 apt-get update 299 apt-get install -y lxc-docker 300 301 # 302 # Alternatively, just use the curl-able install.sh script provided at $(s3_url) 303 # 304 EOF 305 306 # Add redirect at /ubuntu/info for URL-backwards-compatibility 307 rm -rf /tmp/emptyfile && touch /tmp/emptyfile 308 s3cmd --acl-public --add-header='x-amz-website-redirect-location:/ubuntu/' --mime-type='text/plain' put /tmp/emptyfile s3://$BUCKET/ubuntu/info 309 310 echo "APT repository uploaded. Instructions available at $(s3_url)/ubuntu" 311 } 312 313 # Upload binaries and tgz files to S3 314 release_binaries() { 315 [ -e bundles/$VERSION/cross/linux/amd64/docker-$VERSION ] || { 316 echo >&2 './hack/make.sh must be run before release_binaries' 317 exit 1 318 } 319 320 for d in bundles/$VERSION/cross/*/*; do 321 GOARCH="$(basename "$d")" 322 GOOS="$(basename "$(dirname "$d")")" 323 release_build "$GOOS" "$GOARCH" 324 done 325 326 # TODO create redirect from builds/*/i686 to builds/*/i386 327 328 cat <<EOF | write_to_s3 s3://$BUCKET/builds/index 329 # To install, run the following command as root: 330 curl -sSL -O $(s3_url)/builds/Linux/x86_64/docker-$VERSION && chmod +x docker-$VERSION && sudo mv docker-$VERSION /usr/local/bin/docker 331 # Then start docker in daemon mode: 332 sudo /usr/local/bin/docker -d 333 EOF 334 335 # Add redirect at /builds/info for URL-backwards-compatibility 336 rm -rf /tmp/emptyfile && touch /tmp/emptyfile 337 s3cmd --acl-public --add-header='x-amz-website-redirect-location:/builds/' --mime-type='text/plain' put /tmp/emptyfile s3://$BUCKET/builds/info 338 339 if [ -z "$NOLATEST" ]; then 340 echo "Advertising $VERSION on $BUCKET as most recent version" 341 echo $VERSION | write_to_s3 s3://$BUCKET/latest 342 fi 343 } 344 345 # Upload the index script 346 release_index() { 347 sed "s,url='https://get.docker.com/',url='$(s3_url)/'," hack/install.sh | write_to_s3 s3://$BUCKET/index 348 } 349 350 release_test() { 351 if [ -e "bundles/$VERSION/test" ]; then 352 s3cmd --acl-public sync bundles/$VERSION/test/ s3://$BUCKET/test/ 353 fi 354 } 355 356 setup_gpg() { 357 # Make sure that we have our keys 358 mkdir -p $HOME/.gnupg/ 359 s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ $HOME/.gnupg/ || true 360 gpg --list-keys releasedocker >/dev/null || { 361 gpg --gen-key --batch <<EOF 362 Key-Type: RSA 363 Key-Length: 4096 364 Passphrase: $GPG_PASSPHRASE 365 Name-Real: Docker Release Tool 366 Name-Email: docker@docker.com 367 Name-Comment: releasedocker 368 Expire-Date: 0 369 %commit 370 EOF 371 } 372 } 373 374 main() { 375 build_all 376 setup_s3 377 setup_gpg 378 release_binaries 379 release_ubuntu 380 release_index 381 release_test 382 } 383 384 main 385 386 echo 387 echo 388 echo "Release complete; see $(s3_url)" 389 echo