diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index a2b4e44..97216d1 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -13,8 +13,31 @@ on: env: IMAGE_NAME: robles + REGISTRY_IMAGE: razeware/robles jobs: + determine_environment: + name: Determine environment + runs-on: ubuntu-latest + outputs: + environment: ${{ steps.set_environment.outputs.environment }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set environment + id: set_environment + run: | + if [[ $GITHUB_REF == 'refs/heads/development' ]]; then + echo "environment=staging" >> $GITHUB_OUTPUT + # Else if tag starts with v, then it's a release + elif [[ $GITHUB_REF == 'refs/tags/v'* ]]; then + echo "environment=production" >> $GITHUB_OUTPUT + else + echo "environment=na" >> $GITHUB_OUTPUT + fi + + # Run tests. # See also https://docs.docker.com/docker-hub/builds/automated-testing/ test: @@ -43,13 +66,26 @@ jobs: color: danger # Push image to DockerHub. - push: + build: # Ensure test job passes before pushing image. - needs: test + needs: + - determine_environment + - test - runs-on: ubuntu-latest if: github.event_name == 'push' + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-latest + platform: linux/amd64 + - runner: public-arm-4core + platform: linux/arm64 + + runs-on: ${{ matrix.runner }} + outputs: + slack_message_id: ${{ steps.slack.outputs.message_id }} steps: - name: Notify slack - build starting uses: voxmedia/github-action-slack-notify-build@v1 @@ -62,58 +98,112 @@ jobs: status: STARTING color: warning - - uses: actions/checkout@v4 + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - name: Set up QEMU - uses: docker/setup-qemu-action@v3.2.0 + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.REGISTRY_IMAGE }} + tags: | + type=ref,event=tag,prefix=release- + type=raw,value=latest,enable=${{ github.ref_name == 'master' }} + type=raw,value=staging,enable=${{ needs.determine_environment.outputs.environment == 'staging' }} + + - uses: actions/checkout@v4 - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v3.6.1 + uses: docker/setup-buildx-action@v3 with: buildkitd-flags: --debug - name: Log in to DockerHub registry run: echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u razewareci --password-stdin - - name: Generate tag list - id: generate_tags - run: | - IMAGE_ID=razeware/$IMAGE_NAME + - name: Build and push + id: build + uses: docker/build-push-action@v6 + 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 + tags: ${{ steps.meta.outputs.tags }} - # Change all uppercase to lowercase - IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') + - name: Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" - # Strip git ref prefix from version - VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') + - 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 - # Prefix tags with 'release' - if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - TAGS=$(echo "${VERSION}" | sed -E "s/v?([0-9]+)\.([0-9]+)\.([0-9]+)/release-v\1.\2.\3 release-v\1.\2 release-v\1/g") - fi + - name: Logout of DockerHub Registry + if: ${{ always() }} + run: docker logout - # Use Docker `latest` tag convention - [ "$VERSION" == "master" ] && TAGS=latest - [ "$VERSION" == "development" ] && TAGS=staging + - name: Notify slack - build result failed + uses: voxmedia/github-action-slack-notify-build@v1 + if: failure() + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + with: + message_id: ${{ steps.slack.outputs.message_id }} + channel: build + status: FAILED + color: danger - echo IMAGE_ID=$IMAGE_ID - echo TAGS=$TAGS + merge: + runs-on: ubuntu-latest + needs: + - determine_environment + - build - TAG_LIST="" - for TAG in ${TAGS}; do - TAG_LIST="${TAG_LIST}${IMAGE_ID}:${TAG}," - done + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-* + merge-multiple: true - echo $TAG_LIST - echo "::set-output name=tag_list::${TAG_LIST}" + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - - name: Build and push - uses: docker/build-push-action@v6.6.1 + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 with: - context: . - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.generate_tags.outputs.tag_list }} + images: | + ${{ env.REGISTRY_IMAGE }} + tags: | + type=ref,event=tag,prefix=release- + type=raw,value=latest,enable=${{ github.ref_name == 'master' }} + type=raw,value=staging,enable=${{ needs.determine_environment.outputs.environment == 'staging' }} + + - name: Log in to DockerHub registry + run: echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u razewareci --password-stdin + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} - name: Logout of DockerHub Registry if: ${{ always() }} @@ -125,7 +215,7 @@ jobs: env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} with: - message_id: ${{ steps.slack.outputs.message_id }} + message_id: ${{ needs.build.outputs.slack_message_id }} channel: build status: SUCCESS color: good @@ -136,7 +226,7 @@ jobs: env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} with: - message_id: ${{ steps.slack.outputs.message_id }} + message_id: ${{ needs.build.outputs.slack_message_id }} channel: build status: FAILED color: danger diff --git a/.ruby-version b/.ruby-version index 15a2799..fa7adc7 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.0 +3.3.5 diff --git a/Gemfile b/Gemfile index 93b59e0..cedb53a 100644 --- a/Gemfile +++ b/Gemfile @@ -48,9 +48,6 @@ gem 'sass-embedded' gem 'sinatra', '~> 4' gem 'thin' -# Pinning google-protobuf so that it continues to build on ARM devices -gem 'google-protobuf', '=3.22.0' - # Controlling Chrome to create snapshots gem 'ferrum' diff --git a/Gemfile.lock b/Gemfile.lock index eff91c8..1c8def1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,9 +8,9 @@ GIT GEM remote: https://rubygems.org/ specs: - activemodel (7.2.0) - activesupport (= 7.2.0) - activesupport (7.2.0) + activemodel (7.2.1) + activesupport (= 7.2.1) + activesupport (7.2.1) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) @@ -25,20 +25,20 @@ GEM public_suffix (>= 2.0.2, < 7.0) ast (2.4.2) aws-eventstream (1.3.0) - aws-partitions (1.964.0) - aws-sdk-core (3.201.5) + aws-partitions (1.977.0) + aws-sdk-core (3.208.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.88.0) - aws-sdk-core (~> 3, >= 3.201.0) + aws-sdk-kms (1.93.0) + aws-sdk-core (~> 3, >= 3.207.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.158.0) - aws-sdk-core (~> 3, >= 3.201.0) + aws-sdk-s3 (1.165.0) + aws-sdk-core (~> 3, >= 3.207.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.9.1) + aws-sigv4 (1.10.0) aws-eventstream (~> 1, >= 1.0.2) backport (1.2.0) base64 (0.2.0) @@ -57,10 +57,11 @@ GEM eventmachine (>= 0.12.9) http_parser.rb (~> 0) eventmachine (1.2.7) - faraday (2.10.1) - faraday-net_http (>= 2.0, < 3.2) + faraday (2.12.0) + faraday-net_http (>= 2.0, < 3.4) + json logger - faraday-net_http (3.1.1) + faraday-net_http (3.3.0) net-http faraday-retry (2.2.1) faraday (~> 2.0) @@ -71,12 +72,14 @@ GEM websocket-driver (~> 0.7) ffi (1.17.0) formatador (1.1.0) - git (2.1.1) + git (2.3.0) activesupport (>= 5.0) addressable (~> 2.8) process_executer (~> 1.1) rchardet (~> 1.8) - google-protobuf (3.22.0) + google-protobuf (4.28.2) + bigdecimal + rake (>= 13) guard (2.18.1) formatador (>= 0.2.4) listen (>= 2.7, < 4.0) @@ -93,7 +96,7 @@ GEM guard-compat (~> 1.0) multi_json (~> 1.8) http_parser.rb (0.8.0) - i18n (1.14.5) + i18n (1.14.6) concurrent-ruby (~> 1.0) jaro_winkler (1.6.0) jmespath (1.6.2) @@ -106,14 +109,14 @@ GEM listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - logger (1.6.0) + logger (1.6.1) lumberjack (1.2.10) method_source (1.1.0) mini_magick (5.0.1) mini_portile2 (2.8.7) - minitest (5.25.0) + minitest (5.25.1) multi_json (1.15.0) - mustermann (3.0.2) + mustermann (3.0.3) ruby2_keywords (~> 0.0.1) nenv (0.3.0) net-http (0.4.1) @@ -127,8 +130,8 @@ GEM octokit (9.1.0) faraday (>= 1, < 3) sawyer (~> 0.9) - parallel (1.26.2) - parser (3.3.4.2) + parallel (1.26.3) + parser (3.3.5.0) ast (~> 2.4.1) racc process_executer (1.1.0) @@ -162,26 +165,24 @@ GEM regexp_parser (2.9.2) reverse_markdown (2.1.1) nokogiri - rexml (3.3.5) - strscan - rubocop (1.65.1) + rexml (3.3.7) + rubocop (1.66.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.4, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.31.1, < 2.0) + rubocop-ast (>= 1.32.2, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.32.0) + rubocop-ast (1.32.3) parser (>= 3.3.1.0) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) - sass-embedded (1.62.1) - google-protobuf (~> 3.21) - rake (>= 10.0.0) + sass-embedded (1.79.3) + google-protobuf (~> 4.27) + rake (>= 13) sawyer (0.9.2) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) @@ -210,24 +211,23 @@ GEM thor (~> 1.0) tilt (~> 2.0) yard (~> 0.9, >= 0.9.24) - strscan (3.1.0) thin (1.6.2) daemons (>= 1.0.9) eventmachine (>= 1.0.0) rack (>= 1.0.0) - thor (1.3.1) + thor (1.3.2) tilt (2.4.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) - uri (0.13.0) - webrick (1.8.1) + unicode-display_width (2.6.0) + uri (0.13.1) + webrick (1.8.2) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) webvtt-ruby (0.4.2) - yard (0.9.36) - zeitwerk (2.6.17) + yard (0.9.37) + zeitwerk (2.6.18) PLATFORMS ruby @@ -243,7 +243,6 @@ DEPENDENCIES faraday-retry ferrum git - google-protobuf (= 3.22.0) guard (~> 2, >= 2.16.2) guard-livereload levenshtein-ffi! @@ -264,4 +263,4 @@ DEPENDENCIES zeitwerk (~> 2.3) BUNDLED WITH - 2.5.17 + 2.5.19