diff options
Diffstat (limited to 'script')
29 files changed, 1000 insertions, 0 deletions
diff --git a/script/build/image b/script/build/image new file mode 100755 index 00000000..a3198c99 --- /dev/null +++ b/script/build/image @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +if [ -z "$1" ]; then + >&2 echo "First argument must be image tag." + exit 1 +fi + +TAG=$1 + +VERSION="$(python setup.py --version)" + +./script/build/write-git-sha +python setup.py sdist bdist_wheel +./script/build/linux +docker build -t docker/compose:$TAG -f Dockerfile.run . diff --git a/script/build/linux b/script/build/linux new file mode 100755 index 00000000..1a4cd4d9 --- /dev/null +++ b/script/build/linux @@ -0,0 +1,13 @@ +#!/bin/bash + +set -ex + +./script/clean + +TAG="docker-compose" +docker build -t "$TAG" . | tail -n 200 +docker run \ + --rm --entrypoint="script/build/linux-entrypoint" \ + -v $(pwd)/dist:/code/dist \ + -v $(pwd)/.git:/code/.git \ + "$TAG" diff --git a/script/build/linux-entrypoint b/script/build/linux-entrypoint new file mode 100755 index 00000000..bf515060 --- /dev/null +++ b/script/build/linux-entrypoint @@ -0,0 +1,15 @@ +#!/bin/bash + +set -ex + +TARGET=dist/docker-compose-$(uname -s)-$(uname -m) +VENV=/code/.tox/py27 + +mkdir -p `pwd`/dist +chmod 777 `pwd`/dist + +$VENV/bin/pip install -q -r requirements-build.txt +./script/build/write-git-sha +su -c "$VENV/bin/pyinstaller docker-compose.spec" user +mv dist/docker-compose $TARGET +$TARGET version diff --git a/script/build/osx b/script/build/osx new file mode 100755 index 00000000..3de34576 --- /dev/null +++ b/script/build/osx @@ -0,0 +1,15 @@ +#!/bin/bash +set -ex + +PATH="/usr/local/bin:$PATH" + +rm -rf venv + +virtualenv -p /usr/local/bin/python venv +venv/bin/pip install -r requirements.txt +venv/bin/pip install -r requirements-build.txt +venv/bin/pip install --no-deps . +./script/build/write-git-sha +venv/bin/pyinstaller docker-compose.spec +mv dist/docker-compose dist/docker-compose-Darwin-x86_64 +dist/docker-compose-Darwin-x86_64 version diff --git a/script/build/test-image b/script/build/test-image new file mode 100755 index 00000000..a2eb62cd --- /dev/null +++ b/script/build/test-image @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +if [ -z "$1" ]; then + >&2 echo "First argument must be image tag." + exit 1 +fi + +TAG=$1 + +docker build -t docker-compose-tests:tmp . +ctnr_id=$(docker create --entrypoint=tox docker-compose-tests:tmp) +docker commit $ctnr_id docker/compose-tests:latest +docker tag docker/compose-tests:latest docker/compose-tests:$TAG +docker rm -f $ctnr_id +docker rmi -f docker-compose-tests:tmp diff --git a/script/build/windows.ps1 b/script/build/windows.ps1 new file mode 100644 index 00000000..db643274 --- /dev/null +++ b/script/build/windows.ps1 @@ -0,0 +1,60 @@ +# Builds the Windows binary. +# +# From a fresh 64-bit Windows 10 install, prepare the system as follows: +# +# 1. Install Git: +# +# http://git-scm.com/download/win +# +# 2. Install Python 2.7.10: +# +# https://www.python.org/downloads/ +# +# 3. Append ";C:\Python27;C:\Python27\Scripts" to the "Path" environment variable: +# +# https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/sysdm_advancd_environmnt_addchange_variable.mspx?mfr=true +# +# 4. In Powershell, run the following commands: +# +# $ pip install virtualenv +# $ Set-ExecutionPolicy -Scope CurrentUser RemoteSigned +# +# 5. Clone the repository: +# +# $ git clone https://github.com/docker/compose.git +# $ cd compose +# +# 6. Build the binary: +# +# .\script\build\windows.ps1 + +$ErrorActionPreference = "Stop" + +# Remove virtualenv +if (Test-Path venv) { + Remove-Item -Recurse -Force .\venv +} + +# Remove .pyc files +Get-ChildItem -Recurse -Include *.pyc | foreach ($_) { Remove-Item $_.FullName } + +# Create virtualenv +virtualenv .\venv + +# pip and pyinstaller generate lots of warnings, so we need to ignore them +$ErrorActionPreference = "Continue" + +# Install dependencies +.\venv\Scripts\pip install pypiwin32==219 +.\venv\Scripts\pip install -r requirements.txt +.\venv\Scripts\pip install --no-deps . +.\venv\Scripts\pip install --allow-external pyinstaller -r requirements-build.txt + +git rev-parse --short HEAD | out-file -encoding ASCII compose\GITSHA + +# Build binary +.\venv\Scripts\pyinstaller .\docker-compose.spec +$ErrorActionPreference = "Stop" + +Move-Item -Force .\dist\docker-compose.exe .\dist\docker-compose-Windows-x86_64.exe +.\dist\docker-compose-Windows-x86_64.exe --version diff --git a/script/build/write-git-sha b/script/build/write-git-sha new file mode 100755 index 00000000..d16743c6 --- /dev/null +++ b/script/build/write-git-sha @@ -0,0 +1,7 @@ +#!/bin/bash +# +# Write the current commit sha to the file GITSHA. This file is included in +# packaging so that `docker-compose version` can include the git sha. +# +set -e +git rev-parse --short HEAD > compose/GITSHA diff --git a/script/ci b/script/ci new file mode 100755 index 00000000..34bf9a4b --- /dev/null +++ b/script/ci @@ -0,0 +1,8 @@ +#!/bin/bash +# +# Backwards compatibility for jenkins +# +# TODO: remove this script after all current PRs and jenkins are updated with +# the new script/test/ci change +set -e +exec script/test/ci diff --git a/script/clean b/script/clean new file mode 100755 index 00000000..fb7ba3be --- /dev/null +++ b/script/clean @@ -0,0 +1,7 @@ +#!/bin/sh +set -e + +find . -type f -name '*.pyc' -delete +find . -name .coverage.* -delete +find . -name __pycache__ -delete +rm -rf docs/_site build dist docker-compose.egg-info diff --git a/script/release/build-binaries b/script/release/build-binaries new file mode 100755 index 00000000..a39b186d --- /dev/null +++ b/script/release/build-binaries @@ -0,0 +1,40 @@ +#!/bin/bash +# +# Build the release binaries +# + +. "$(dirname "${BASH_SOURCE[0]}")/utils.sh" + +function usage() { + >&2 cat << EOM +Build binaries for the release. + +This script requires that 'git config branch.${BRANCH}.release' is set to the +release version for the release branch. + +EOM + exit 1 +} + +BRANCH="$(git rev-parse --abbrev-ref HEAD)" +VERSION="$(git config "branch.${BRANCH}.release")" || usage +REPO=docker/compose + +# Build the binaries +script/clean +script/build/linux + +echo "Building the container distribution" +script/build/image $VERSION + +echo "Building the compose-tests image" +script/build/test-image $VERSION + +echo "Create a github release" +# TODO: script more of this https://developer.github.com/v3/repos/releases/ +browser https://github.com/$REPO/releases/new + +echo "Don't forget to download the osx and windows binaries from appveyor/bintray\!" +echo "https://dl.bintray.com/docker-compose/$BRANCH/" +echo "https://ci.appveyor.com/project/docker/compose" +echo diff --git a/script/release/cherry-pick-pr b/script/release/cherry-pick-pr new file mode 100755 index 00000000..f4a5a740 --- /dev/null +++ b/script/release/cherry-pick-pr @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Cherry-pick a PR into the release branch +# + +set -e +set -o pipefail + + +function usage() { + >&2 cat << EOM +Cherry-pick commits from a github pull request. + +Usage: + + $0 <github PR number> +EOM + exit 1 +} + +[ -n "$1" ] || usage + +if [ -z "$(command -v hub 2> /dev/null)" ]; then + >&2 echo "$0 requires https://hub.github.com/." + >&2 echo "Please install it and make sure it is available on your \$PATH." + exit 2 +fi + + +REPO=docker/compose +GITHUB=https://github.com/$REPO/pull +PR=$1 +url="$GITHUB/$PR" +hub am -3 $url diff --git a/script/release/contributors b/script/release/contributors new file mode 100755 index 00000000..4657dd80 --- /dev/null +++ b/script/release/contributors @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + + +function usage() { + >&2 cat << EOM +Print the list of github contributors for the release + +Usage: + + $0 <previous release tag> +EOM + exit 1 +} + +[[ -n "$1" ]] || usage +PREV_RELEASE=$1 +BRANCH="$(git rev-parse --abbrev-ref HEAD)" +URL="https://api.github.com/repos/docker/compose/compare" + +contribs=$(curl -sf "$URL/$PREV_RELEASE...$BRANCH" | \ + jq -r '.commits[].author.login' | \ + sort | \ + uniq -c | \ + sort -nr) + +echo "Contributions by user: " +echo "$contribs" +echo +echo "$contribs" | awk '{print "@"$2","}' | xargs diff --git a/script/release/download-binaries b/script/release/download-binaries new file mode 100755 index 00000000..5d01f5f7 --- /dev/null +++ b/script/release/download-binaries @@ -0,0 +1,32 @@ +#!/bin/bash + +function usage() { + >&2 cat << EOM +Download Linux, Mac OS and Windows binaries from remote endpoints + +Usage: + + $0 <version> + +Options: + + version version string for the release (ex: 1.6.0) + +EOM + exit 1 +} + + +[ -n "$1" ] || usage +VERSION=$1 +BASE_BINTRAY_URL=https://dl.bintray.com/docker-compose/bump-$VERSION/ +DESTINATION=binaries-$VERSION +APPVEYOR_URL=https://ci.appveyor.com/api/projects/docker/compose/\ +artifacts/dist%2Fdocker-compose-Windows-x86_64.exe?branch=bump-$VERSION + +mkdir $DESTINATION + + +wget -O $DESTINATION/docker-compose-Darwin-x86_64 $BASE_BINTRAY_URL/docker-compose-Darwin-x86_64 +wget -O $DESTINATION/docker-compose-Linux-x86_64 $BASE_BINTRAY_URL/docker-compose-Linux-x86_64 +wget -O $DESTINATION/docker-compose-Windows-x86_64.exe $APPVEYOR_URL diff --git a/script/release/make-branch b/script/release/make-branch new file mode 100755 index 00000000..b8a0cd31 --- /dev/null +++ b/script/release/make-branch @@ -0,0 +1,86 @@ +#!/bin/bash +# +# Prepare a new release branch +# + +. "$(dirname "${BASH_SOURCE[0]}")/utils.sh" + +function usage() { + >&2 cat << EOM +Create a new release branch 'release-<version>' + +Usage: + + $0 <version> [<base_version>] + +Options: + + version version string for the release (ex: 1.6.0) + base_version branch or tag to start from. Defaults to master. For + bug-fix releases use the previous stage release tag. + +EOM + exit 1 +} + + +[ -n "$1" ] || usage +VERSION=$1 +BRANCH=bump-$VERSION +REPO=docker/compose +GITHUB_REPO=git@github.com:$REPO + +if [ -z "$2" ]; then + BASE_VERSION="master" +else + BASE_VERSION=$2 +fi + + +DEFAULT_REMOTE=release +REMOTE="$(find_remote "$GITHUB_REPO")" +# If we don't have a docker remote add one +if [ -z "$REMOTE" ]; then + echo "Creating $DEFAULT_REMOTE remote" + git remote add ${DEFAULT_REMOTE} ${GITHUB_REPO} +fi + +# handle the difference between a branch and a tag +if [ -z "$(git name-rev --tags $BASE_VERSION | grep tags)" ]; then + BASE_VERSION=$REMOTE/$BASE_VERSION +fi + +echo "Creating a release branch $VERSION from $BASE_VERSION" +read -n1 -r -p "Continue? (ctrl+c to cancel)" +git fetch $REMOTE -p +git checkout -b $BRANCH $BASE_VERSION + +echo "Merging remote release branch into new release branch" +git merge --strategy=ours --no-edit $REMOTE/release + +# Store the release version for this branch in git, so that other release +# scripts can use it +git config "branch.${BRANCH}.release" $VERSION + + +editor=${EDITOR:-vim} + +echo "Update versions in compose/__init__.py, script/run/run.sh" +$editor compose/__init__.py +$editor script/run/run.sh + + +echo "Write release notes in CHANGELOG.md" +browser "https://github.com/docker/compose/issues?q=milestone%3A$VERSION+is%3Aclosed" +$editor CHANGELOG.md + + +git diff +echo "Verify changes before commit. Exit the shell to commit changes" +$SHELL || true +git commit -a -m "Bump $VERSION" --signoff --no-verify + + +echo "Push branch to docker remote" +git push $REMOTE +browser https://github.com/$REPO/compare/docker:release...$BRANCH?expand=1 diff --git a/script/release/push-release b/script/release/push-release new file mode 100755 index 00000000..0578aaff --- /dev/null +++ b/script/release/push-release @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Create the official release +# + +. "$(dirname "${BASH_SOURCE[0]}")/utils.sh" + +function usage() { + >&2 cat << EOM +Publish a release by building all artifacts and pushing them. + +This script requires that 'git config branch.${BRANCH}.release' is set to the +release version for the release branch. + +EOM + exit 1 +} + +BRANCH="$(git rev-parse --abbrev-ref HEAD)" +VERSION="$(git config "branch.${BRANCH}.release")" || usage + +if [ -z "$(command -v jq 2> /dev/null)" ]; then + >&2 echo "$0 requires https://stedolan.github.io/jq/" + >&2 echo "Please install it and make sure it is available on your \$PATH." + exit 2 +fi + + +if [ -z "$(command -v pandoc 2> /dev/null)" ]; then + >&2 echo "$0 requires http://pandoc.org/" + >&2 echo "Please install it and make sure it is available on your \$PATH." + exit 2 +fi + +API=https://api.github.com/repos +REPO=docker/compose +GITHUB_REPO=git@github.com:$REPO + +# Check the build status is green +sha=$(git rev-parse HEAD) +url=$API/$REPO/statuses/$sha +build_status=$(curl -s $url | jq -r '.[0].state') +if [ -n "$SKIP_BUILD_CHECK" ]; then + echo "Skipping build status check..." +elif [[ "$build_status" != "success" ]]; then + >&2 echo "Build status is $build_status, but it should be success." + exit -1 +fi + +echo "Tagging the release as $VERSION" +git tag $VERSION +git push $GITHUB_REPO $VERSION + +echo "Uploading the docker image" +docker push docker/compose:$VERSION + +echo "Uploading the compose-tests image" +docker push docker/compose-tests:latest +docker push docker/compose-tests:$VERSION + +echo "Uploading package to PyPI" +pandoc -f markdown -t rst README.md -o README.rst +sed -i -e 's/logo.png?raw=true/https:\/\/github.com\/docker\/compose\/raw\/master\/logo.png?raw=true/' README.rst +./script/build/write-git-sha +python setup.py sdist bdist_wheel +if [ "$(command -v twine 2> /dev/null)" ]; then + twine upload ./dist/docker-compose-${VERSION/-/}.tar.gz ./dist/docker_compose-${VERSION/-/}-py2.py3-none-any.whl +else + python setup.py upload +fi + +echo "Testing pip package" +deactivate || true +virtualenv venv-test +source venv-test/bin/activate +pip install docker-compose==$VERSION +docker-compose version +deactivate +rm -rf venv-test + +echo "Now publish the github release, and test the downloads." +echo "Email maintainers@dockerproject.org and engineering@docker.com about the new release." diff --git a/script/release/rebase-bump-commit b/script/release/rebase-bump-commit new file mode 100755 index 00000000..3c2ae72b --- /dev/null +++ b/script/release/rebase-bump-commit @@ -0,0 +1,38 @@ +#!/bin/bash +# +# Move the "bump to <version>" commit to the HEAD of the branch +# + +. "$(dirname "${BASH_SOURCE[0]}")/utils.sh" + +function usage() { + >&2 cat << EOM +Move the "bump to <version>" commit to the HEAD of the branch + +This script requires that 'git config branch.${BRANCH}.release' is set to the +release version for the release branch. + +EOM + exit 1 +} + + +BRANCH="$(git rev-parse --abbrev-ref HEAD)" +VERSION="$(git config "branch.${BRANCH}.release")" || usage + + +COMMIT_MSG="Bump $VERSION" +sha="$(git log --grep "$COMMIT_MSG\$" --format="%H")" +if [ -z "$sha" ]; then + >&2 echo "No commit with message \"$COMMIT_MSG\"" + exit 2 +fi +if [[ "$sha" == "$(git rev-parse HEAD)" ]]; then + >&2 echo "Bump commit already at HEAD" + exit 0 +fi + +commits=$(git log --format="%H" "$sha..HEAD" | wc -l | xargs echo) + +git rebase --onto $sha~1 HEAD~$commits $BRANCH +git cherry-pick $sha diff --git a/script/release/utils.sh b/script/release/utils.sh new file mode 100644 index 00000000..321c1fb7 --- /dev/null +++ b/script/release/utils.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# +# Util functions for release scripts +# + +set -e +set -o pipefail + + +function browser() { + local url=$1 + xdg-open $url || open $url +} + + +function find_remote() { + local url=$1 + for remote in $(git remote); do + git config --get remote.${remote}.url | grep $url > /dev/null && echo -n $remote + done + # Always return true, extra remotes cause it to return false + true +} diff --git a/script/run/run.ps1 b/script/run/run.ps1 new file mode 100644 index 00000000..47ec5469 --- /dev/null +++ b/script/run/run.ps1 @@ -0,0 +1,22 @@ +# Run docker-compose in a container via boot2docker.
+#
+# The current directory will be mirrored as a volume and additional
+# volumes (or any other options) can be mounted by using
+# $Env:DOCKER_COMPOSE_OPTIONS.
+
+if ($Env:DOCKER_COMPOSE_VERSION -eq $null -or $Env:DOCKER_COMPOSE_VERSION.Length -eq 0) {
+ $Env:DOCKER_COMPOSE_VERSION = "latest"
+}
+
+if ($Env:DOCKER_COMPOSE_OPTIONS -eq $null) {
+ $Env:DOCKER_COMPOSE_OPTIONS = ""
+}
+
+if (-not $Env:DOCKER_HOST) {
+ docker-machine env --shell=powershell default | Invoke-Expression
+ if (-not $?) { exit $LastExitCode }
+}
+
+$local="/$($PWD -replace '^(.):(.*)$', '"$1".ToLower()+"$2".Replace("\","/")' | Invoke-Expression)"
+docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock -v "${local}:$local" -w "$local" $Env:DOCKER_COMPOSE_OPTIONS "docker/compose:$Env:DOCKER_COMPOSE_VERSION" $args
+exit $LastExitCode
diff --git a/script/run/run.sh b/script/run/run.sh new file mode 100755 index 00000000..58483196 --- /dev/null +++ b/script/run/run.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Run docker-compose in a container +# +# This script will attempt to mirror the host paths by using volumes for the +# following paths: +# * $(pwd) +# * $(dirname $COMPOSE_FILE) if it's set +# * $HOME if it's set +# +# You can add additional volumes (or any docker run options) using +# the $COMPOSE_OPTIONS environment variable. +# + + +set -e + +VERSION="1.17.1" +IMAGE="docker/compose:$VERSION" + + +# Setup options for connecting to docker host +if [ -z "$DOCKER_HOST" ]; then + DOCKER_HOST="/var/run/docker.sock" +fi +if [ -S "$DOCKER_HOST" ]; then + DOCKER_ADDR="-v $DOCKER_HOST:$DOCKER_HOST -e DOCKER_HOST" +else + DOCKER_ADDR="-e DOCKER_HOST -e DOCKER_TLS_VERIFY -e DOCKER_CERT_PATH" +fi + + +# Setup volume mounts for compose config and context +if [ "$(pwd)" != '/' ]; then + VOLUMES="-v $(pwd):$(pwd)" +fi +if [ -n "$COMPOSE_FILE" ]; then + COMPOSE_OPTIONS="$COMPOSE_OPTIONS -e COMPOSE_FILE=$COMPOSE_FILE" + compose_dir=$(realpath $(dirname $COMPOSE_FILE)) +fi +# TODO: also check --file argument +if [ -n "$compose_dir" ]; then + VOLUMES="$VOLUMES -v $compose_dir:$compose_dir" +fi +if [ -n "$HOME" ]; then + VOLUMES="$VOLUMES -v $HOME:$HOME -v $HOME:/root" # mount $HOME in /root to share docker.config +fi + +# Only allocate tty if we detect one +if [ -t 1 ]; then + DOCKER_RUN_OPTIONS="-t" +fi +if [ -t 0 ]; then + DOCKER_RUN_OPTIONS="$DOCKER_RUN_OPTIONS -i" +fi + +exec docker run --rm $DOCKER_RUN_OPTIONS $DOCKER_ADDR $COMPOSE_OPTIONS $VOLUMES -w "$(pwd)" $IMAGE "$@" diff --git a/script/setup/osx b/script/setup/osx new file mode 100755 index 00000000..e0c2bd0a --- /dev/null +++ b/script/setup/osx @@ -0,0 +1,52 @@ +#!/bin/bash + +set -ex + +python_version() { + python -V 2>&1 +} + +openssl_version() { + python -c "import ssl; print ssl.OPENSSL_VERSION" +} + +desired_python_version="2.7.12" +desired_python_brew_version="2.7.12" +python_formula="https://raw.githubusercontent.com/Homebrew/homebrew-core/737a2e34a89b213c1f0a2a24fc1a3c06635eed04/Formula/python.rb" + +desired_openssl_version="1.0.2j" +desired_openssl_brew_version="1.0.2j" +openssl_formula="https://raw.githubusercontent.com/Homebrew/homebrew-core/30d3766453347f6e22b3ed6c74bb926d6def2eb5/Formula/openssl.rb" + +PATH="/usr/local/bin:$PATH" + +if !(which brew); then + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" +fi + +brew update > /dev/null + +if !(python_version | grep "$desired_python_version"); then + if brew list | grep python; then + brew unlink python + fi + + brew install "$python_formula" + brew switch python "$desired_python_brew_version" +fi + +if !(openssl_version | grep "$desired_openssl_version"); then + if brew list | grep openssl; then + brew unlink openssl + fi + + brew install "$openssl_formula" + brew switch openssl "$desired_openssl_brew_version" +fi + +echo "*** Using $(python_version)" +echo "*** Using $(openssl_version)" + +if !(which virtualenv); then + pip install virtualenv +fi diff --git a/script/test/all b/script/test/all new file mode 100755 index 00000000..1200c496 --- /dev/null +++ b/script/test/all @@ -0,0 +1,64 @@ +#!/bin/bash +# This should be run inside a container built from the Dockerfile +# at the root of the repo - script/test will do it automatically. + +set -e + +>&2 echo "Running lint checks" +docker run --rm \ + --tty \ + ${GIT_VOLUME} \ + --entrypoint="tox" \ + "$TAG" -e pre-commit + +get_versions="docker run --rm + --entrypoint=/code/.tox/py27/bin/python + $TAG + /code/script/test/versions.py docker/docker-ce,moby/moby" + +if [ "$DOCKER_VERSIONS" == "" ]; then + DOCKER_VERSIONS="$($get_versions default)" +elif [ "$DOCKER_VERSIONS" == "all" ]; then + DOCKER_VERSIONS=$($get_versions -n 2 recent) +fi + + +BUILD_NUMBER=${BUILD_NUMBER-$USER} +PY_TEST_VERSIONS=${PY_TEST_VERSIONS:-py27,py34} + +for version in $DOCKER_VERSIONS; do + >&2 echo "Running tests against Docker $version" + + daemon_container="compose-dind-$version-$BUILD_NUMBER" + + function on_exit() { + if [[ "$?" != "0" ]]; then + docker logs "$daemon_container" 2>&1 | tail -n 100 + fi + docker rm -vf "$daemon_container" + } + + trap "on_exit" EXIT + + repo="dockerswarm/dind" + + docker run \ + -d \ + --name "$daemon_container" \ + --privileged \ + --volume="/var/lib/docker" \ + "$repo:$version" \ + dockerd -H tcp://0.0.0.0:2375 $DOCKER_DAEMON_ARGS \ + 2>&1 | tail -n 10 + + docker run \ + --rm \ + --tty \ + --link="$daemon_container:docker" \ + --env="DOCKER_HOST=tcp://docker:2375" \ + --env="DOCKER_VERSION=$version" \ + --entrypoint="tox" \ + "$TAG" \ + -e "$PY_TEST_VERSIONS" -- "$@" + +done diff --git a/script/test/ci b/script/test/ci new file mode 100755 index 00000000..c5927b2c --- /dev/null +++ b/script/test/ci @@ -0,0 +1,25 @@ +#!/bin/bash +# This should be run inside a container built from the Dockerfile +# at the root of the repo: +# +# $ TAG="docker-compose:$(git rev-parse --short HEAD)" +# $ docker build -t "$TAG" . +# $ docker run --rm \ +# --volume="/var/run/docker.sock:/var/run/docker.sock" \ +# --volume="$(pwd)/.git:/code/.git" \ +# -e "TAG=$TAG" \ +# --entrypoint="script/test/ci" "$TAG" + +set -ex + +docker version + +export DOCKER_VERSIONS=all +STORAGE_DRIVER=${STORAGE_DRIVER:-overlay} +export DOCKER_DAEMON_ARGS="--storage-driver=$STORAGE_DRIVER" + +GIT_VOLUME="--volumes-from=$(hostname)" +. script/test/all + +>&2 echo "Building Linux binary" +. script/build/linux-entrypoint diff --git a/script/test/default b/script/test/default new file mode 100755 index 00000000..aabb4e42 --- /dev/null +++ b/script/test/default @@ -0,0 +1,19 @@ +#!/bin/bash +# See CONTRIBUTING.md for usage. + +set -ex + +TAG="docker-compose:$(git rev-parse --short HEAD)" + +# By default use the Dockerfile, but can be overriden to use an alternative file +# e.g DOCKERFILE=Dockerfile.armhf script/test/default +DOCKERFILE="${DOCKERFILE:-Dockerfile}" + +rm -rf coverage-html +# Create the host directory so it's owned by $USER +mkdir -p coverage-html + +docker build -f ${DOCKERFILE} -t "$TAG" . + +GIT_VOLUME="--volume=$(pwd)/.git:/code/.git" +. script/test/all diff --git a/script/test/versions.py b/script/test/versions.py new file mode 100755 index 00000000..46872ed9 --- /dev/null +++ b/script/test/versions.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +""" +Query the github API for the git tags of a project, and return a list of +version tags for recent releases, or the default release. + +The default release is the most recent non-RC version. + +Recent is a list of unique major.minor versions, where each is the most +recent version in the series. + +For example, if the list of versions is: + + 1.8.0-rc2 + 1.8.0-rc1 + 1.7.1 + 1.7.0 + 1.7.0-rc1 + 1.6.2 + 1.6.1 + +`default` would return `1.7.1` and +`recent -n 3` would return `1.8.0-rc2 1.7.1 1.6.2` +""" +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import itertools +import operator +import sys +from collections import namedtuple + +import requests + + +GITHUB_API = 'https://api.github.com/repos' + + +class Version(namedtuple('_Version', 'major minor patch rc edition')): + + @classmethod + def parse(cls, version): + edition = None + version = version.lstrip('v') + version, _, rc = version.partition('-') + if rc: + if 'rc' not in rc: + edition = rc + rc = None + elif '-' in rc: + edition, rc = rc.split('-') + + major, minor, patch = version.split('.', 3) + return cls(major, minor, patch, rc, edition) + + @property + def major_minor(self): + return self.major, self.minor + + @property + def order(self): + """Return a representation that allows this object to be sorted + correctly with the default comparator. + """ + # rc releases should appear before official releases + rc = (0, self.rc) if self.rc else (1, ) + return (int(self.major), int(self.minor), int(self.patch)) + rc + + def __str__(self): + rc = '-{}'.format(self.rc) if self.rc else '' + edition = '-{}'.format(self.edition) if self.edition else '' + return '.'.join(map(str, self[:3])) + edition + rc + + +def group_versions(versions): + """Group versions by `major.minor` releases. + + Example: + + >>> group_versions([ + Version(1, 0, 0), + Version(2, 0, 0, 'rc1'), + Version(2, 0, 0), + Version(2, 1, 0), + ]) + + [ + [Version(1, 0, 0)], + [Version(2, 0, 0), Version(2, 0, 0, 'rc1')], + [Version(2, 1, 0)], + ] + """ + return list( + list(releases) + for _, releases + in itertools.groupby(versions, operator.attrgetter('major_minor')) + ) + + +def get_latest_versions(versions, num=1): + """Return a list of the most recent versions for each major.minor version + group. + """ + versions = group_versions(versions) + num = min(len(versions), num) + return [versions[index][0] for index in range(num)] + + +def get_default(versions): + """Return a :class:`Version` for the latest non-rc version.""" + for version in versions: + if not version.rc: + return version + + +def get_versions(tags): + for tag in tags: + try: + yield Version.parse(tag['name']) + except ValueError: + print("Skipping invalid tag: {name}".format(**tag), file=sys.stderr) + + +def get_github_releases(projects): + """Query the Github API for a list of version tags and return them in + sorted order. + + See https://developer.github.com/v3/repos/#list-tags + """ + versions = [] + for project in projects: + url = '{}/{}/tags'.format(GITHUB_API, project) + response = requests.get(url) + response.raise_for_status() + versions.extend(get_versions(response.json())) + return sorted(versions, reverse=True, key=operator.attrgetter('order')) + + +def parse_args(argv): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('project', help="Github project name (ex: docker/docker)") + parser.add_argument('command', choices=['recent', 'default']) + parser.add_argument('-n', '--num', type=int, default=2, + help="Number of versions to return from `recent`") + return parser.parse_args(argv) + + +def main(argv=None): + args = parse_args(argv) + versions = get_github_releases(args.project.split(',')) + + if args.command == 'recent': + print(' '.join(map(str, get_latest_versions(versions, args.num)))) + elif args.command == 'default': + print(get_default(versions)) + else: + raise ValueError("Unknown command {}".format(args.command)) + + +if __name__ == "__main__": + main() diff --git a/script/travis/bintray.json.tmpl b/script/travis/bintray.json.tmpl new file mode 100644 index 00000000..f9728558 --- /dev/null +++ b/script/travis/bintray.json.tmpl @@ -0,0 +1,29 @@ +{ + "package": { + "name": "${TRAVIS_OS_NAME}", + "repo": "${TRAVIS_BRANCH}", + "subject": "docker-compose", + "desc": "Automated build of master branch from travis ci.", + "website_url": "https://github.com/docker/compose", + "issue_tracker_url": "https://github.com/docker/compose/issues", + "vcs_url": "https://github.com/docker/compose.git", + "licenses": ["Apache-2.0"] + }, + + "version": { + "name": "${TRAVIS_BRANCH}", + "desc": "Automated build of the ${TRAVIS_BRANCH} branch.", + "released": "${DATE}", + "vcs_tag": "master" + }, + + "files": [ + { + "includePattern": "dist/(.*)", + "excludePattern": ".*\.tar.gz", + "uploadPattern": "$1", + "matrixParams": { "override": 1 } + } + ], + "publish": true +} diff --git a/script/travis/build-binary b/script/travis/build-binary new file mode 100755 index 00000000..7707a1ee --- /dev/null +++ b/script/travis/build-binary @@ -0,0 +1,13 @@ +#!/bin/bash + +set -ex + +if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + script/build/linux + # TODO: requires auth to push, so disable for now + # script/build/image master + # docker push docker/compose:master +else + script/setup/osx + script/build/osx +fi diff --git a/script/travis/ci b/script/travis/ci new file mode 100755 index 00000000..cd4fcc6d --- /dev/null +++ b/script/travis/ci @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + tox -e py27,py34 -- tests/unit +else + # TODO: we could also install py34 and test against it + tox -e py27 -- tests/unit +fi diff --git a/script/travis/install b/script/travis/install new file mode 100755 index 00000000..d4b34786 --- /dev/null +++ b/script/travis/install @@ -0,0 +1,10 @@ +#!/bin/bash + +set -ex + +if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + pip install tox==2.1.1 +else + sudo pip install --upgrade pip tox==2.1.1 virtualenv + pip --version +fi diff --git a/script/travis/render-bintray-config.py b/script/travis/render-bintray-config.py new file mode 100755 index 00000000..b5364a0b --- /dev/null +++ b/script/travis/render-bintray-config.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import datetime +import os.path +import sys + +os.environ['DATE'] = str(datetime.date.today()) + +for line in sys.stdin: + print(os.path.expandvars(line), end='') |