diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2283396..954aeae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,11 +5,11 @@ on: branches: - main schedule: - - cron: "0 5 * * *" + - cron: "0 1 * * 1" jobs: build: - name: Build Container + name: Build and Push Container runs-on: ubuntu-latest strategy: matrix: @@ -21,9 +21,6 @@ jobs: - name: Docker info run: docker info - - - name: Docker Builder - run: docker buildx ls - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -33,9 +30,24 @@ jobs: with: platforms: linux/amd64,linux/arm64 - - name: "ddev ${{ matrix.version }}" + name: Setup BATS + uses: mig4/setup-bats@v1 + with: + bats-version: 1.11.0 + - + name: Check out code + uses: actions/checkout@v1 + - + name: "Test ddev ${{ matrix.version }} image" + shell: 'script -q -e -c "bash {0}"' + run: | + sudo snap install yq + ./build.sh -v ${{ matrix.version }} -l + DDEV_VERSION=${{ matrix.version }} bash bats tests + - + name: "Build ddev ${{ matrix.version }} multi-arch image" shell: 'script -q -e -c "bash {0}"' run: | echo ${{ secrets.GHCR_TOKEN }} | docker login ghcr.io -u ${{ secrets.GHCR_USERNAME }} --password-stdin docker buildx create --use --platform=linux/arm64,linux/amd64 - ./build.sh -v ${{ matrix.version }} -p + ./build.sh -v ${{ matrix.version }} -x -p diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..211204c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,45 @@ +name: Test + +on: + pull_request: + push: + branches: + - '**' + - '!main' +jobs: + build: + name: Build and Test Container + runs-on: ubuntu-latest + strategy: + matrix: + version: [ v1.23, v1.22 ] + steps: + - + name: Checkout code + uses: actions/checkout@v3 + - + name: Docker info + run: docker info + - + name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + platforms: linux/amd64,linux/arm64 + - + name: Setup BATS + uses: mig4/setup-bats@v1 + with: + bats-version: 1.11.0 + - + name: Check out code + uses: actions/checkout@v1 + - + name: "Test ddev ${{ matrix.version }} image" + shell: 'script -q -e -c "bash {0}"' + run: | + sudo snap install yq + ./build.sh -v ${{ matrix.version }} -l + DDEV_VERSION=${{ matrix.version }} bash bats tests diff --git a/README.md b/README.md index 1ed5892..336134b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Available options: * v - DDEV version e.g. 'v1.23.1' * l - Load the image (--load) * p - Push the image (--push) + * x - Build multi-arch image (--platform linux/amd64,linux/arm64) ## Version to tags @@ -27,3 +28,11 @@ Available options: | ./build.sh -v v1.23 | v1.23, v1.23.x (latest bugfix) | | ... | ... | +## Run tests locally + +Requires [bats-core](https://bats-core.readthedocs.io/en/stable/installation.html) and [yq](https://github.com/mikefarah/yq/tree/v4.44.2?tab=readme-ov-file#install). + +``` +DDEV_VERSION=v1.23.3 bash bats tests +``` + diff --git a/build.sh b/build.sh index f6fdf0d..5fba3b1 100755 --- a/build.sh +++ b/build.sh @@ -15,6 +15,7 @@ help() { echo " * v - DDEV version e.g. 'v1.23.1'" echo " * l - Load the image (--load)" echo " * p - Push the image (--push)" + echo " * x - Build multi-arch image (--platform linux/amd64,linux/arm64)" } loadVersionAndTags() { @@ -49,7 +50,7 @@ loadVersionAndTags() { fi } -while getopts ":v:hpl" opt; do +while getopts ":v:hplx" opt; do case $opt in h) help @@ -64,6 +65,9 @@ while getopts ":v:hpl" opt; do l) LOAD="--load" ;; + x) + PLATFORM="--platform linux/amd64,linux/arm64" + ;; *) echo "Invalid option: -$OPTARG" help @@ -74,9 +78,4 @@ done loadVersionAndTags -docker buildx build --platform linux/amd64,linux/arm64 --progress plain --no-cache --pull . -f Dockerfile ${DOCKER_TAGS[@]} --build-arg ddev_version="$DDEV_VERSION" $PUSH $LOAD - -if [ $LOAD ]; then - docker run --rm -it -v "$(pwd)/test.sh:/tmp/test.sh" --entrypoint "ash" "$IMAGE_NAME:$DDEV_VERSION" /tmp/test.sh -fi - +docker buildx build ${PLATFORM} --progress plain --no-cache --pull . -f Dockerfile ${DOCKER_TAGS[@]} --build-arg ddev_version="$DDEV_VERSION" $PUSH $LOAD diff --git a/ddev-install.sh b/ddev-install.sh index e800904..b5c555e 100755 --- a/ddev-install.sh +++ b/ddev-install.sh @@ -1,6 +1,6 @@ #!/usr/bin/ash -apk add --no-cache bash sudo jq +apk add --no-cache bash sudo jq curl adduser -D ddev -g "ddev" -s /bin/bash -D ddev -h /home/ddev echo "ddev ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/ddev && chmod 0440 /etc/sudoers.d/ddev unamearch=$(uname -m) @@ -27,9 +27,38 @@ mkdir ddev tar xfvz "ddev_linux-${ARCH}.${DDEV_VERSION}.tar.gz" --directory ddev mv ddev/ddev /usr/local/bin/ mv ddev/mkcert /usr/local/bin/ +sudo -i ddev /usr/local/bin/mkcert -install rm -Rf ddev "ddev_linux-${ARCH}.${DDEV_VERSION}.tar.gz" # Ensure required folders exist mkdir -p /home/ddev/.ddev/commands/host +echo " +disable_http2: false +fail_on_hook_fail: false +instrumentation_opt_in: false +internet_detection_timeout_ms: 3000 +last_started_version: ${DDEV_VERSION} +letsencrypt_email: "" +mkcert_caroot: /home/ddev/.local/share/mkcert +no_bind_mounts: false +omit_containers: [] +performance_mode: none +project_tld: ddev.site +router: traefik +router_bind_all_interfaces: false +router_http_port: \"80\" +router_https_port: \"443\" +mailpit_http_port: \"8025\" +mailpit_https_port: \"8026\" +simple_formatting: false +table_style: default +traefik_monitor_port: \"10999\" +use_hardened_images: false +use_letsencrypt: false +wsl2_no_windows_hosts_mgt: false +web_environment: [] +xdebug_ide_location: "" +" > /home/ddev/.ddev/global_config.yaml + mkdir /builds -chown -R ddev:ddev /home/ddev/.ddev/ +chown -R ddev:ddev /home/ddev /builds diff --git a/test.sh b/test.sh deleted file mode 100644 index a1d1239..0000000 --- a/test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -docker --version | head -n 1 || exit 1 -docker-compose --version | head -n 1 || exit 1 -ddev --version | head -n 1 || exit 1 -echo "mkcert $(mkcert -version || exit 1)" -echo "Current user: $(whoami)" diff --git a/tests/setup_suite.bash b/tests/setup_suite.bash new file mode 100644 index 0000000..d783a86 --- /dev/null +++ b/tests/setup_suite.bash @@ -0,0 +1,36 @@ +#!/usr/bin/env bats + +setup_suite() { + NETWORK="ddev-docker" + if docker network inspect "$NETWORK" &>/dev/null; then + echo "Network '$NETWORK' already exists." + else + echo "Creating network '$NETWORK'." + docker network create "$NETWORK" + fi + + docker run --privileged -e DOCKER_TLS_CERTDIR="" --name ddev-dind -d --network ddev-docker --network-alias docker docker:dind + waitForDinD +} + +waitForDinD() { + local TEST_COMMAND=" + COUNT=0; + while ! docker info > /dev/null 2>&1; do + if [ \"\${COUNT}\" -ge 30 ]; then + echo \"Could not connect to docker after \$COUNT seconds\" + exit 1 + fi + + sleep 1 + COUNT=\$((COUNT + 1)); + done + " + + docker run --rm --network ddev-docker --name wait-for-docker-dind "docker:latest" /bin/sh -c "${TEST_COMMAND}" +} + +teardown_suite() { + docker stop ddev-dind + docker rm ddev-dind +} diff --git a/tests/test.bats b/tests/test.bats new file mode 100644 index 0000000..bcb98e2 --- /dev/null +++ b/tests/test.bats @@ -0,0 +1,76 @@ +#!/bin/bash + +@test "See docker version" { + run docker-run "docker version -f json" + + version=$(echo "$output" | yq .Client.Version) + regex='^([0-9]+)\.([0-9]+)\.([0-9]+)$' + + [[ $version =~ $regex ]] + [ "$status" -eq 0 ] +} + +@test "See ddev version" { + run docker-run "ddev version -j" + + version=$(echo "$output" | tail -n 1 | yq '.raw.["DDEV version"]') + regex='^v([0-9]+)\.([0-9]+)\.([0-9]+)$' + + [[ $version =~ $regex ]] + [ "$status" -eq 0 ] +} + +@test "See mkcert is installed" { + run docker-run "mkcert -help" + + [[ "$output" == *"Usage of mkcert:"* ]] + [ "$status" -eq 0 ] +} + +@test "Create and run a ddev project" { + local TEST_COMMAND=" + mkdir ~/ddev-test + cd ~/ddev-test + echo ' index.php + ddev config --project-type php --auto + ddev config global --no-bind-mounts=true + ddev start + curl https://ddev-test.ddev.site/index.php + ddev poweroff + " + run docker-run "${TEST_COMMAND}" + + [[ "$output" == *"Configuration complete. You may now run 'ddev start'"* ]] + [[ "$output" == *"Hello World"* ]] + [ "$status" -eq 0 ] +} + +@test "Run ddev debug dockercheck" { + run docker-run "ddev debug dockercheck" + + [[ "$output" == *"Able to run simple container that mounts a volume."* ]] + [[ "$output" == *"Able to use internet inside container."* ]] + [ "$status" -eq 0 ] +} + +# Use "--no-bind-mounts=true" to make "ddev debug test" pass. This is only required in testing environment +@test "Run ddev debug test" { + local TEST_COMMAND=" + mkdir ~/ddev-test + cd ~/ddev-test + ddev config --project-type php --auto + ddev config global --no-bind-mounts=true + ddev debug test + " + run docker-run "${TEST_COMMAND}" + + [[ "$output" == *"All project containers are now ready."* ]] + [[ "$output" == *"Successfully started tryddevproject-"* ]] + [ "$status" -eq 0 ] +} + +docker-run() { + local COMMAND=${1} + + docker run --rm -it --network ddev-docker ghcr.io/ochorocho/ddev-gitlab-ci:"${DDEV_VERSION}" /bin/sh -c "${COMMAND}" +}