Skip to content

syncstorage-rs-mysql #106

syncstorage-rs-mysql

syncstorage-rs-mysql #106

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 }}