83a2e92d |
#!/bin/bash
set -e |
ccc39695 |
|
d9f76993 |
# This script looks for bundles built by make.sh, and releases them on a
# public S3 bucket. |
ccc39695 |
#
# Bundles should be available for the VERSION string passed as argument.
# |
d9f76993 |
# The correct way to call this script is inside a container built by the
# official Dockerfile at the root of the Docker source code. The Dockerfile,
# make.sh and release.sh should all be from the same source code revision. |
ccc39695 |
|
83a2e92d |
set -o pipefail |
ccc39695 |
# Print a usage message and exit.
usage() { |
83a2e92d |
cat >&2 <<'EOF' |
ff30eb96 |
To run, I need:
- to be in a container generated by the Dockerfile at the top of the Docker
repository;
- to be provided with the name of an S3 bucket, in environment variable
AWS_S3_BUCKET;
- to be provided with AWS credentials for this S3 bucket, in environment
variables AWS_ACCESS_KEY and AWS_SECRET_KEY; |
9c06420b |
- the passphrase to unlock the GPG key which will sign the deb packages
(passed as environment variable GPG_PASSPHRASE); |
ff30eb96 |
- a generous amount of good will and nice manners.
The canonical way to run me is to run the image produced by the Dockerfile: e.g.:"
|
83a2e92d |
docker run -e AWS_S3_BUCKET=get-staging.docker.io \
-e AWS_ACCESS_KEY=AKI1234... \
-e AWS_SECRET_KEY=sEs4mE... \
-e GPG_PASSPHRASE=m0resEs4mE... \
-i -t -privileged \
docker ./hack/release.sh |
ff30eb96 |
EOF |
ccc39695 |
exit 1
}
|
ff30eb96 |
[ "$AWS_S3_BUCKET" ] || usage
[ "$AWS_ACCESS_KEY" ] || usage
[ "$AWS_SECRET_KEY" ] || usage |
9c06420b |
[ "$GPG_PASSPHRASE" ] || usage |
83a2e92d |
[ -d /go/src/github.com/dotcloud/docker ] || usage
cd /go/src/github.com/dotcloud/docker
[ -x hack/make.sh ] || usage
RELEASE_BUNDLES=(
binary |
62a81370 |
cross |
b3f5973f |
tgz |
83a2e92d |
ubuntu
)
if [ "$1" != '--release-regardless-of-test-failure' ]; then
RELEASE_BUNDLES=( test "${RELEASE_BUNDLES[@]}" )
fi
if ! ./hack/make.sh "${RELEASE_BUNDLES[@]}"; then
echo >&2
echo >&2 'The build or tests appear to have failed.'
echo >&2
echo >&2 'You, as the release maintainer, now have a couple options:'
echo >&2 '- delay release and fix issues'
echo >&2 '- delay release and fix issues'
echo >&2 '- did we mention how important this is? issues need fixing :)'
echo >&2
echo >&2 'As a final LAST RESORT, you (because only you, the release maintainer,'
echo >&2 ' really knows all the hairy problems at hand with the current release'
echo >&2 ' issues) may bypass this checking by running this script again with the'
echo >&2 ' single argument of "--release-regardless-of-test-failure", which will skip'
echo >&2 ' running the test suite, and will only build the binaries and packages. Please'
echo >&2 ' avoid using this if at all possible.'
echo >&2
echo >&2 'Regardless, we cannot stress enough the scarcity with which this bypass'
echo >&2 ' should be used. If there are release issues, we should always err on the'
echo >&2 ' side of caution.'
echo >&2
exit 1
fi |
ff30eb96 |
VERSION=$(cat VERSION) |
ab4fb9bb |
BUCKET=$AWS_S3_BUCKET |
ccc39695 |
setup_s3() {
# Try creating the bucket. Ignore errors (it might already exist). |
0469e476 |
s3cmd mb s3://$BUCKET 2>/dev/null || true |
ab4fb9bb |
# Check access to the bucket.
# s3cmd has no useful exit status, so we cannot check that.
# Instead, we check if it outputs anything on standard output.
# (When there are problems, it uses standard error instead.)
s3cmd info s3://$BUCKET | grep -q . |
0469e476 |
# Make the bucket accessible through website endpoints.
s3cmd ws-create --ws-index index --ws-error error s3://$BUCKET |
ccc39695 |
}
# write_to_s3 uploads the contents of standard input to the specified S3 url.
write_to_s3() {
DEST=$1
F=`mktemp`
cat > $F |
7f1b179c |
s3cmd --acl-public --mime-type='text/plain' put $F $DEST |
ccc39695 |
rm -f $F
}
s3_url() { |
94bf5b00 |
case "$BUCKET" in
get.docker.io|test.docker.io)
echo "https://$BUCKET"
;;
*) |
b8e7ec1b |
s3cmd ws-info s3://$BUCKET | awk -v 'FS=: +' '/http:\/\/'$BUCKET'/ { gsub(/\/+$/, "", $2); print $2 }' |
94bf5b00 |
;;
esac |
ccc39695 |
}
|
4100e9b7 |
release_build() {
GOOS=$1
GOARCH=$2
BINARY=bundles/$VERSION/cross/$GOOS/$GOARCH/docker-$VERSION
TGZ=bundles/$VERSION/tgz/$GOOS/$GOARCH/docker-$VERSION.tgz
# we need to map our GOOS and GOARCH to uname values
# see https://en.wikipedia.org/wiki/Uname
# ie, GOOS=linux -> "uname -s"=Linux
S3OS=$GOOS
case "$S3OS" in
darwin)
S3OS=Darwin
;;
freebsd)
S3OS=FreeBSD
;;
linux)
S3OS=Linux
;;
*)
echo >&2 "error: can't convert $S3OS to an appropriate value for 'uname -s'"
exit 1
;;
esac
S3ARCH=$GOARCH
case "$S3ARCH" in
amd64)
S3ARCH=x86_64
;;
386)
S3ARCH=i386
;;
arm)
# GOARCH is fine
;;
*)
echo >&2 "error: can't convert $S3ARCH to an appropriate value for 'uname -m'"
exit 1
;;
esac
S3DIR=s3://$BUCKET/builds/$S3OS/$S3ARCH
if [ ! -x "$BINARY" ]; then
echo >&2 "error: can't find $BINARY - was it compiled properly?"
exit 1
fi
if [ ! -f "$TGZ" ]; then
echo >&2 "error: can't find $TGZ - was it packaged properly?"
exit 1
fi
echo "Uploading $BINARY to $S3OS/$S3ARCH/docker-$VERSION"
s3cmd --follow-symlinks --preserve --acl-public put $BINARY $S3DIR/docker-$VERSION
echo "Uploading $TGZ to $S3OS/$S3ARCH/docker-$VERSION.tgz"
s3cmd --follow-symlinks --preserve --acl-public put $TGZ $S3DIR/docker-$VERSION.tgz
if [ -z "$NOLATEST" ]; then
echo "Copying $S3OS/$S3ARCH/docker-$VERSION to $S3OS/$S3ARCH/docker-latest"
s3cmd --acl-public cp $S3DIR/docker-$VERSION $S3DIR/docker-latest
echo "Copying $S3OS/$S3ARCH/docker-$VERSION.tgz to $S3OS/$S3ARCH/docker-latest.tgz"
s3cmd --acl-public cp $S3DIR/docker-$VERSION.tgz $S3DIR/docker-latest.tgz
fi
}
|
ccc39695 |
# Upload the 'ubuntu' bundle to S3:
# 1. A full APT repository is published at $BUCKET/ubuntu/ |
f56945d7 |
# 2. Instructions for using the APT repository are uploaded at $BUCKET/ubuntu/index |
ccc39695 |
release_ubuntu() { |
83a2e92d |
[ -e bundles/$VERSION/ubuntu ] || {
echo >&2 './hack/make.sh must be run before release_ubuntu'
exit 1
} |
9c06420b |
# Make sure that we have our keys
mkdir -p /.gnupg/
s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ /.gnupg/ || true
gpg --list-keys releasedocker >/dev/null || { |
83a2e92d |
gpg --gen-key --batch <<EOF |
9c06420b |
Key-Type: RSA
Key-Length: 2048
Passphrase: $GPG_PASSPHRASE
Name-Real: Docker Release Tool
Name-Email: docker@dotcloud.com
Name-Comment: releasedocker
Expire-Date: 0
%commit
EOF
}
# Sign our packages
dpkg-sig -g "--passphrase $GPG_PASSPHRASE" -k releasedocker \ |
83a2e92d |
--sign builder bundles/$VERSION/ubuntu/*.deb |
9c06420b |
|
5b0eaef6 |
# Setup the APT repo
APTDIR=bundles/$VERSION/ubuntu/apt
mkdir -p $APTDIR/conf $APTDIR/db
s3cmd sync s3://$BUCKET/ubuntu/db/ $APTDIR/db/ || true
cat > $APTDIR/conf/distributions <<EOF
Codename: docker
Components: main |
87872006 |
Architectures: amd64 i386 |
5b0eaef6 |
EOF
# Add the DEB package to the APT repo
DEBFILE=bundles/$VERSION/ubuntu/lxc-docker*.deb
reprepro -b $APTDIR includedeb docker $DEBFILE
|
9c06420b |
# Sign |
83a2e92d |
for F in $(find $APTDIR -name Release); do |
9c06420b |
gpg -u releasedocker --passphrase $GPG_PASSPHRASE \
--armor --sign --detach-sign \
--output $F.gpg $F
done
# Upload keys
s3cmd sync /.gnupg/ s3://$BUCKET/ubuntu/.gnupg/
gpg --armor --export releasedocker > bundles/$VERSION/ubuntu/gpg
s3cmd --acl-public put bundles/$VERSION/ubuntu/gpg s3://$BUCKET/gpg
# Upload repo
s3cmd --acl-public sync $APTDIR/ s3://$BUCKET/ubuntu/ |
f56945d7 |
cat <<EOF | write_to_s3 s3://$BUCKET/ubuntu/index |
9c06420b |
# Add the repository to your APT sources |
94bf5b00 |
echo deb $(s3_url)/ubuntu docker main > /etc/apt/sources.list.d/docker.list |
9c06420b |
# Then import the repository key |
94bf5b00 |
curl $(s3_url)/gpg | apt-key add - |
9c06420b |
# Install docker |
a8059059 |
apt-get update ; apt-get install -y lxc-docker |
83a2e92d |
#
# Alternatively, just use the curl-able install.sh script provided at $(s3_url)
# |
ccc39695 |
EOF |
f56945d7 |
# Add redirect at /ubuntu/info for URL-backwards-compatibility
rm -rf /tmp/emptyfile && touch /tmp/emptyfile
s3cmd --acl-public --add-header='x-amz-website-redirect-location:/ubuntu/' --mime-type='text/plain' put /tmp/emptyfile s3://$BUCKET/ubuntu/info
echo "APT repository uploaded. Instructions available at $(s3_url)/ubuntu" |
ccc39695 |
}
|
4100e9b7 |
# Upload binaries and tgz files to S3
release_binaries() {
[ -e bundles/$VERSION/cross/linux/amd64/docker-$VERSION ] || {
echo >&2 './hack/make.sh must be run before release_binaries' |
b3f5973f |
exit 1
}
|
4100e9b7 |
for d in bundles/$VERSION/cross/*/*; do
GOARCH="$(basename "$d")"
GOOS="$(basename "$(dirname "$d")")"
release_build "$GOOS" "$GOARCH"
done |
b3f5973f |
|
4100e9b7 |
# TODO create redirect from builds/*/i686 to builds/*/i386 |
f56945d7 |
cat <<EOF | write_to_s3 s3://$BUCKET/builds/index |
ccc39695 |
# To install, run the following command as root: |
94bf5b00 |
curl -O $(s3_url)/builds/Linux/x86_64/docker-$VERSION && chmod +x docker-$VERSION && sudo mv docker-$VERSION /usr/local/bin/docker |
ccc39695 |
# Then start docker in daemon mode:
sudo /usr/local/bin/docker -d
EOF |
f56945d7 |
# Add redirect at /builds/info for URL-backwards-compatibility
rm -rf /tmp/emptyfile && touch /tmp/emptyfile
s3cmd --acl-public --add-header='x-amz-website-redirect-location:/builds/' --mime-type='text/plain' put /tmp/emptyfile s3://$BUCKET/builds/info
|
ccc39695 |
if [ -z "$NOLATEST" ]; then
echo "Advertising $VERSION on $BUCKET as most recent version"
echo $VERSION | write_to_s3 s3://$BUCKET/latest
fi
}
|
0469e476 |
# Upload the index script
release_index() { |
94bf5b00 |
sed "s,https://get.docker.io/,$(s3_url)/," hack/install.sh | write_to_s3 s3://$BUCKET/index |
0469e476 |
}
|
59856a20 |
release_test() {
if [ -e "bundles/$VERSION/test" ]; then
s3cmd --acl-public sync bundles/$VERSION/test/ s3://$BUCKET/test/
fi
}
|
ccc39695 |
main() {
setup_s3 |
4100e9b7 |
release_binaries |
ccc39695 |
release_ubuntu |
0469e476 |
release_index |
59856a20 |
release_test |
ccc39695 |
}
main |
4100e9b7 |
echo
echo
echo "Release complete; see $(s3_url)"
echo |