syncstorage-rs-mysql #106
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: syncstorage-rs-mysql | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: '15 6 * * 1' # Run every Monday at 06:15 UTC | |
| # - cron: '*/7 * * * *' # Test | |
| push: | |
| branches: | |
| - main | |
| - '**' | |
| paths-ignore: | |
| - '**/README.md' | |
| env: | |
| # repository variables | |
| REPOSITORY_REGISTRY: ghcr.io | |
| REPOSITORY_FULL_NAME: ${{ github.repository }} | |
| REPOSITORY_MAIN_BRANCH: main | |
| # service variables | |
| SERVICE_NAME: syncstorage-rs | |
| SERVICE_REPOSITORY_SERVER: github.com | |
| SERVICE_REPOSITORY_NAME: mozilla-services/syncstorage-rs | |
| SERVICE_CHANGELOG_PATH: CHANGELOG.md | |
| # specific for this component | |
| IMAGE_TAGS: mysql | |
| DATABASE_BACKEND: mysql | |
| jobs: | |
| ## Set common libraries ## | |
| prepare-env: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| github_release: ${{ steps.set-version-suffix-and-release-strategy.outputs.github_release }} | |
| service_tag: ${{ steps.get-service-latest-tag.outputs.service_tag }} | |
| internal_commit_head: ${{ steps.find-code.outputs.internal_commit_head }} | |
| build_date: ${{ steps.build_date.outputs.build_date }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Find local code to build | |
| id: find-code | |
| uses: ./.github/actions/find-head | |
| with: | |
| event_name: ${{ github.event_name }} | |
| repository_main_branch: ${{ env.REPOSITORY_MAIN_BRANCH }} | |
| - name: Decide release strategy | |
| id: set-version-suffix-and-release-strategy | |
| # <GIT_BRANCH> , <GIT_TAG> on head, github release | |
| # main , yes , yes | |
| # non-main-branch, yes , no | |
| # any-branch , no , no | |
| run: | | |
| if [[ "${{ steps.find-code.outputs.internal_commit_branch_name }}" == ${{ env.REPOSITORY_MAIN_BRANCH }} ]] && [[ "${{ steps.find-code.outputs.internal_commit_tag }}" != "" ]]; then | |
| echo 'github_release=true' >> ${GITHUB_OUTPUT} | |
| else | |
| echo 'github_release=false' >> ${GITHUB_OUTPUT} | |
| fi | |
| - name: Fetch latest tags from service repository | |
| id: get-service-latest-tag | |
| run: | | |
| latest_tag=$(git ls-remote --tags "https://${{ env.SERVICE_REPOSITORY_SERVER }}/${{ env.SERVICE_REPOSITORY_NAME }}" | grep -v '\^{}' | awk -F/ '{print $NF}' | sort -V | tail -n1) | |
| echo "Latest tag for this service: ${latest_tag}" | |
| echo "service_tag=${latest_tag}" >> ${GITHUB_OUTPUT} | |
| - name: Set current date as env variable | |
| id: build_date | |
| run: echo "build_date=$(date +'%Y%m%dT%H%M%S')" >> ${GITHUB_OUTPUT} | |
| # Remove old build cache ## | |
| cleanup-registry: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: Clean all build cache if there is a push | |
| if: github.event_name == 'push' | |
| uses: dataaxiom/ghcr-cleanup-action@v1 | |
| with: | |
| dry-run: false | |
| use-regex: true | |
| delete-tags: buildcache-* | |
| - name: Clean old build cache | |
| if: github.event_name == 'schedule' | |
| uses: dataaxiom/ghcr-cleanup-action@v1 | |
| with: | |
| dry-run: false | |
| older-than: 6 days | |
| use-regex: true | |
| delete-tags: buildcache-* | |
| ## Build containers for all platforms ## | |
| build-and-push-containers: | |
| needs: | |
| - prepare-env | |
| - cleanup-registry | |
| permissions: | |
| contents: write | |
| packages: write | |
| strategy: | |
| matrix: | |
| config: | |
| - docker_architecture: amd64 | |
| github_runner_image: ubuntu-latest | |
| image_type: app | |
| - docker_architecture: amd64 | |
| github_runner_image: ubuntu-latest | |
| image_type: init | |
| - docker_architecture: arm64 | |
| github_runner_image: ubuntu-24.04-arm | |
| image_type: app | |
| - docker_architecture: arm64 | |
| github_runner_image: ubuntu-24.04-arm | |
| image_type: init | |
| runs-on: ${{ matrix.config.github_runner_image }} | |
| steps: | |
| - name: Prepare variables | |
| id: prepare-variables | |
| run: | | |
| # setting docker and github variables | |
| case ${{ matrix.config.docker_architecture }} in | |
| amd64) | |
| echo docker_architecture='amd64' >> ${GITHUB_OUTPUT} | |
| echo docker_target='linux/amd64' >> ${GITHUB_OUTPUT} | |
| ;; | |
| arm64) | |
| echo docker_architecture='arm64' >> ${GITHUB_OUTPUT} | |
| echo docker_target='linux/arm64' >> ${GITHUB_OUTPUT} | |
| ;; | |
| *) | |
| echo "Unknown architecture" | |
| exit 1 | |
| ;; | |
| esac | |
| # setting image-specific paths | |
| case ${{ matrix.config.image_type }} in | |
| app) | |
| echo code_repository="${{ env.SERVICE_REPOSITORY_NAME }}" >> ${GITHUB_OUTPUT} | |
| echo code_dockerfile_path='./' >> ${GITHUB_OUTPUT} | |
| echo code_commit_head="${{ needs.prepare-env.outputs.service_tag }}" >> ${GITHUB_OUTPUT} | |
| ;; | |
| *) | |
| echo code_repository="${{ env.REPOSITORY_FULL_NAME }}" >> ${GITHUB_OUTPUT} | |
| echo code_dockerfile_path="./${{ env.SERVICE_NAME }}-${{ matrix.config.image_type }}/" >> ${GITHUB_OUTPUT} | |
| echo code_commit_head="${{ needs.prepare-env.outputs.internal_commit_head }}" >> ${GITHUB_OUTPUT} | |
| ;; | |
| esac | |
| - name: Prepare platform pair | |
| id: prepare-platform-pair | |
| run: | | |
| platform=${{ steps.prepare-variables.outputs.docker_target }} | |
| echo "platform_pair=${platform//\//-}" >> ${GITHUB_OUTPUT} | |
| - name: Checkout workflows | |
| uses: actions/checkout@v4 | |
| with: | |
| path: workflows | |
| - name: Prepare image name | |
| id: image_name | |
| uses: ./workflows/.github/actions/image-name-suffix | |
| with: | |
| image_type: ${{ matrix.config.image_type }} | |
| image_tags: ${{ env.IMAGE_TAGS }} | |
| # service_tag: ${{ needs.prepare-env.outputs.service_tag }} | |
| # platform_pair: ${{ steps.prepare-platform-pair.outputs.platform_pair }} | |
| - name: Clean workflows | |
| run: | | |
| rm -Rf ./workflows | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.prepare-variables.outputs.code_commit_head }} | |
| repository: ${{ steps.prepare-variables.outputs.code_repository }} | |
| - name: Docker meta | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: | | |
| ${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }} | |
| tags: | | |
| type=pep440,pattern={{version}},value=${{ needs.prepare-env.outputs.service_tag }} | |
| flavor: | | |
| latest=false | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REPOSITORY_REGISTRY }} | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| ############################################################################################################################# | |
| ## non-amd64 is not natively supported in syncstorage-rs, see https://github.com/mozilla-services/syncstorage-rs/pull/1635 ## | |
| ############################################################################################################################# | |
| - name: Replace MySQL client with MariaDB client where architecture is not supported | |
| if: steps.prepare-variables.outputs.code_repository == 'mozilla-services/syncstorage-rs' && steps.prepare-variables.outputs.docker_architecture != 'amd64' | |
| run: | | |
| sed -i 's/libmysqlclient-dev/libmariadb-dev-compat libmariadb-dev/g' "./Dockerfile" | |
| - name: Build and push | |
| id: build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| platforms: ${{ steps.prepare-variables.outputs.docker_target }} | |
| tags: | | |
| ${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}:${{ env.SERVICE_NAME }}-${{ steps.image_name.outputs.docker_image_name_suffix }}-${{ needs.prepare-env.outputs.service_tag }}-${{ needs.prepare-env.outputs.build_date }}-${{ steps.prepare-platform-pair.outputs.platform_pair }}, | |
| ${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}:${{ env.SERVICE_NAME }}-${{ steps.image_name.outputs.docker_image_name_suffix }}-${{ needs.prepare-env.outputs.service_tag }}-${{ steps.prepare-platform-pair.outputs.platform_pair }}, | |
| ${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}:${{ env.SERVICE_NAME }}-${{ steps.image_name.outputs.docker_image_name_suffix }}-${{ steps.prepare-platform-pair.outputs.platform_pair }}-latest | |
| labels: ${{ steps.meta.outputs.labels }} | |
| outputs: type=image,"name=${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}",name-canonical=true,push=true | |
| context: ${{ steps.prepare-variables.outputs.code_dockerfile_path }} | |
| build-args: | | |
| DATABASE_BACKEND=${{ env.DATABASE_BACKEND }} | |
| cache-from: type=registry,ref=${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}:buildcache-${{ env.SERVICE_NAME }}-${{ steps.image_name.outputs.docker_image_name_suffix }}-${{ needs.prepare-env.outputs.service_tag }}-${{ steps.prepare-platform-pair.outputs.platform_pair }} | |
| cache-to: type=registry,ref=${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}:buildcache-${{ env.SERVICE_NAME }}-${{ steps.image_name.outputs.docker_image_name_suffix }}-${{ needs.prepare-env.outputs.service_tag }}-${{ steps.prepare-platform-pair.outputs.platform_pair }},mode=max | |
| - name: Export digest | |
| run: | | |
| mkdir -p ${{ runner.temp }}/digests | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "${{ runner.temp }}/digests/${digest#sha256:}" | |
| - name: Upload digest | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.config.image_type }}-${{ steps.prepare-platform-pair.outputs.platform_pair }} | |
| path: ${{ runner.temp }}/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| ## Collect digests from previus builds and create a single manifest ## | |
| build-and-push-manifests: | |
| needs: | |
| - prepare-env | |
| - build-and-push-containers | |
| permissions: | |
| contents: write | |
| packages: write | |
| strategy: | |
| matrix: | |
| image_type: [app, init] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout workflows | |
| uses: actions/checkout@v4 | |
| with: | |
| path: workflows | |
| - name: Prepare image name | |
| id: image_name | |
| uses: ./workflows/.github/actions/image-name-suffix | |
| with: | |
| image_type: ${{ matrix.image_type }} | |
| image_tags: ${{ env.IMAGE_TAGS }} | |
| - name: Clean workflows | |
| run: | | |
| rm -Rf ./workflows | |
| - name: Download digests | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ${{ runner.temp }}/digests | |
| pattern: ${{ matrix.image_type }}-* | |
| merge-multiple: true | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REPOSITORY_REGISTRY }} | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Docker tags | |
| id: docker_tags | |
| run: | | |
| prefix="${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}:${{ env.SERVICE_NAME }}-${{ steps.image_name.outputs.docker_image_name_suffix }}" | |
| echo "docker_tags={ \"tags\": [ \"${prefix}-${{ needs.prepare-env.outputs.service_tag }}-${{ needs.prepare-env.outputs.build_date }}\", \"${prefix}-${{ needs.prepare-env.outputs.service_tag }}\", \"${prefix}-latest\" ] }" >> ${GITHUB_OUTPUT} | |
| - name: Create manifest list and push | |
| working-directory: ${{ runner.temp }}/digests | |
| run: | | |
| docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.docker_tags.outputs.docker_tags }}') \ | |
| $(printf '${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}@sha256:%s ' *) | |
| - name: Inspect image | |
| run: | | |
| docker buildx imagetools inspect ${{ env.REPOSITORY_REGISTRY }}/${{ env.REPOSITORY_FULL_NAME }}:${{ env.SERVICE_NAME }}-${{ steps.image_name.outputs.docker_image_name_suffix }}-latest | |
| ## Prepare GitHub release ## | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| needs: | |
| - prepare-env | |
| - build-and-push-containers | |
| - build-and-push-manifests | |
| permissions: | |
| contents: write | |
| packages: write | |
| steps: | |
| - name: Checkout workflows | |
| uses: actions/checkout@v4 | |
| with: | |
| path: workflows | |
| - name: Prepare image name | |
| id: image_name | |
| uses: ./workflows/.github/actions/image-name-suffix | |
| with: | |
| image_type: 'app' | |
| image_tags: ${{ env.IMAGE_TAGS }} | |
| service_tag: ${{ needs.prepare-env.outputs.service_tag }} | |
| - name: Clean workflows | |
| run: | | |
| rm -Rf ./workflows | |
| - name: Get changelog from service | |
| if: needs.prepare-env.outputs.github_release == 'true' | |
| run: | | |
| mkdir -p mozilla-services/${{ env.SERVICE_NAME }} | |
| curl -H 'Accept: application/vnd.github.v3.raw' -L -s https://github.com/mozilla-services/syncstorage-rs/raw/refs/tags/${{ needs.prepare-env.outputs.service_tag }}/CHANGELOG.md -o mozilla-services/${{ env.SERVICE_NAME }}/${{ env.SERVICE_CHANGELOG_PATH }} | |
| - name: Prepare changelog | |
| if: needs.prepare-env.outputs.github_release == 'true' | |
| run: | | |
| sed -i -n '/<a name="${{ needs.prepare-env.outputs.service_tag }}"/,/^<a name=/ {/^<a name=/!p; /^<a name="${{ needs.prepare-env.outputs.service_tag }}"/p}' "./mozilla-services/${{ env.SERVICE_NAME }}/${{ env.SERVICE_CHANGELOG_PATH }}" | |
| sed "2s/$/ - Built on ${{ needs.prepare-env.outputs.build_date }}/" -i "./mozilla-services/${{ env.SERVICE_NAME }}/${{ env.SERVICE_CHANGELOG_PATH }}" | |
| - name: Create Release | |
| if: needs.prepare-env.outputs.github_release == 'true' | |
| uses: ncipollo/release-action@v1 | |
| with: | |
| name: ${{ env.SERVICE_NAME }} | |
| tag: ${{ env.SERVICE_NAME }}-${{ steps.image_name.outputs.docker_image_name_suffix }}-${{ needs.prepare-env.outputs.build_date }} | |
| bodyFile: ./mozilla-services/${{ env.SERVICE_NAME }}/${{ env.SERVICE_CHANGELOG_PATH }} |