diff --git a/README.md b/README.md index f939336b..4b5054ea 100644 --- a/README.md +++ b/README.md @@ -468,7 +468,9 @@ Completely avoid running any `pull` command. Images being used will need to be p ### `workdir` (optional, run only) -Specify the container working directory via `docker-compose run --workdir`. +Specify the container working directory via `docker-compose run --workdir`. This option is also used by [`mount-checkout`](#mount-checkout-optional-run-only-boolean) to determine where to mount the checkout in the container. + +Example: `/app` ### `user` (optional, run only) @@ -492,6 +494,12 @@ Whether to automatically mount the `buildkite-agent` binary and associated envir Default: `false` +### `mount-checkout` (optional, run-only, boolean) + +Whether to automatically mount the current working directory which contains your checked out codebase. Mounts onto `/workdir`, unless `workdir` is set, in which case that will be used. + +Default: `false` + ### `pull-retries` (optional) A number of times to retry failed docker pull. Defaults to 0. diff --git a/commands/run.sh b/commands/run.sh index b78f01a1..5784ed47 100755 --- a/commands/run.sh +++ b/commands/run.sh @@ -9,6 +9,7 @@ container_name="$(docker_compose_project_name)_${run_service}_build_${BUILDKITE_ override_file="docker-compose.buildkite-${BUILDKITE_BUILD_NUMBER}-override.yml" pull_retries="$(plugin_read_config PULL_RETRIES "0")" mount_ssh_agent='' +mount_checkout="$(plugin_read_config MOUNT_CHECKOUT "false")" expand_headers_on_error() { echo "^^^ +++" @@ -115,10 +116,16 @@ if [[ -n "${BUILDKITE_REPO_MIRROR:-}" ]]; then fi tty_default='true' +workdir_default="/workdir" +pwd_default="$PWD" # Set operating system specific defaults if is_windows ; then tty_default='false' + workdir_default="C:\\workdir" + # escaping /C is a necessary workaround for an issue with Git for Windows 2.24.1.2 + # https://github.com/git-for-windows/git/issues/2442 + pwd_default="$(cmd.exe //C "echo %CD%")" fi # Optionally disable allocating a TTY @@ -131,8 +138,19 @@ if [[ "$(plugin_read_config DEPENDENCIES "true")" == "false" ]] ; then run_params+=(--no-deps) fi -if [[ -n "$(plugin_read_config WORKDIR)" ]] ; then - run_params+=("--workdir=$(plugin_read_config WORKDIR)") +workdir='' + +if [[ -n "$(plugin_read_config WORKDIR)" ]] || [[ "${mount_checkout}" == "true" ]]; then + workdir="$(plugin_read_config WORKDIR "$workdir_default")" +fi + +if [[ -n "${workdir}" ]] ; then + run_params+=("--workdir=${workdir}") +fi + +# By default, mount $PWD onto $WORKDIR +if [[ "${mount_checkout}" == "true" ]] ; then + run_params+=("-v" "${pwd_default}:${workdir}") fi # Can't set both user and propagate-uid-gid diff --git a/plugin.yml b/plugin.yml index c2136ecb..b511865f 100644 --- a/plugin.yml +++ b/plugin.yml @@ -59,6 +59,8 @@ configuration: type: boolean mount-ssh-agent: type: boolean + mount-checkout: + type: boolean no-cache: type: boolean propagate-environment: @@ -115,6 +117,7 @@ configuration: image-name: [ build ] leave-volumes: [ run ] mount-buildkite-agent: [ run ] + mount-checkout: [ run ] propagate-uid-gid: [ run ] pull: [ run ] push-retries: [ push ] diff --git a/tests/run.bats b/tests/run.bats index 2b4ef823..3f8e2e53 100644 --- a/tests/run.bats +++ b/tests/run.bats @@ -1159,3 +1159,85 @@ export BUILDKITE_JOB_ID=1111 unstub docker-compose unstub buildkite-agent } + +@test "Run without mount-checkout doesn't set volume" { + export BUILDKITE_JOB_ID=1111 + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_RUN=myservice + export BUILDKITE_PIPELINE_SLUG=test + export BUILDKITE_BUILD_NUMBER=1 + export BUILDKITE_COMMAND=pwd + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CHECK_LINKED_CONTAINERS=false + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CLEANUP=false + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_MOUNT_CHECKOUT=false + + stub docker-compose \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml pull myservice : echo pulled myservice" \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml up -d --scale myservice=0 myservice : echo started dependencies for myservice" \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml run --name buildkite1111_myservice_build_1 --rm myservice /bin/sh -e -c 'pwd' : echo ran myservice without mount-checkout" + + stub buildkite-agent \ + "meta-data exists docker-compose-plugin-built-image-tag-myservice : exit 0" \ + "meta-data get docker-compose-plugin-built-image-tag-myservice : echo myimage" + + run "$PWD"/hooks/command + + assert_success + assert_output --partial "ran myservice without mount-checkout" + unstub docker-compose + unstub buildkite-agent +} + +@test "Run with mount-checkout set with default workdir" { + export BUILDKITE_JOB_ID=1111 + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_RUN=myservice + export BUILDKITE_PIPELINE_SLUG=test + export BUILDKITE_BUILD_NUMBER=1 + export BUILDKITE_COMMAND=pwd + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CHECK_LINKED_CONTAINERS=false + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CLEANUP=false + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_MOUNT_CHECKOUT=true + + stub docker-compose \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml pull myservice : echo pulled myservice" \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml up -d --scale myservice=0 myservice : echo started dependencies for myservice" \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml run --name buildkite1111_myservice_build_1 --workdir=/workdir -v $PWD:/workdir --rm myservice /bin/sh -e -c 'pwd' : echo ran myservice with mount-checkout" + + stub buildkite-agent \ + "meta-data exists docker-compose-plugin-built-image-tag-myservice : exit 0" \ + "meta-data get docker-compose-plugin-built-image-tag-myservice : echo myimage" + + run "$PWD"/hooks/command + + assert_success + assert_output --partial "ran myservice with mount-checkout" + unstub docker-compose + unstub buildkite-agent +} + +@test "Run with mount-checkout set with custom workdir" { + export BUILDKITE_JOB_ID=1111 + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_RUN=myservice + export BUILDKITE_PIPELINE_SLUG=test + export BUILDKITE_BUILD_NUMBER=1 + export BUILDKITE_COMMAND=pwd + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CHECK_LINKED_CONTAINERS=false + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_CLEANUP=false + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_MOUNT_CHECKOUT=true + export BUILDKITE_PLUGIN_DOCKER_COMPOSE_WORKDIR="/custom_workdir" + + stub docker-compose \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml pull myservice : echo pulled myservice" \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml up -d --scale myservice=0 myservice : echo started dependencies for myservice" \ + "-f docker-compose.yml -p buildkite1111 -f docker-compose.buildkite-1-override.yml run --name buildkite1111_myservice_build_1 --workdir=$BUILDKITE_PLUGIN_DOCKER_COMPOSE_WORKDIR -v $PWD:$BUILDKITE_PLUGIN_DOCKER_COMPOSE_WORKDIR --rm myservice /bin/sh -e -c 'pwd' : echo ran myservice with mount-checkout" + + stub buildkite-agent \ + "meta-data exists docker-compose-plugin-built-image-tag-myservice : exit 0" \ + "meta-data get docker-compose-plugin-built-image-tag-myservice : echo myimage" + + run "$PWD"/hooks/command + + assert_success + assert_output --partial "ran myservice with mount-checkout" + unstub docker-compose + unstub buildkite-agent +}