From b9eff113ac4fa7c67c1a1389e0420c35d692ac5e Mon Sep 17 00:00:00 2001 From: Nawaz Dhandala Date: Thu, 12 Mar 2026 22:14:10 +0000 Subject: [PATCH] Refactor Docker image build and merge workflows for multi-architecture support - Updated GitHub Actions workflows to implement a matrix strategy for building Docker images across multiple architectures (linux/amd64 and linux/arm64). - Introduced new jobs for merging multi-arch manifests after building images, ensuring proper tagging and pushing to Docker Hub and GitHub Container Registry. - Enhanced the `build_docker_images.sh` script to append architecture suffixes to tags for single-platform builds, preventing tag collisions. - Added a new script `merge_docker_manifests.sh` to create and push multi-arch manifests for built images. - Removed redundant Docker metadata actions and streamlined the build process for clarity and efficiency. --- .github/workflows/release.yml | 695 +++++++++++++++----------- .github/workflows/test-release.yaml | 645 ++++++++++++++---------- Scripts/GHA/build_docker_images.sh | 31 +- Scripts/GHA/merge_docker_manifests.sh | 67 +++ 4 files changed, 894 insertions(+), 544 deletions(-) create mode 100755 Scripts/GHA/merge_docker_manifests.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f92ec4eed..a69d9899e9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,12 +78,12 @@ jobs: # Check if this version is already released on GitHub echo "Checking if version $VERSION_RAW is already released on GitHub..." - + if gh release view "$VERSION_RAW" --repo "$REPOSITORY" &>/dev/null; then echo "::error::Version $VERSION_RAW is already released on GitHub. Please update the VERSION file to a new version." exit 1 fi - + # Also check with 'v' prefix just in case if gh release view "v$VERSION_RAW" --repo "$REPOSITORY" &>/dev/null; then echo "::error::Version v$VERSION_RAW is already released on GitHub. Please update the VERSION file to a new version." @@ -103,11 +103,11 @@ jobs: helm-chart-deploy: runs-on: ubuntu-latest needs: [generate-build-number, read-version] - env: + env: CI_COMMIT_AUTHOR: Continuous Integration steps: - - name: Install Helm + - name: Install Helm run: curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash - uses: actions/checkout@v4 @@ -121,7 +121,7 @@ jobs: gpg --import private.key || true rm private.key echo "GPG key imported successfully" - gpg --export-secret-keys >~/.gnupg/secring.gpg + gpg --export-secret-keys >~/.gnupg/secring.gpg echo "GPG key exported successfully" eval `ssh-agent -s` ssh-add - <<< '${{ secrets.HELM_CHART_GITHUB_REPO_DEPLOY_KEY }}' @@ -129,7 +129,7 @@ jobs: cd oneuptime/HelmChart/Public helm lint oneuptime helm template oneuptime --values oneuptime/values.yaml - helm package --sign --key 'key@oneuptime.com' --keyring ~/.gnupg/secring.gpg oneuptime --version ${{needs.read-version.outputs.major_minor}} --app-version ${{needs.read-version.outputs.major_minor}} + helm package --sign --key 'key@oneuptime.com' --keyring ~/.gnupg/secring.gpg oneuptime --version ${{needs.read-version.outputs.major_minor}} --app-version ${{needs.read-version.outputs.major_minor}} echo "Helm Chart Package created successfully" cd .. ls @@ -148,13 +148,21 @@ jobs: git commit -m "Helm Chart Release ${{needs.read-version.outputs.major_minor}}" git push origin master - nginx-docker-image-deploy: + # ─── Docker image build jobs (per-arch matrix) ─────────────────────── + + nginx-docker-image-build: needs: [generate-build-number, read-version] - runs-on: ubuntu-latest - env: - QEMU_CPU: max + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -164,16 +172,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/nginx - ghcr.io/oneuptime/nginx - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -183,21 +181,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy nginx. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -213,16 +202,49 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./Nginx/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" - e2e-docker-image-deploy: - needs: [generate-build-number, read-version] + nginx-docker-image-merge: + needs: [nginx-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image nginx \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + e2e-docker-image-build: + needs: [generate-build-number, read-version] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -232,16 +254,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/e2e - ghcr.io/oneuptime/e2e - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -251,21 +263,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy e2e. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -281,16 +284,49 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./E2E/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" - home-docker-image-deploy: - needs: [generate-build-number, read-version] + e2e-docker-image-merge: + needs: [e2e-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image e2e \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + home-docker-image-build: + needs: [generate-build-number, read-version] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -300,16 +336,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/home - ghcr.io/oneuptime/home - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -319,21 +345,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy home. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -349,19 +366,49 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./Home/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" - - - - test-server-docker-image-deploy: - needs: [generate-build-number, read-version] + home-docker-image-merge: + needs: [home-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image home \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + test-server-docker-image-build: + needs: [generate-build-number, read-version] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -371,16 +418,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/test-server - ghcr.io/oneuptime/test-server - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -390,21 +427,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy test-server. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -420,16 +448,49 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./TestServer/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" - test-docker-image-deploy: - needs: [generate-build-number, read-version] + test-server-docker-image-merge: + needs: [test-server-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image test-server \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + test-docker-image-build: + needs: [generate-build-number, read-version] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -439,16 +500,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/test - ghcr.io/oneuptime/test - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -458,21 +509,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy test. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -488,16 +530,49 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./Tests/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" - telemetry-docker-image-deploy: - needs: [generate-build-number, read-version] + test-docker-image-merge: + needs: [test-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image test \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + telemetry-docker-image-build: + needs: [generate-build-number, read-version] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -507,16 +582,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/telemetry - ghcr.io/oneuptime/telemetry - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -526,21 +591,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy telemetry. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -556,17 +612,49 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./Telemetry/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" - - probe-docker-image-deploy: - needs: [generate-build-number, read-version] + telemetry-docker-image-merge: + needs: [telemetry-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image telemetry \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + probe-docker-image-build: + needs: [generate-build-number, read-version] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -576,16 +664,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/probe - ghcr.io/oneuptime/probe - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -595,21 +673,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy probe. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -625,16 +694,49 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./Probe/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" - app-docker-image-deploy: - needs: [generate-build-number, read-version] + probe-docker-image-merge: + needs: [probe-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image probe \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + app-docker-image-build: + needs: [generate-build-number, read-version] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -644,16 +746,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/app - ghcr.io/oneuptime/app - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -663,21 +755,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy app. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -693,17 +776,49 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./App/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" - - ai-agent-docker-image-deploy: - needs: [generate-build-number, read-version] + app-docker-image-merge: + needs: [app-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image app \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + ai-agent-docker-image-build: + needs: [generate-build-number, read-version] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -713,16 +828,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/ai-agent - ghcr.io/oneuptime/ai-agent - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - uses: actions/checkout@v4 with: @@ -732,21 +837,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy ai-agent. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -762,9 +858,36 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./AIAgent/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" + ai-agent-docker-image-merge: + needs: [ai-agent-docker-image-build, read-version] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image ai-agent \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + publish-npm-packages: runs-on: ubuntu-latest needs: [generate-build-number, read-version] @@ -775,7 +898,7 @@ jobs: CI_PIPELINE_ID: ${{github.run_number}} PACKAGE_VERSION: ${{needs.read-version.outputs.major_minor}} steps: - - name: Checkout + - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 @@ -789,13 +912,19 @@ jobs: - name: Publish NPM Packages run: bash ./Scripts/NPM/PublishAllPackages.sh - worker-docker-image-deploy: + worker-docker-image-build: needs: [generate-build-number, read-version] - runs-on: ubuntu-latest - env: - QEMU_CPU: max + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -805,17 +934,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/worker - ghcr.io/oneuptime/worker - tags: | - type=raw,value=release,enable=true - type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true - - uses: actions/checkout@v4 with: @@ -825,21 +943,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy nginx. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -855,16 +964,42 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}" \ --dockerfile ./Worker/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" + worker-docker-image-merge: + needs: [worker-docker-image-build, read-version] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image worker \ + --tags "${SANITIZED_VERSION},enterprise-${SANITIZED_VERSION}" + + # ─── Non-Docker jobs (downstream dependencies updated) ─────────────── publish-terraform-provider: runs-on: ubuntu-latest needs: [generate-build-number, read-version] - env: + env: CI_PIPELINE_ID: ${{github.run_number}} GITHUB_TOKEN: ${{ secrets.SIMLARSEN_GITHUB_PAT }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} @@ -914,29 +1049,29 @@ jobs: gpg --import private.key || true rm private.key echo "GPG key imported successfully" - gpg --export-secret-keys >~/.gnupg/secring.gpg + gpg --export-secret-keys >~/.gnupg/secring.gpg echo "GPG key exported successfully" - name: Generate Terraform provider run: npm run publish-terraform-provider -- --version "${{ steps.version.outputs.version }}" --github-token "${{ secrets.SIMLARSEN_GITHUB_PAT }}" --github-repo-deploy-key "${{ secrets.TERRAFORM_PROVIDER_GITHUB_REPO_DEPLOY_KEY }}" - + push-release-tags: name: Push release tags before GitHub release needs: - read-version - generate-build-number - - nginx-docker-image-deploy - - e2e-docker-image-deploy - - home-docker-image-deploy - - test-server-docker-image-deploy - - test-docker-image-deploy - - telemetry-docker-image-deploy - - probe-docker-image-deploy - - app-docker-image-deploy - - ai-agent-docker-image-deploy - - worker-docker-image-deploy + - nginx-docker-image-merge + - e2e-docker-image-merge + - home-docker-image-merge + - test-server-docker-image-merge + - test-docker-image-merge + - telemetry-docker-image-merge + - probe-docker-image-merge + - app-docker-image-merge + - ai-agent-docker-image-merge + - worker-docker-image-merge - test-e2e-release-saas - test-e2e-release-self-hosted runs-on: ubuntu-latest @@ -994,13 +1129,12 @@ jobs: docker buildx imagetools create \ --tag ghcr.io/oneuptime/${{ matrix.image }}:enterprise-release \ ghcr.io/oneuptime/${{ matrix.image }}:enterprise-${VERSION} - - - + + test-e2e-release-saas: runs-on: ubuntu-latest - needs: [telemetry-docker-image-deploy, ai-agent-docker-image-deploy, app-docker-image-deploy, home-docker-image-deploy, worker-docker-image-deploy, probe-docker-image-deploy, test-docker-image-deploy, test-server-docker-image-deploy, publish-npm-packages, e2e-docker-image-deploy, helm-chart-deploy, generate-build-number, read-version, nginx-docker-image-deploy] + needs: [telemetry-docker-image-merge, ai-agent-docker-image-merge, app-docker-image-merge, home-docker-image-merge, worker-docker-image-merge, probe-docker-image-merge, test-docker-image-merge, test-server-docker-image-merge, publish-npm-packages, e2e-docker-image-merge, helm-chart-deploy, generate-build-number, read-version, nginx-docker-image-merge] env: CI_PIPELINE_ID: ${{github.run_number}} steps: @@ -1114,13 +1248,13 @@ jobs: # Name of the artifact to upload. # Optional. Default is 'artifact' name: test-results-${{ github.job }}-${{ github.run_attempt }} - + # A file, directory or wildcard pattern that describes what to upload # Required. path: | ./E2E - - + + # Duration after which artifact will expire in days. 0 means using default retention. # Minimum 1 day. # Maximum 90 days unless changed from the repository settings page. @@ -1131,7 +1265,7 @@ jobs: test-e2e-release-self-hosted: runs-on: ubuntu-latest # After all the jobs runs - needs: [telemetry-docker-image-deploy, ai-agent-docker-image-deploy, app-docker-image-deploy, home-docker-image-deploy, worker-docker-image-deploy, probe-docker-image-deploy, test-docker-image-deploy, test-server-docker-image-deploy, publish-npm-packages, e2e-docker-image-deploy, helm-chart-deploy, generate-build-number, read-version, nginx-docker-image-deploy] + needs: [telemetry-docker-image-merge, ai-agent-docker-image-merge, app-docker-image-merge, home-docker-image-merge, worker-docker-image-merge, probe-docker-image-merge, test-docker-image-merge, test-server-docker-image-merge, publish-npm-packages, e2e-docker-image-merge, helm-chart-deploy, generate-build-number, read-version, nginx-docker-image-merge] env: CI_PIPELINE_ID: ${{github.run_number}} steps: @@ -1244,13 +1378,13 @@ jobs: # Name of the artifact to upload. # Optional. Default is 'artifact' name: test-results-${{ github.job }}-${{ github.run_attempt }} - + # A file, directory or wildcard pattern that describes what to upload # Required. path: | ./E2E - - + + # Duration after which artifact will expire in days. 0 means using default retention. # Minimum 1 day. # Maximum 90 days unless changed from the repository settings page. @@ -1274,7 +1408,7 @@ jobs: uses: mikepenz/release-changelog-builder-action@v4.2.0 with: configuration: "./Scripts/Release/ChangelogConfig.json" - - run: echo "Changelog:" + - run: echo "Changelog:" - run: echo "${{steps.build_changelog.outputs.changelog}}" - name: Fallback to commit messages if changelog empty id: fallback_changelog @@ -1340,7 +1474,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.ref }} - + - name: Set up Go uses: actions/setup-go@v4 @@ -1364,7 +1498,7 @@ jobs: - name: Release MSI Images run: cd InfrastructureAgent && bash build-msi.sh ${{needs.read-version.outputs.major_minor}} - + # Upload binaries to github release - name: Release uses: softprops/action-gh-release@v2 @@ -1780,4 +1914,3 @@ jobs: rm -f $RUNNER_TEMP/distribution_certificate.p12 rm -f $RUNNER_TEMP/distribution_profile.mobileprovision rm -f $RUNNER_TEMP/AuthKey_*.p8 - diff --git a/.github/workflows/test-release.yaml b/.github/workflows/test-release.yaml index eabcba1423..8c1f626581 100644 --- a/.github/workflows/test-release.yaml +++ b/.github/workflows/test-release.yaml @@ -86,13 +86,21 @@ jobs: echo "patch=${target_patch}" >> "$GITHUB_OUTPUT" echo "Using version base: ${new_version}" - nginx-docker-image-deploy: + # ─── Docker image build jobs (per-arch matrix) ─────────────────────── + + nginx-docker-image-build: needs: [read-version, generate-build-number] - runs-on: ubuntu-latest - env: - QEMU_CPU: max + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -102,17 +110,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/nginx - ghcr.io/oneuptime/nginx - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -122,20 +119,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy nginx. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -151,19 +140,52 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./Nginx/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - - e2e-docker-image-deploy: - needs: [read-version, generate-build-number] + nginx-docker-image-merge: + needs: [nginx-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image nginx \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + + e2e-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -173,17 +195,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/e2e - ghcr.io/oneuptime/e2e - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -193,20 +204,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy e2e. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -222,18 +225,51 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./E2E/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - test-server-docker-image-deploy: - needs: [read-version, generate-build-number] + e2e-docker-image-merge: + needs: [e2e-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image e2e \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + test-server-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -243,17 +279,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/test-server - ghcr.io/oneuptime/test-server - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -263,20 +288,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy test-server. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -292,18 +309,51 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./TestServer/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - home-docker-image-deploy: - needs: [read-version, generate-build-number] + test-server-docker-image-merge: + needs: [test-server-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image test-server \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + home-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -313,17 +363,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/home - ghcr.io/oneuptime/home - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -333,20 +372,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy home. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -362,20 +393,51 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./Home/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - - - test-docker-image-deploy: - needs: [read-version, generate-build-number] + home-docker-image-merge: + needs: [home-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image home \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + test-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -385,17 +447,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/test - ghcr.io/oneuptime/test - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -405,20 +456,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy test. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -434,19 +477,51 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./Tests/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - - telemetry-docker-image-deploy: - needs: [read-version, generate-build-number] + test-docker-image-merge: + needs: [test-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image test \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + telemetry-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -456,17 +531,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/telemetry - ghcr.io/oneuptime/telemetry - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -476,20 +540,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy telemetry. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -505,18 +561,51 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./Telemetry/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - probe-docker-image-deploy: - needs: [read-version, generate-build-number] + telemetry-docker-image-merge: + needs: [telemetry-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image telemetry \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + probe-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -526,17 +615,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/probe - ghcr.io/oneuptime/probe - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -546,20 +624,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy probe. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -575,18 +645,51 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./Probe/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - app-docker-image-deploy: - needs: [read-version, generate-build-number] + probe-docker-image-merge: + needs: [probe-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image probe \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + app-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -596,17 +699,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/app - ghcr.io/oneuptime/app - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -616,20 +708,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy app. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -645,21 +729,51 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./App/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - - - - ai-agent-docker-image-deploy: - needs: [read-version, generate-build-number] + app-docker-image-merge: + needs: [app-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image app \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + ai-agent-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -669,17 +783,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/ai-agent - ghcr.io/oneuptime/ai-agent - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -689,19 +792,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy ai-agent. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -717,18 +813,51 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./AIAgent/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test - worker-docker-image-deploy: - needs: [read-version, generate-build-number] + ai-agent-docker-image-merge: + needs: [ai-agent-docker-image-build, read-version] runs-on: ubuntu-latest - env: - QEMU_CPU: max + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image ai-agent \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + worker-docker-image-build: + needs: [read-version, generate-build-number] + strategy: + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Free Disk Space (Ubuntu) + if: matrix.platform == 'linux/amd64' uses: jlumbroso/free-disk-space@main with: tool-cache: false @@ -738,17 +867,6 @@ jobs: large-packages: true docker-images: true swap-storage: true - - name: Docker Meta - id: meta - uses: docker/metadata-action@v4 - with: - images: | - oneuptime/worker - ghcr.io/oneuptime/worker - tags: | - type=raw,value=test,enable=true - type=raw,value=${{needs.read-version.outputs.major_minor}}-test,enable=true - - uses: actions/checkout@v4 with: @@ -758,20 +876,12 @@ jobs: with: node-version: latest - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - image: tonistiigi/binfmt:qemu-v10.0.4 - - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Generate Dockerfile from Dockerfile.tpl run: npm run prerun - # Build and deploy accounts. - - name: Login to Docker Hub run: | echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin @@ -787,11 +897,39 @@ jobs: --version "${{needs.read-version.outputs.major_minor}}-test" \ --dockerfile ./Worker/Dockerfile \ --context . \ - --platforms linux/amd64,linux/arm64 \ + --platforms ${{ matrix.platform }} \ --git-sha "${{ github.sha }}" \ --extra-tags test \ --extra-enterprise-tags enterprise-test + worker-docker-image-merge: + needs: [worker-docker-image-build, read-version] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + run: | + echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin + + - name: Merge multi-arch manifests + run: | + VERSION="${{needs.read-version.outputs.major_minor}}-test" + SANITIZED_VERSION="${VERSION//+/-}" + bash ./Scripts/GHA/merge_docker_manifests.sh \ + --image worker \ + --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test" + + # ─── Non-Docker jobs (unchanged) ───────────────────────────────────── publish-terraform-provider: runs-on: ubuntu-latest @@ -805,11 +943,10 @@ jobs: VERSION="${{needs.read-version.outputs.major_minor}}-test" echo "Skipping Terraform provider publish for test release $VERSION" - test-helm-chart: runs-on: ubuntu-latest - needs: [infrastructure-agent-deploy, publish-terraform-provider, telemetry-docker-image-deploy, worker-docker-image-deploy, home-docker-image-deploy, test-server-docker-image-deploy, test-docker-image-deploy, probe-docker-image-deploy, app-docker-image-deploy, ai-agent-docker-image-deploy, nginx-docker-image-deploy, e2e-docker-image-deploy] + needs: [infrastructure-agent-deploy, publish-terraform-provider, telemetry-docker-image-merge, worker-docker-image-merge, home-docker-image-merge, test-server-docker-image-merge, test-docker-image-merge, probe-docker-image-merge, app-docker-image-merge, ai-agent-docker-image-merge, nginx-docker-image-merge, e2e-docker-image-merge] env: CI_PIPELINE_ID: ${{github.run_number}} steps: @@ -910,7 +1047,7 @@ jobs: retention-days: 7 - test-e2e-test-self-hosted: + test-e2e-test-self-hosted: runs-on: ubuntu-latest # After all the jobs runs needs: [test-helm-chart, generate-build-number, read-version] @@ -1003,7 +1140,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.ref }} - + - name: Set up Go uses: actions/setup-go@v4 @@ -1027,7 +1164,7 @@ jobs: - name: Release MSI Images run: cd InfrastructureAgent && bash build-msi.sh ${{needs.read-version.outputs.major_minor}}.${{needs.generate-build-number.outputs.build_number}} - + - name: Upload Release Binaries uses: actions/upload-artifact@v4 @@ -1036,13 +1173,13 @@ jobs: # Name of the artifact to upload. # Optional. Default is 'artifact' name: binaries - + # A file, directory or wildcard pattern that describes what to upload # Required. path: | ./InfrastructureAgent/dist - - + + # Duration after which artifact will expire in days. 0 means using default retention. # Minimum 1 day. # Maximum 90 days unless changed from the repository settings page. diff --git a/Scripts/GHA/build_docker_images.sh b/Scripts/GHA/build_docker_images.sh index 9a9611ff53..dedbed4ade 100644 --- a/Scripts/GHA/build_docker_images.sh +++ b/Scripts/GHA/build_docker_images.sh @@ -14,6 +14,8 @@ Required flags: Optional flags: --context Build context directory (default: .) --platforms Comma-separated platforms passed to docker buildx (default: linux/amd64,linux/arm64) + When a single platform is given, tags are suffixed with the arch + (e.g. -amd64 or -arm64) so parallel builds don't overwrite each other. --git-sha Commit SHA used for the GIT_SHA build arg (default: detected via git) --extra-tags Additional tags for the community image (can be repeated) --extra-enterprise-tags Additional tags for the enterprise image (can be repeated) @@ -88,6 +90,15 @@ if [[ -z "$GIT_SHA" ]]; then fi fi +# Determine if this is a single-platform build. +# When building for a single platform, append the arch suffix to tags +# so that parallel per-arch jobs don't overwrite each other. +ARCH_SUFFIX="" +if [[ "$PLATFORMS" != *","* ]]; then + # Single platform — extract arch (e.g. linux/amd64 -> amd64) + ARCH_SUFFIX="-${PLATFORMS#*/}" +fi + build_variant() { local variant_prefix="$1" # "" or "enterprise-" local enterprise_flag="$2" # false/true @@ -95,24 +106,26 @@ build_variant() { local sanitized_version sanitized_version="${VERSION//+/-}" + local cache_scope="${IMAGE}-${variant_prefix:-community}" + local -a args args=( docker buildx build --file "$DOCKERFILE" --platform "$PLATFORMS" --push - --cache-from "type=gha,scope=${IMAGE}-${variant_prefix:-community}" - --cache-to "type=gha,mode=max,scope=${IMAGE}-${variant_prefix:-community}" + --cache-from "type=registry,ref=ghcr.io/oneuptime/${IMAGE}:cache-${cache_scope}" + --cache-to "type=registry,ref=ghcr.io/oneuptime/${IMAGE}:cache-${cache_scope},mode=max" ) args+=( - --tag "oneuptime/${IMAGE}:${variant_prefix}${sanitized_version}" - --tag "ghcr.io/oneuptime/${IMAGE}:${variant_prefix}${sanitized_version}" + --tag "oneuptime/${IMAGE}:${variant_prefix}${sanitized_version}${ARCH_SUFFIX}" + --tag "ghcr.io/oneuptime/${IMAGE}:${variant_prefix}${sanitized_version}${ARCH_SUFFIX}" ) for tag_suffix in "${extra_tags_ref[@]}"; do - args+=(--tag "oneuptime/${IMAGE}:${tag_suffix}") - args+=(--tag "ghcr.io/oneuptime/${IMAGE}:${tag_suffix}") + args+=(--tag "oneuptime/${IMAGE}:${tag_suffix}${ARCH_SUFFIX}") + args+=(--tag "ghcr.io/oneuptime/${IMAGE}:${tag_suffix}${ARCH_SUFFIX}") done args+=( @@ -125,8 +138,8 @@ build_variant() { "${args[@]}" } -echo "🚀 Building docker images for ${IMAGE} (${VERSION})" +echo "🚀 Building docker images for ${IMAGE} (${VERSION}) [${PLATFORMS}]" build_variant "" false EXTRA_TAGS -echo "✅ Pushed community image for ${IMAGE}:${VERSION}" +echo "✅ Pushed community image for ${IMAGE}:${VERSION}${ARCH_SUFFIX}" build_variant "enterprise-" true EXTRA_ENTERPRISE_TAGS -echo "✅ Pushed enterprise image for ${IMAGE}:enterprise-${VERSION}" +echo "✅ Pushed enterprise image for ${IMAGE}:enterprise-${VERSION}${ARCH_SUFFIX}" diff --git a/Scripts/GHA/merge_docker_manifests.sh b/Scripts/GHA/merge_docker_manifests.sh new file mode 100755 index 0000000000..e3638b55fe --- /dev/null +++ b/Scripts/GHA/merge_docker_manifests.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + cat <<'EOF' +Usage: merge_docker_manifests.sh --image --tags + +Combines per-architecture images (tagged with -amd64 / -arm64 suffixes) into +multi-arch manifests and pushes them to Docker Hub and GHCR. + +Required flags: + --image Image name without registry prefix (example: nginx) + --tags Comma-separated list of final manifest tags to create + (e.g. "10.0.31,release,enterprise-10.0.31,enterprise-release") +EOF +} + +IMAGE="" +TAGS="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --image) + IMAGE="$2" + shift 2 + ;; + --tags) + TAGS="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + usage + exit 1 + ;; + esac +done + +if [[ -z "$IMAGE" || -z "$TAGS" ]]; then + echo "Missing required arguments" >&2 + usage + exit 1 +fi + +IFS=',' read -ra TAG_LIST <<< "$TAGS" + +for tag in "${TAG_LIST[@]}"; do + tag="$(echo "$tag" | xargs)" # trim whitespace + [[ -z "$tag" ]] && continue + + echo "🔗 Creating multi-arch manifest for ${IMAGE}:${tag}" + + # Create manifest from arch-specific tags and push to both registries + for registry in "oneuptime" "ghcr.io/oneuptime"; do + docker buildx imagetools create \ + --tag "${registry}/${IMAGE}:${tag}" \ + "${registry}/${IMAGE}:${tag}-amd64" \ + "${registry}/${IMAGE}:${tag}-arm64" + done + + echo "✅ Pushed multi-arch manifest for ${IMAGE}:${tag}" +done