diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 62173334..66daa8f4 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -8,7 +8,7 @@ on: jobs: audit: - name: 💥 cross-audit + name: 👮 cross-audit strategy: fail-fast: false matrix: @@ -23,19 +23,4 @@ jobs: if: ${{ matrix.DOCKER_TARGET_PLATFORM }} == 'linux/arm' || 'linux/arm64' run: ./script/release-workflow/docker-prepare.sh - name: Audit Docker image for ${{ matrix.DOCKER_TARGET_PLATFORM }} - run: ./script/release-workflow/audit.sh - # # We could also run via a trivy action and publish results back to GitHub :) - # - name: Run Trivy vulnerability scanner for ${{ matrix.DOCKER_TARGET_PLATFORM }} - # uses: aquasecurity/trivy-action@master - # with: - # image-ref: 'pactfoundation/pact-broker:audit' - # exit-code: '1' - # format: 'sarif' - # output: 'trivy-results.sarif' - # ignore-unfixed: true - # vuln-type: 'os,library' - # severity: 'CRITICAL,HIGH' - # - name: Upload Trivy scan results to GitHub Security tab - # uses: github/codeql-action/upload-sarif@v2 - # with: - # sarif_file: 'trivy-results.sarif' + run: ./script/release-workflow/audit.sh \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d1d4d8e4..d4764b0f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,8 +1,6 @@ name: Test on: [push, pull_request] -env: - DOCKER_TARGET_PLATFORM: "linux/amd64" jobs: test: @@ -13,8 +11,19 @@ jobs: - run: "bundle install" - run: "bundle exec rake" - - name: Build Docker image - run: docker buildx build --platform=${DOCKER_TARGET_PLATFORM} -t pactfoundation/pact-broker:latest . + - name: Setup Docker builder + run: ./script/release-workflow/docker-prepare.sh + + - name: Build Docker image for single platform + run: ./script/release-workflow/docker-build.sh + + - uses: KengoTODA/actions-setup-docker-compose@v1 + if: ${{ env.ACT }} + name: Install `docker-compose` for use with https://github.com/nektos/act + with: + version: '2.15.1' - name: Integration tests run: script/test.sh + env: + TAG: latest-amd64 diff --git a/Dockerfile b/Dockerfile index af45f4be..cdd3dab5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,26 @@ -FROM ruby:3.2.1-alpine3.17 +FROM ruby:3.2.1-alpine3.17 as base -ARG SUPERCRONIC_PLATFORM=amd64 -ARG SUPERCRONIC_SHA1SUM=6817299e04457e5d6ec4809c72ee13a43e95ba41 +# 1. Install target specfic dependencies +# - gcompat required for arm/arm64 (otherwise nokogiri breaks when viewing network graph) +# - https://github.com/sparklemotion/nokogiri/issues/2414 +# 2. Supercronic - setup sha1sum for each supported architecture +FROM base AS base-amd64 +ENV SUPERCRONIC_SHA1SUM=6817299e04457e5d6ec4809c72ee13a43e95ba41 +FROM base AS base-arm64 +ENV SUPERCRONIC_SHA1SUM=fce407a3d7d144120e97cfc0420f16a18f4637d9 +RUN apk add --update --no-cache gcompat +FROM base AS base-arm +ENV SUPERCRONIC_SHA1SUM=fad9380ed30b9eae61a5b1089f93bd7ee8eb1a9c +RUN apk add --update --no-cache gcompat -ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.2.24/supercronic-linux-${SUPERCRONIC_PLATFORM} \ - SUPERCRONIC=supercronic-linux-${SUPERCRONIC_PLATFORM} +# Supercronic - use base-$TARGETARCH to select correct base image SUPERCRONIC_SHA1SUM +ARG TARGETARCH +FROM base-$TARGETARCH AS pb-dev +# Install Supercronic +ARG TARGETARCH +ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.2.24/supercronic-linux-${TARGETARCH} \ + SUPERCRONIC=supercronic-linux-${TARGETARCH} RUN wget "$SUPERCRONIC_URL" \ && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ && chmod +x "$SUPERCRONIC" \ @@ -59,4 +74,4 @@ ENV PACT_BROKER_DATABASE_CLEAN_OVERWRITTEN_DATA_MAX_AGE=7 ENV PACT_BROKER_DATABASE_CLEAN_DRY_RUN=false USER ruby ENTRYPOINT ["sh", "./entrypoint.sh"] -CMD ["config.ru"] +CMD ["config.ru"] \ No newline at end of file diff --git a/README.md b/README.md index 644ade57..cb486a09 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,26 @@ # Dockerised Pact Broker -[![Release Docker image](https://github.com/pact-foundation/pact-broker-docker/actions/workflows/release_image.yml/badge.svg)](https://github.com/pact-foundation/pact-broker-docker/actions/workflows/release_image.yml) - This repository contains a Dockerized version of the [Pact Broker][pact-broker]. You can pull the `pactfoundation/pact-broker` image from [Dockerhub][pact-broker-docker]. If you're viewing these docs on Dockerhub, here is a link to the [github repository][github]. > Note: On 3 May 2023, the format of the docker tag changed from starting with the Pact Broker gem version (`2.107.0.1`), to ending with the Pact Broker gem version (`2.107.1-pactbroker2.107.1`). Read about the new versioning scheme [here](#versioning). +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/pact-foundation/pact-msw-adapter/graphs/commit-activity) + +[![Linux](https://svgshare.com/i/Zhy.svg)](https://svgshare.com/i/Zhy.svg) +[![macOS](https://svgshare.com/i/ZjP.svg)](https://svgshare.com/i/ZjP.svg) +[![Windows](https://svgshare.com/i/ZhY.svg)](https://svgshare.com/i/ZhY.svg) + +[![Build and test](https://github.com/pact-foundation/pact-broker-docker/actions/workflows/test.yml/badge.svg)](https://github.com/pact-foundation/pact-broker-docker/actions/workflows/test.yml) +[![Audit](https://github.com/pact-foundation/pact-broker-docker/actions/workflows/audit.yml/badge.svg)](https://github.com/pact-foundation/pact-broker-docker/actions/workflows/audit.yml) +[![Release](https://github.com/pact-foundation/pact-broker-docker/actions/workflows/release_image.yml/badge.svg)](https://github.com/pact-foundation/pact-broker-docker/actions/workflows/release_image.yml) + +[![pulls](https://badgen.net/docker/pulls/pactfoundation/pact-broker?icon=docker&label=pulls)](https://hub.docker.com/r/pactfoundation/pact-broker) +[![stars](https://badgen.net/docker/stars/pactfoundation/pact-broker?icon=docker&label=stars)](https://hub.docker.com/r/pactfoundation/pact-broker) + +[![size: amd64](https://badgen.net/docker/size/pactfoundation/pact-broker/latest-multi/amd64?icon=docker&label=size%3Aamd64)](https://hub.docker.com/r/pactfoundation/pact-broker) +[![size: arm64](https://badgen.net/docker/size/pactfoundation/pact-broker/latest-multi/arm64?icon=docker&label=size%3Aarm64)](https://hub.docker.com/r/pactfoundation/pact-broker) +[![size: arm](https://badgen.net/docker/size/pactfoundation/pact-broker/latest-multi/arm?icon=docker&label=size%3Aarm)](https://hub.docker.com/r/pactfoundation/pact-broker) + ## In a hurry? If you want to try out a Pact Broker that can be accessed by all your teams, without having to fill in requisition forms and wait for 3 months, you can get a free trial at pactflow.io. Built by a group of core Pact maintainers, PactFlow is a fork of the OSS Pact Broker with extra goodies like an improved UI, user and team management, secrets, field level verification results and federated login. It's also fully supported, and that means when something goes wrong, *someone else* gets woken up in the middle of the afternoon to fix it... @@ -22,6 +37,30 @@ Please read https://github.com/phusion/passenger/wiki/Puma-vs-Phusion-Passenger If you want to run the container as a standalone instance, then the `dius/pact-broker` image which uses Phusion Passenger may serve you better, as Passenger will restart any crashed processes. +## Platforms + +### Single platform images + +By default, vanilla tags, are built only for `amd64` + +- `--platform=linux/amd64` + + ```sh + docker run --rm -it --entrypoint /bin/sh pactfoundation/pact-broker:latest -c 'uname -sm' + ``` + +### Multi-manifest image + +Multi-platform images are available, by appending `-multi` to any release tag + +- `--platform=linux/amd64` +- `--platform=linux/arm/v7` +- `--platform=linux/arm64` + + ```sh + docker run --rm -it --entrypoint /bin/sh pactfoundation/pact-broker:latest-multi -c 'uname -sm' + ``` + ## Prerequisites * A running Postgresql database (v9.4 or later) and the ability to connect to it (see [POSTGRESQL.md][postgres]). diff --git a/script/release-workflow/docker-build.sh b/script/release-workflow/docker-build.sh index 302d7a1b..a3daefec 100755 --- a/script/release-workflow/docker-build.sh +++ b/script/release-workflow/docker-build.sh @@ -2,6 +2,14 @@ set -euo >/dev/null -DOCKER_TARGET_PLATFORM=${DOCKER_TARGET_PLATFORM:-"linux/amd64"} - -docker buildx build --platform=${DOCKER_TARGET_PLATFORM} -t ${DOCKER_IMAGE_ORG_AND_NAME}:latest . --load +## This will allow for local use for testing or scanning with trivy (multi-manifest builds cannot be imported) +## we will build a multi-manifest build during ./docker-push.sh +ARCHES=${ARCHES:-'amd64'} +DOCKER_IMAGE_ORG_AND_NAME="${DOCKER_REPOSITORY:-pactfoundation}/pact-broker" +for arch in $ARCHES; do + docker buildx build \ + --platform linux/$arch \ + --output type=docker \ + --tag ${DOCKER_IMAGE_ORG_AND_NAME}:latest-${arch} \ + . +done \ No newline at end of file diff --git a/script/release-workflow/docker-push.sh b/script/release-workflow/docker-push.sh index d0e40803..fb0e31ca 100755 --- a/script/release-workflow/docker-push.sh +++ b/script/release-workflow/docker-push.sh @@ -2,14 +2,29 @@ set -euo >/dev/null +## Publish a multi arch build with -multi added to the tag +## ($TAG||$MAJOR_TAG||$LATEST)-multi +push_multi() { + ## These will use cached builds, so wont build every time. + docker buildx build --platform=linux/amd64,linux/arm64,linux/arm \ + --output=type=image,push=true \ + -t ${DOCKER_IMAGE_ORG_AND_NAME}:$1-multi . +} +push() { + docker buildx build --platform=linux/amd64 \ + --output=type=image,push=true \ + -t ${DOCKER_IMAGE_ORG_AND_NAME}:$1 . +} + if [ -n "${MAJOR_TAG:-}" ]; then - docker tag ${DOCKER_IMAGE_ORG_AND_NAME}:latest ${DOCKER_IMAGE_ORG_AND_NAME}:${MAJOR_TAG} - docker push ${DOCKER_IMAGE_ORG_AND_NAME}:${MAJOR_TAG} + push ${MAJOR_TAG} + push_multi ${MAJOR_TAG} fi -docker tag ${DOCKER_IMAGE_ORG_AND_NAME}:latest ${DOCKER_IMAGE_ORG_AND_NAME}:${TAG} -docker push ${DOCKER_IMAGE_ORG_AND_NAME}:${TAG} +push ${TAG} +push_multi ${TAG} if [ "${PUSH_TO_LATEST}" != "false" ]; then - docker push ${DOCKER_IMAGE_ORG_AND_NAME}:latest -fi + push latest + push_multi latest +fi \ No newline at end of file diff --git a/script/release-workflow/docker-scan.sh b/script/release-workflow/docker-scan.sh index bf3b596c..22f643d8 100755 --- a/script/release-workflow/docker-scan.sh +++ b/script/release-workflow/docker-scan.sh @@ -4,4 +4,5 @@ set -euo >/dev/null script_dir=$(cd "$(dirname $0)" && pwd) -${script_dir}/../scan.sh ${DOCKER_IMAGE_ORG_AND_NAME}:latest +ARCH=${ARCH:-'amd64'} +${script_dir}/../scan.sh ${DOCKER_IMAGE_ORG_AND_NAME}:latest-${ARCH} diff --git a/script/release-workflow/run.sh b/script/release-workflow/run.sh index 544c754b..e8b10405 100755 --- a/script/release-workflow/run.sh +++ b/script/release-workflow/run.sh @@ -12,6 +12,7 @@ fi . ${workflow_dir}/set-env-vars.sh ${workflow_dir}/validate.sh +${workflow_dir}/docker-prepare.sh ${workflow_dir}/docker-build.sh ${workflow_dir}/docker-scan.sh ${workflow_dir}/prepare-release.sh diff --git a/script/release-workflow/set-env-vars.sh b/script/release-workflow/set-env-vars.sh index 890adb9a..7b4a29df 100755 --- a/script/release-workflow/set-env-vars.sh +++ b/script/release-workflow/set-env-vars.sh @@ -7,6 +7,13 @@ set -e export DOCKER_IMAGE_ORG_AND_NAME="${DOCKER_REPOSITORY:-pactfoundation}/pact-broker" +if [ -n "${DOCKER_TARGET_PLATFORM:-}" ]; then + export ARCH=$(echo "$DOCKER_TARGET_PLATFORM" | sed 's/linux\///' | sed 's/\/v.*//') + export ARCHES=$ARCH +else + export ARCHES='amd64 arm64 arm' + export ARCH=amd64 +fi if [ -z "$TAG" ]; then if [ -n "$VERSION" ] && [ -z "$INCREMENT" ]; then @@ -31,4 +38,4 @@ if [ -z "$TAG" ]; then echo "MAJOR_TAG=$MAJOR_TAG" else echo "TAG=$TAG" -fi +fi \ No newline at end of file diff --git a/script/scan.sh b/script/scan.sh index 3a5cf6da..c6850292 100755 --- a/script/scan.sh +++ b/script/scan.sh @@ -7,6 +7,7 @@ set -eu SCRIPT_DIR=$(cd "$(dirname $0)" && pwd) docker run --rm \ + --platform=linux/${ARCH} \ -v ${SCRIPT_DIR}/.trivyignore:/pact_broker/.trivyignore \ -v ${PWD}/script/scan-inside-docker-container.sh:/pact_broker/scan-inside-docker-container.sh \ -u root \ diff --git a/script/test.sh b/script/test.sh index 5b0c97f2..ab8db3f4 100755 --- a/script/test.sh +++ b/script/test.sh @@ -2,6 +2,13 @@ set -e +docker_compose_files=$(find . -name "docker-compose-test*.yml") + +for file in $docker_compose_files; do + cat $file | sed -e "s~image: pactfoundation/pact-broker:.*~image: pactfoundation/pact-broker:${TAG}~g" > dc-tmp + mv dc-tmp $file +done + cleanup() { docker-compose -f docker-compose-tests.yml rm -fv || true docker-compose -f docker-compose-test-different-env-var-names.yml rm -fv || true diff --git a/test/Dockerfile b/test/Dockerfile index fcb81d11..105720f0 100644 --- a/test/Dockerfile +++ b/test/Dockerfile @@ -1,11 +1,6 @@ -FROM bash:5.0.17 +FROM powerman/dockerize -RUN apk add --no-cache openssl curl +RUN apk add --no-cache openssl curl bash -ENV DOCKERIZE_VERSION v0.6.1 -RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ - && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ - && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz - -Add test.sh /home/test.sh +ADD test.sh /home/test.sh ADD foo-bar.json /home/foo-bar.json \ No newline at end of file