diff --git a/.github/workflows/continuous_delivery.yml b/.github/workflows/continuous_delivery.yml index f3ade794..b6b5e70d 100644 --- a/.github/workflows/continuous_delivery.yml +++ b/.github/workflows/continuous_delivery.yml @@ -23,4 +23,4 @@ jobs: - name: Build and push Docker image for release run: | make release GOTENBERG_VERSION=${{ github.event.release.tag_name }} - make release GOTENBERG_VERSION=${{ github.event.release.tag_name }} DOCKER_REPOSITORY=thecodingmachine + make release GOTENBERG_VERSION=${{ github.event.release.tag_name }} DOCKER_REGISTRY=thecodingmachine diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 2f80adf9..809a3568 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -28,7 +28,7 @@ jobs: tests: needs: - - Lint + - lint name: Tests # TODO: once arm64 actions are available, also run the tests on this architecture. # See: https://github.com/actions/virtual-environments/issues/2552#issuecomment-771478000. @@ -50,11 +50,32 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} verbose: true - multiarch_build: + snapshot_release: + if: github.event_name == 'pull_request' + needs: + - tests + name: Snapshot release + runs-on: ubuntu-latest + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Checkout source code + uses: actions/checkout@v4 + - name: Log in to Docker Hub Container Registry + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push snapshot Docker image (linux/amd64) + run: make release GOTENBERG_VERSION=${{ github.head_ref }} DOCKER_REPOSITORY=snapshot LINUX_AMD64_RELEASE=true + + edge_release: if: github.event_name == 'push' && github.ref == 'refs/heads/main' needs: - - Tests - name: Multi-arch build + - tests + name: Edge release runs-on: ubuntu-latest steps: - name: Set up QEMU @@ -71,4 +92,4 @@ jobs: - name: Build and push Docker image for main branch run: | make release GOTENBERG_VERSION=edge - make release GOTENBERG_VERSION=edge DOCKER_REPOSITORY=thecodingmachine + make release GOTENBERG_VERSION=edge DOCKER_REGISTRY=thecodingmachine diff --git a/Makefile b/Makefile index 5760042b..3e658a7f 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ help: ## Show the help it: build build-tests ## Initialize the development environment GOLANG_VERSION=1.23 +DOCKER_REGISTRY=gotenberg DOCKER_REPOSITORY=gotenberg GOTENBERG_VERSION=snapshot GOTENBERG_USER_GID=1001 @@ -23,7 +24,7 @@ build: ## Build the Gotenberg's Docker image --build-arg GOTENBERG_USER_UID=$(GOTENBERG_USER_UID) \ --build-arg NOTO_COLOR_EMOJI_VERSION=$(NOTO_COLOR_EMOJI_VERSION) \ --build-arg PDFTK_VERSION=$(PDFTK_VERSION) \ - -t $(DOCKER_REPOSITORY)/gotenberg:$(GOTENBERG_VERSION) \ + -t $(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY):$(GOTENBERG_VERSION) \ -f build/Dockerfile . GOTENBERG_GRACEFUL_SHUTDOWN_DURATION=30s @@ -84,7 +85,7 @@ run: ## Start a Gotenberg container -p $(API_PORT):$(API_PORT) \ -e GOTENBERG_API_BASIC_AUTH_USERNAME=$(GOTENBERG_API_BASIC_AUTH_USERNAME) \ -e GOTENBERG_API_BASIC_AUTH_PASSWORD=$(GOTENBERG_API_BASIC_AUTH_PASSWORD) \ - $(DOCKER_REPOSITORY)/gotenberg:$(GOTENBERG_VERSION) \ + $(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY):$(GOTENBERG_VERSION) \ gotenberg \ --gotenberg-graceful-shutdown-duration=$(GOTENBERG_GRACEFUL_SHUTDOWN_DURATION) \ --api-port=$(API_PORT) \ @@ -143,21 +144,21 @@ build-tests: ## Build the tests' Docker image --build-arg DOCKER_REPOSITORY=$(DOCKER_REPOSITORY) \ --build-arg GOTENBERG_VERSION=$(GOTENBERG_VERSION) \ --build-arg GOLANGCI_LINT_VERSION=$(GOLANGCI_LINT_VERSION) \ - -t $(DOCKER_REPOSITORY)/gotenberg:$(GOTENBERG_VERSION)-tests \ + -t $(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY):$(GOTENBERG_VERSION)-tests \ -f test/Dockerfile . .PHONY: tests tests: ## Start the testing environment docker run --rm -it \ -v $(PWD):/tests \ - $(DOCKER_REPOSITORY)/gotenberg:$(GOTENBERG_VERSION)-tests \ + $(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY)g:$(GOTENBERG_VERSION)-tests \ bash .PHONY: tests-once tests-once: ## Run the tests once (prefer the "tests" command while developing) docker run --rm \ -v $(PWD):/tests \ - $(DOCKER_REPOSITORY)/gotenberg:$(GOTENBERG_VERSION)-tests \ + $(DOCKER_REGISTRY)/$(DOCKER_REPOSITORY):$(GOTENBERG_VERSION)-tests \ gotest # go install mvdan.cc/gofumpt@latest @@ -174,8 +175,10 @@ godoc: ## Run a webserver with Gotenberg godoc $(info http://localhost:6060/pkg/github.com/gotenberg/gotenberg/v8) godoc -http=:6060 +LINUX_AMD64_RELEASE=false + .PHONY: release -release: ## Build the Gotenberg's Docker image for many platforms, then push it to a Docker repository +release: ## Build the Gotenberg's Docker image and push it to a Docker repository ./scripts/release.sh \ $(GOLANG_VERSION) \ $(GOTENBERG_VERSION) \ @@ -183,4 +186,7 @@ release: ## Build the Gotenberg's Docker image for many platforms, then push it $(GOTENBERG_USER_UID) \ $(NOTO_COLOR_EMOJI_VERSION) \ $(PDFTK_VERSION) \ - $(DOCKER_REPOSITORY) + $(DOCKER_REGISTRY) \ + $(DOCKER_REPOSITORY) \ + $(LINUX_AMD64_RELEASE) + diff --git a/build/Dockerfile.cloudrun b/build/Dockerfile.cloudrun index 8f400b0a..0298ae93 100644 --- a/build/Dockerfile.cloudrun +++ b/build/Dockerfile.cloudrun @@ -1,7 +1,8 @@ +ARG DOCKER_REGISTRY ARG DOCKER_REPOSITORY ARG GOTENBERG_VERSION -FROM $DOCKER_REPOSITORY/gotenberg:$GOTENBERG_VERSION +FROM $DOCKER_REGISTRY/$DOCKER_REPOSITORY:$GOTENBERG_VERSION USER root diff --git a/scripts/release.sh b/scripts/release.sh index df50077f..1b56ce2f 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -2,50 +2,60 @@ set -e +# Args. GOLANG_VERSION="$1" GOTENBERG_VERSION="$2" GOTENBERG_USER_GID="$3" GOTENBERG_USER_UID="$4" NOTO_COLOR_EMOJI_VERSION="$5" PDFTK_VERSION="$6" -DOCKER_REPOSITORY="$7" - -if [ "$GOTENBERG_VERSION" == "edge" ]; then - docker buildx build \ - --build-arg GOLANG_VERSION="$GOLANG_VERSION" \ - --build-arg GOTENBERG_VERSION="$GOTENBERG_VERSION" \ - --build-arg GOTENBERG_USER_GID="$GOTENBERG_USER_GID" \ - --build-arg GOTENBERG_USER_UID="$GOTENBERG_USER_UID" \ - --build-arg NOTO_COLOR_EMOJI_VERSION="$NOTO_COLOR_EMOJI_VERSION" \ - --build-arg PDFTK_VERSION="$PDFTK_VERSION" \ - --platform linux/amd64 \ - --platform linux/arm64 \ - --platform linux/386 \ - --platform linux/arm/v7 \ - -t "$DOCKER_REPOSITORY/gotenberg:edge" \ - --push \ - -f build/Dockerfile . - - # Cloud Run variant. - # Only linux/amd64! See https://github.com/gotenberg/gotenberg/issues/505#issuecomment-1264679278. - docker buildx build \ - --build-arg DOCKER_REPOSITORY="$DOCKER_REPOSITORY" \ - --build-arg GOTENBERG_VERSION="$GOTENBERG_VERSION" \ - --platform linux/amd64 \ - -t "$DOCKER_REPOSITORY/gotenberg:edge-cloudrun" \ - --push \ - -f build/Dockerfile.cloudrun . - - exit 0 -fi +DOCKER_REGISTRY="$7" +DOCKER_REPOSITORY="$8" +LINUX_AMD64_RELEASE="$9" +# Find out if given version is "semver". GOTENBERG_VERSION="${GOTENBERG_VERSION//v}" IFS='.' read -ra SEMVER <<< "$GOTENBERG_VERSION" VERSION_LENGTH=${#SEMVER[@]} +TAGS=() +TAGS_CLOUD_RUN=() -if [ "$VERSION_LENGTH" -ne 3 ]; then - echo "$VERSION is not semver." - exit 1 +if [ "$VERSION_LENGTH" -eq 3 ]; then + MAJOR="${SEMVER[0]}" + MINOR="${SEMVER[1]}" + PATCH="${SEMVER[2]}" + + TAGS+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:latest") + TAGS+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:$MAJOR") + TAGS+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:$MAJOR.$MINOR") + TAGS+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:$MAJOR.$MINOR.$PATCH") + + TAGS_CLOUD_RUN+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:latest-cloudrun") + TAGS_CLOUD_RUN+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:$MAJOR-cloudrun") + TAGS_CLOUD_RUN+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:$MAJOR.$MINOR-cloudrun") + TAGS_CLOUD_RUN+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:$MAJOR.$MINOR.$PATCH-cloudrun") +else + # Normalizes version. + GOTENBERG_VERSION="${GOTENBERG_VERSION// /-}" + GOTENBERG_VERSION="$(echo "$GOTENBERG_VERSION" | tr -cd '[:alnum:]._\-')" + + if [[ "$GOTENBERG_VERSION" =~ ^[\.\-] ]]; then + GOTENBERG_VERSION="_${GOTENBERG_VERSION#?}" + fi + + if [ "${#GOTENBERG_VERSION}" -gt 128 ]; then + GOTENBERG_VERSION="${GOTENBERG_VERSION:0:128}" + fi + + TAGS+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:$GOTENBERG_VERSION") + TAGS_CLOUD_RUN+=("-t" "$DOCKER_REGISTRY/$DOCKER_REPOSITORY:$GOTENBERG_VERSION-cloudrun") +fi + +# Multi-arch build takes a lot of time. +if [ "$LINUX_AMD64_RELEASE" = true ]; then + PLATFORM_FLAG="--platform linux/amd64" +else + PLATFORM_FLAG="--platform linux/amd64,linux/arm64,linux/386,linux/arm/v7" fi docker buildx build \ @@ -55,26 +65,18 @@ docker buildx build \ --build-arg GOTENBERG_USER_UID="$GOTENBERG_USER_UID" \ --build-arg NOTO_COLOR_EMOJI_VERSION="$NOTO_COLOR_EMOJI_VERSION" \ --build-arg PDFTK_VERSION="$PDFTK_VERSION" \ - --platform linux/amd64 \ - --platform linux/arm64 \ - --platform linux/386 \ - --platform linux/arm/v7 \ - -t "$DOCKER_REPOSITORY/gotenberg:latest" \ - -t "$DOCKER_REPOSITORY/gotenberg:${SEMVER[0]}" \ - -t "$DOCKER_REPOSITORY/gotenberg:${SEMVER[0]}.${SEMVER[1]}" \ - -t "$DOCKER_REPOSITORY/gotenberg:${SEMVER[0]}.${SEMVER[1]}.${SEMVER[2]}" \ + $PLATFORM_FLAG \ + "${TAGS[@]}" \ --push \ -f build/Dockerfile . # Cloud Run variant. # Only linux/amd64! See https://github.com/gotenberg/gotenberg/issues/505#issuecomment-1264679278. docker buildx build \ + --build-arg DOCKER_REGISTRY="$DOCKER_REGISTRY" \ --build-arg DOCKER_REPOSITORY="$DOCKER_REPOSITORY" \ --build-arg GOTENBERG_VERSION="$GOTENBERG_VERSION" \ --platform linux/amd64 \ - -t "$DOCKER_REPOSITORY/gotenberg:latest-cloudrun" \ - -t "$DOCKER_REPOSITORY/gotenberg:${SEMVER[0]}-cloudrun" \ - -t "$DOCKER_REPOSITORY/gotenberg:${SEMVER[0]}.${SEMVER[1]}-cloudrun" \ - -t "$DOCKER_REPOSITORY/gotenberg:${SEMVER[0]}.${SEMVER[1]}.${SEMVER[2]}-cloudrun" \ + "${TAGS_CLOUD_RUN[@]}" \ --push \ - -f build/Dockerfile.cloudrun . \ No newline at end of file + -f build/Dockerfile.cloudrun .