diff --git a/.github/workflows/publish_canary_docker.yml b/.github/workflows/publish_canary_docker.yml index ef19c9b3..963daae8 100644 --- a/.github/workflows/publish_canary_docker.yml +++ b/.github/workflows/publish_canary_docker.yml @@ -17,10 +17,9 @@ jobs: username: playwright password: ${{ secrets.DOCKER_PASSWORD }} - uses: actions/checkout@v2 - - name: Build Docker image - run: docker build -t playwright-java:localbuild-focal -f Dockerfile.focal . - - name: tag & publish - run: | - ./scripts/tag_image_and_push.sh playwright-java:localbuild-focal playwright.azurecr.io/public/playwright/java:next - ./scripts/tag_image_and_push.sh playwright-java:localbuild-focal playwright.azurecr.io/public/playwright/java:next-focal - ./scripts/tag_image_and_push.sh playwright-java:localbuild-focal playwright.azurecr.io/public/playwright/java:sha-${{ github.sha }} + - name: Set up Docker QEMU for arm64 docker builds + uses: docker/setup-qemu-action@v1 + with: + platforms: arm64 + - name: publish docker canary + run: ./utils/docker/publish_docker.sh canary diff --git a/.github/workflows/publish_docker_release.yml b/.github/workflows/publish_docker_release.yml index 6a86ffff..4ae104bf 100644 --- a/.github/workflows/publish_docker_release.yml +++ b/.github/workflows/publish_docker_release.yml @@ -17,20 +17,12 @@ jobs: login-server: playwright.azurecr.io username: playwright password: ${{ secrets.DOCKER_PASSWORD }} + - name: Set up Docker QEMU for arm64 docker builds + uses: docker/setup-qemu-action@v1 + with: + platforms: arm64 - uses: actions/checkout@v2 - - name: Build Docker image - run: docker build -t playwright-java:localbuild-focal -f Dockerfile.focal . - - name: tag & publish - run: | - # GITHUB_REF has a form of `refs/tags/v1.3.0`. - # TAG_NAME would be `v1.3.0` - TAG_NAME=${GITHUB_REF#refs/tags/} - if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; - then - echo "Wrong TAG_NAME format: $TAG_NAME" - exit 1 - fi - ./scripts/tag_image_and_push.sh playwright-java:localbuild-focal playwright.azurecr.io/public/playwright/java:latest - ./scripts/tag_image_and_push.sh playwright-java:localbuild-focal playwright.azurecr.io/public/playwright/java:focal - ./scripts/tag_image_and_push.sh playwright-java:localbuild-focal playwright.azurecr.io/public/playwright/java:${TAG_NAME} - ./scripts/tag_image_and_push.sh playwright-java:localbuild-focal playwright.azurecr.io/public/playwright/java:${TAG_NAME}-focal + - run: ./utils/docker/publish_docker.sh stable + if: (github.event_name != 'workflow_dispatch' && !github.event.release.prerelease) || (github.event_name == 'workflow_dispatch' && github.event.inputs.is_release == 'true') + - run: ./utils/docker/publish_docker.sh canary + if: (github.event_name != 'workflow_dispatch' && github.event.release.prerelease) || (github.event_name == 'workflow_dispatch' && github.event.inputs.is_release != 'true') diff --git a/.github/workflows/test_docker.yml b/.github/workflows/test_docker.yml index c683017d..6a136d6a 100644 --- a/.github/workflows/test_docker.yml +++ b/.github/workflows/test_docker.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Build Docker image - run: docker build -t playwright-java:localbuild-focal -f Dockerfile.focal . + run: bash utils/docker/build.sh --amd64 focal playwright-java:localbuild-focal - name: Test run: | CONTAINER_ID="$(docker run --rm --ipc=host -v $(pwd):/root/playwright --name playwright-docker-test -d -t playwright-java:localbuild-focal /bin/bash)" diff --git a/scripts/tag_image_and_push.sh b/scripts/tag_image_and_push.sh deleted file mode 100755 index 9c5b09d2..00000000 --- a/scripts/tag_image_and_push.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -echo "-- tagging: $2" -docker tag $1 $2 -docker push $2 diff --git a/Dockerfile.focal b/utils/docker/Dockerfile.focal similarity index 64% rename from Dockerfile.focal rename to utils/docker/Dockerfile.focal index 396086a6..4f55b625 100644 --- a/Dockerfile.focal +++ b/utils/docker/Dockerfile.focal @@ -2,26 +2,32 @@ FROM ubuntu:focal # === INSTALL JDK and Maven === -RUN apt-get update && apt-get install -y --no-install-recommends \ - openjdk-11-jdk maven +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + openjdk-11-jdk maven \ + # Install utilities required for downloading browsers + curl \ + # Install utilities required for downloading driver + unzip && \ + rm -rf /var/lib/apt/lists/* && \ + # Create the pwuser + adduser pwuser ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 -# Install utilities required for downloading driver -RUN apt-get update && apt-get install -y --no-install-recommends \ - curl unzip - -# === INSTALL playwright maven modules & browsers === +# === BAKE BROWSERS INTO IMAGE === # Browsers will remain downloaded in `/ms-playwright`. # Note: make sure to set 777 to the registry so that any user can access # registry. ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright -RUN mkdir /ms-playwright && chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH +RUN mkdir /ms-playwright && \ + chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH && \ + mkdir /tmp/pw-java -RUN mkdir /tmp/pw-java COPY . /tmp/pw-java + RUN cd /tmp/pw-java && \ ./scripts/download_driver_for_all_platforms.sh && \ mvn install -D skipTests --no-transfer-progress && \ diff --git a/utils/docker/README.md b/utils/docker/README.md new file mode 100644 index 00000000..1523b730 --- /dev/null +++ b/utils/docker/README.md @@ -0,0 +1,4 @@ +# Docker build infra + +This folder contains the infra to build the Docker images for Java. It's based on +the upstream code located in [`microsoft/playwright/utils/docker`](https://github.com/microsoft/playwright/tree/main/utils/docker). diff --git a/utils/docker/build.sh b/utils/docker/build.sh new file mode 100755 index 00000000..474a1152 --- /dev/null +++ b/utils/docker/build.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e +set +x + +if [[ ($1 == '--help') || ($1 == '-h') || ($1 == '') || ($2 == '') ]]; then + echo "usage: $(basename $0) {--arm64,--amd64} {focal} playwright:localbuild-focal" + echo + echo "Build Playwright docker image and tag it as 'playwright:localbuild-focal'." + echo "Once image is built, you can run it with" + echo "" + echo " docker run --rm -it playwright:localbuild-focal /bin/bash" + echo "" + echo "NOTE: this requires on Playwright PIP dependencies to be installed" + echo "" + exit 0 +fi + +function cleanup() { + : +} + +trap "cleanup; cd $(pwd -P)" EXIT +cd "$(dirname "$0")" + +PLATFORM="" +if [[ "$1" == "--arm64" ]]; then + PLATFORM="linux/arm64"; +elif [[ "$1" == "--amd64" ]]; then + PLATFORM="linux/amd64" +else + echo "ERROR: unknown platform specifier - $1. Only --arm64 or --amd64 is supported" + exit 1 +fi + +docker build --platform "${PLATFORM}" -t "$3" -f "Dockerfile.$2" ../../ diff --git a/utils/docker/publish_docker.sh b/utils/docker/publish_docker.sh new file mode 100755 index 00000000..35a68a1e --- /dev/null +++ b/utils/docker/publish_docker.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +set -e +set +x + +trap "cd $(pwd -P)" EXIT +cd "$(dirname "$0")" + +MCR_IMAGE_NAME="playwright/java" +# GITHUB_REF has a form of `refs/tags/v1.3.0`. +# TAG_NAME would be `v1.3.0` +TAG_NAME=${GITHUB_REF#refs/tags/} +PW_VERSION="${TAG_NAME#v}" + +RELEASE_CHANNEL="$1" +if [[ "${RELEASE_CHANNEL}" == "stable" ]]; then + if [[ ! "${PW_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; + echo "ERROR: cannot publish stable docker with Playwright version '${PW_VERSION}'" + exit 1 + fi +elif [[ "${RELEASE_CHANNEL}" == "canary" ]]; then + +else + echo "ERROR: unknown release channel - ${RELEASE_CHANNEL}" + echo "Must be either 'stable' or 'canary'" + exit 1 +fi + +if [[ -z "${GITHUB_SHA}" ]]; then + echo "ERROR: GITHUB_SHA env variable must be specified" + exit 1 +fi + +BIONIC_TAGS=( + "next-bionic" + "v${PW_VERSION}-bionic" +) +if [[ "$RELEASE_CHANNEL" == "stable" ]]; then + BIONIC_TAGS+=("bionic") +fi + +FOCAL_TAGS=( + "next" + "sha-${GITHUB_SHA}" + "next-focal" +) + +if [[ "$RELEASE_CHANNEL" == "stable" ]]; then + FOCAL_TAGS+=("latest") + FOCAL_TAGS+=("focal") + FOCAL_TAGS+=("v${PW_VERSION}-focal") + FOCAL_TAGS+=("v${PW_VERSION}") +fi + +tag_and_push() { + local source="$1" + local target="$2" + echo "-- tagging: $target" + docker tag $source $target + docker push $target +} + +publish_docker_images_with_arch_suffix() { + local FLAVOR="$1" + local TAGS=() + if [[ "$FLAVOR" == "bionic" ]]; then + TAGS=("${BIONIC_TAGS[@]}") + elif [[ "$FLAVOR" == "focal" ]]; then + TAGS=("${FOCAL_TAGS[@]}") + else + echo "ERROR: unknown flavor - $FLAVOR. Must be either 'bionic' or 'focal'" + exit 1 + fi + local ARCH="$2" + if [[ "$ARCH" != "amd64" && "$ARCH" != "arm64" ]]; then + echo "ERROR: unknown arch - $ARCH. Must be either 'amd64' or 'arm64'" + exit 1 + fi + # Prune docker images to avoid platform conflicts + docker system prune -fa + ./build.sh "--${ARCH}" "${FLAVOR}" "${MCR_IMAGE_NAME}:localbuild" + + for ((i = 0; i < ${#TAGS[@]}; i++)) do + local TAG="${TAGS[$i]}" + tag_and_push "${MCR_IMAGE_NAME}:localbuild" "playwright.azurecr.io/public/${MCR_IMAGE_NAME}:${TAG}-${ARCH}" + done +} + +publish_docker_manifest () { + local FLAVOR="$1" + local TAGS=() + if [[ "$FLAVOR" == "bionic" ]]; then + TAGS=("${BIONIC_TAGS[@]}") + elif [[ "$FLAVOR" == "focal" ]]; then + TAGS=("${FOCAL_TAGS[@]}") + else + echo "ERROR: unknown flavor - $FLAVOR. Must be either 'bionic' or 'focal'" + exit 1 + fi + + for ((i = 0; i < ${#TAGS[@]}; i++)) do + local TAG="${TAGS[$i]}" + local BASE_IMAGE_TAG="playwright.azurecr.io/public/${MCR_IMAGE_NAME}:${TAG}" + local IMAGE_NAMES="" + if [[ "$2" == "arm64" || "$2" == "amd64" ]]; then + IMAGE_NAMES="${IMAGE_NAMES} ${BASE_IMAGE_TAG}-$2" + fi + if [[ "$3" == "arm64" || "$3" == "amd64" ]]; then + IMAGE_NAMES="${IMAGE_NAMES} ${BASE_IMAGE_TAG}-$3" + fi + docker manifest create "${BASE_IMAGE_TAG}" $IMAGE_NAMES + docker manifest push "${BASE_IMAGE_TAG}" + done +} + +publish_docker_images_with_arch_suffix focal amd64 +publish_docker_images_with_arch_suffix focal arm64 +publish_docker_manifest focal amd64 arm64