From 28ded3b2643204d6ad6a22c78c0acf0c498ddb11 Mon Sep 17 00:00:00 2001 From: Jakob Lichterfeld Date: Sat, 16 Mar 2024 14:43:17 +0100 Subject: [PATCH] ci: distribute build across multiple runners --- .github/workflows/buildx.yml | 181 ++++++++++++++++++++++------------- CHANGELOG.md | 1 + README.md | 1 + 3 files changed, 119 insertions(+), 64 deletions(-) diff --git a/.github/workflows/buildx.yml b/.github/workflows/buildx.yml index 20af8e7..9b0a2b0 100644 --- a/.github/workflows/buildx.yml +++ b/.github/workflows/buildx.yml @@ -1,88 +1,141 @@ -name: buildx +name: CI on: + workflow_dispatch: + schedule: + - cron: "0 3 * * *" # Every day at 3:00 AM push: branches: - "master" tags: - "v*" paths: - - ".github/workflows/buildx.yml" - - "Dockerfile" + - "**/*" + - "!.github/**" # exclude PRs related to .github from auto-run + - "!.github/workflows/**" # exclude PRs related to .github from auto-run +env: + REGISTRY_IMAGE: teslamatetelegrambot/teslamatetelegrambot jobs: - teslamate-telegram-bot-build: + check_paths: runs-on: ubuntu-latest + outputs: + githubfolder: ${{ steps.filter.outputs.githubfolder }} steps: - - name: Prepare - id: prepare - run: | - DOCKER_USERNAME=teslamatetelegrambot - DOCKER_IMAGE=teslamatetelegrambot/teslamatetelegrambot - DOCKER_PLATFORMS=linux/amd64,linux/arm/v7,linux/arm64 - VERSION=edge - - if [[ $GITHUB_REF == refs/tags/v* ]]; then - VERSION=${GITHUB_REF#refs/tags/v} - MINOR_VERSION=${VERSION%.*} - fi - - TAGS="--tag ${DOCKER_IMAGE}:${VERSION}" - if [ "$VERSION" != "edge" ]; then - TAGS="$TAGS --tag ${DOCKER_IMAGE}:${MINOR_VERSION} --tag ${DOCKER_IMAGE}:latest" - fi - - echo "docker_username=${DOCKER_USERNAME}" >> $GITHUB_OUTPUT - echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT - echo "version=${VERSION}" >> $GITHUB_OUTPUT - echo "buildx_args=--platform ${DOCKER_PLATFORMS} ${TAGS} --file Dockerfile ." >> $GITHUB_OUTPUT - - - name: Checkout + - + name: Checkout uses: actions/checkout@v4 + - + name: Filter paths + uses: dorny/paths-filter@v3.0.1 + id: filter + with: + filters: | + githubfolder: + - '.github/**' - - name: Set up QEMU + build: + needs: check_paths + if: needs.check_paths.outputs.githubfolder == 'false' || github.event_name == 'schedule' + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + platform: + - linux/amd64 + - linux/arm/v7 + - linux/arm64 + steps: + - + name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + - + name: Checkout + uses: actions/checkout@v4 + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + - + name: Set up QEMU uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - id: buildx + - + name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - - name: Available platforms - run: echo ${{ steps.buildx.outputs.platforms }} - - - name: Cache Docker layers - uses: actions/cache@v4 - id: cache + - + name: Login to Docker Hub + uses: docker/login-action@v3 with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-teslamatetelegrambot-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx-teslamatetelegrambot- - - - name: Docker Buildx (build) + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - + name: Build and push by digest + id: build + uses: docker/build-push-action@v5 + with: + context: . + platforms: ${{ matrix.platform }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true + - + name: Export digest run: | - docker buildx build \ - --cache-from "type=local,src=/tmp/.buildx-cache" \ - --cache-to "type=local,dest=/tmp/.buildx-cache,mode=max" \ - --output "type=image,push=false" \ - ${{ steps.prepare.outputs.buildx_args }} + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + - + name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 - - name: Docker Login - if: success() && github.event_name != 'pull_request' && (endsWith(github.ref, github.event.repository.default_branch) || startsWith(github.ref, 'refs/tags/')) + merge: + runs-on: ubuntu-latest + needs: + - build + steps: + - + name: Download digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-* + merge-multiple: true + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: | + type=schedule,pattern=edge + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=edge + - + name: Login to Docker Hub + if: github.event_name != 'pull_request' uses: docker/login-action@v3 with: - username: ${{ steps.prepare.outputs.docker_username }} + username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Docker Buildx (push) - if: success() && github.event_name != 'pull_request' && (endsWith(github.ref, github.event.repository.default_branch) || startsWith(github.ref, 'refs/tags/')) + - + name: Create manifest list and push + working-directory: /tmp/digests run: | - docker buildx build \ - --cache-from "type=local,src=/tmp/.buildx-cache" \ - --output "type=image,push=true" \ - ${{ steps.prepare.outputs.buildx_args }} - - - name: Clear - if: always() + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + - + name: Inspect image run: | - rm -f ${HOME}/.docker/config.json + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 93995c0..a5295a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - build: improve non-root user creation in dockerfile - style: remove global variables for bot and chat_id, ensure UPPERCASE for constants, update imports +- ci: distribute build across multiple runners ### Bug Fixes diff --git a/README.md b/README.md index 354215c..e5ca327 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # TeslaMate Telegram Bot +[![CI](https://github.com/JakobLichterfeld/TeslaMate-Telegram-Bot/actions/workflows/buildx.yml/badge.svg)](https://github.com/JakobLichterfeld/TeslaMate-Telegram-Bot/actions/workflows/buildx.yml) [![latest release](https://img.shields.io/github/v/release/JakobLichterfeld/TeslaMate_Telegram_Bot)](https://github.com/JakobLichterfeld/TeslaMate_Telegram_Bot/releases/latest) [![](https://images.microbadger.com/badges/version/teslamatetelegrambot/teslamatetelegrambot.svg)](https://hub.docker.com/r/teslamatetelegrambot/teslamatetelegrambot) [![](https://images.microbadger.com/badges/image/teslamatetelegrambot/teslamatetelegrambot.svg)](https://microbadger.com/images/teslamatetelegrambot/teslamatetelegrambot)