GitHub CI #1146
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: GitHub CI | |
| on: | |
| pull_request: | |
| push: | |
| schedule: | |
| - cron: '0 0 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Versions to build and push, space-separated (ex: "9.0.2" or "9.0.2 8.1.5" or unstable)' | |
| required: true | |
| type: string | |
| env: | |
| PUBLISH_DOCKERHUB: ${{ secrets.DOCKERHUB_USERNAME != '' && secrets.DOCKERHUB_TOKEN != '' && github.ref == 'refs/heads/mainline' }} | |
| PUBLISH_GHCR: ${{ github.repository == 'valkey-io/valkey-container' && github.ref == 'refs/heads/mainline' }} | |
| PUBLISH_ECR: ${{ secrets.AWS_ROLE_TO_ASSUME != '' && github.ref == 'refs/heads/mainline' }} | |
| defaults: | |
| run: | |
| shell: 'bash -Eeuo pipefail -x {0}' | |
| jobs: | |
| generate-jobs: | |
| name: Generate Jobs | |
| runs-on: ubuntu-latest | |
| outputs: | |
| test_strategy: ${{ steps.generate-jobs.outputs.test_strategy }} | |
| publish_strategy: ${{ steps.generate-jobs.outputs.publish_strategy }} | |
| publish_dockerhub: ${{ steps.check-secrets.outputs.publish_dockerhub }} | |
| publish_ghcr: ${{ steps.check-secrets.outputs.publish_ghcr }} | |
| publish_ecr: ${{ steps.check-secrets.outputs.publish_ecr }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 2 | |
| - uses: docker-library/bashbrew@9eef708e6a0b1b5d8bbda769c766777fe45026eb # v0.1.13 | |
| - id: check-secrets | |
| name: Output publish flags for downstream jobs | |
| run: | | |
| echo "publish_dockerhub=$PUBLISH_DOCKERHUB" >> "$GITHUB_OUTPUT" | |
| echo "publish_ghcr=$PUBLISH_GHCR" >> "$GITHUB_OUTPUT" | |
| echo "publish_ecr=$PUBLISH_ECR" >> "$GITHUB_OUTPUT" | |
| - id: generate-jobs | |
| name: Generate Jobs | |
| run: | | |
| # Generate full strategy for testing all versions | |
| test_strategy="$("$BASHBREW_SCRIPTS/github-actions/generate.sh")" | |
| # Start with the full strategy for publish | |
| publish_strategy="$test_strategy" | |
| # If triggered by a cron event, filter publish_strategy to include `unstable` and `unstable-alpine` | |
| if [[ "${{ github.event_name }}" == "schedule" ]]; then | |
| publish_strategy=$(jq -c '{"fail-fast": .["fail-fast"],"matrix":{"include":[ .matrix.include[]|select(.name =="unstable" or .name== "unstable-alpine")]}}' <<<"$publish_strategy") | |
| elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| # If triggered by a workflow dispatch, build only the specified version(s) | |
| # Space-separated version (e.g. "9.0.2 8.1.5 unstable") | |
| version_input="${{ github.event.inputs.version }}" | |
| version_pattern=$(echo "$version_input" | xargs | tr ' ' '|') | |
| publish_strategy=$(jq -c --arg version "$version_pattern" '{"fail-fast": .["fail-fast"],"matrix":{"include":[ .matrix.include[]|select(.name | test($version))]}}' <<<"$publish_strategy") | |
| elif [[ ("${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/mainline") || ("${{ github.event_name }}" == "pull_request" && "${{ github.base_ref }}" == "mainline") ]]; then | |
| # For pushes to mainline or PRs targeting mainline, only build changed versions | |
| if [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
| # For PRs, compare against the merge base | |
| git fetch origin ${{ github.base_ref }} | |
| changed_files=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) | |
| else | |
| changed_files=$(git diff --name-only HEAD~1 HEAD) | |
| fi | |
| if printf "%s\n" "$changed_files" | grep -qE "^(versions\.json|[0-9]+\.[0-9]+/|unstable/)"; then | |
| changed_versions=$(echo $changed_files | grep -oE "[0-9]+\.[0-9]+|unstable" | sort -u | tr '\n' '|' | sed 's/|$//') | |
| if [[ -n "$changed_versions" ]]; then | |
| publish_strategy=$(jq -c --arg versions "$changed_versions" '{"fail-fast": .["fail-fast"],"matrix":{"include":[ .matrix.include[]|select(.meta.entries[0].directory | test($versions))]}}' <<<"$publish_strategy") | |
| fi | |
| else | |
| publish_strategy='{"fail-fast": false, "matrix": {"include": []}}' | |
| fi | |
| fi | |
| echo "test_strategy=$test_strategy" >> "$GITHUB_OUTPUT" | |
| echo "publish_strategy=$publish_strategy" >> "$GITHUB_OUTPUT" | |
| echo "Test Strategy:" | |
| jq . <<<"$test_strategy" | |
| echo "Publish Strategy:" | |
| jq . <<<"$publish_strategy" # sanity check / debugging aid | |
| test: | |
| needs: generate-jobs | |
| strategy: ${{ fromJson(needs.generate-jobs.outputs.test_strategy) }} | |
| name: ${{ matrix.name }} - test | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Prepare Environment | |
| run: ${{ matrix.runs.prepare }} | |
| - name: Pull Dependencies | |
| run: ${{ matrix.runs.pull }} | |
| - name: Build ${{ matrix.name }} | |
| run: ${{ matrix.runs.build }} | |
| - name: History ${{ matrix.name }} | |
| run: ${{ matrix.runs.history }} | |
| - name: Test ${{ matrix.name }} | |
| run: ${{ matrix.runs.test }} | |
| - name: '"docker images"' | |
| run: ${{ matrix.runs.images }} | |
| build_and_push: | |
| if: | | |
| ((github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && | |
| github.ref == 'refs/heads/mainline' && | |
| fromJson(needs.generate-jobs.outputs.publish_strategy).matrix.include[0] && | |
| (needs.generate-jobs.outputs.publish_dockerhub == 'true' || needs.generate-jobs.outputs.publish_ghcr == 'true' || needs.generate-jobs.outputs.publish_ecr == 'true')) | |
| needs: | |
| - generate-jobs | |
| - test | |
| strategy: ${{ fromJson(needs.generate-jobs.outputs.publish_strategy) }} | |
| name: ${{ matrix.name }} - Build and push | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| id-token: write | |
| contents: read | |
| packages: write | |
| steps: | |
| # Tags are created by generate.sh in the format `valkey-container:<tag>` | |
| # For Docker Hub this step modifies the tags to `account/valkey:<tag>` to be provided to build-push github action. | |
| # For GitHub Container Registry this step modifies the tags to `ghcr.io/<repo-owner>/valkey:<tag>` to be provided to build-push github action. | |
| - name: Modify Tags | |
| id: modify_tags | |
| run: | | |
| original_tags="${{ toJson(matrix.meta.entries[0].tags) }}" | |
| all_tags="" | |
| if [[ "$PUBLISH_DOCKERHUB" == "true" ]]; then | |
| docker_hub_tags=$(echo $original_tags | sed 's/valkey-container/${{ secrets.DOCKERHUB_ACCOUNT }}\/valkey/g'| sed 's/\[ *//; s/ *\]//; s/ //g') | |
| all_tags="$docker_hub_tags" | |
| fi | |
| if [[ "$PUBLISH_GHCR" == "true" ]]; then | |
| ghcr_tags=$(echo $original_tags | sed 's/valkey-container/ghcr.io\/${{ github.repository_owner }}\/valkey/g'| sed 's/\[ *//; s/ *\]//; s/ //g') | |
| all_tags="${all_tags:+$all_tags,}$ghcr_tags" | |
| fi | |
| if [[ "$PUBLISH_ECR" == "true" ]]; then | |
| ecr_tags=$(echo $original_tags | sed 's/valkey-container/public.ecr.aws\/${{ secrets.ECR_REGISTRY_ALIAS }}\/valkey/g'| sed 's/\[ *//; s/ *\]//; s/ //g') | |
| all_tags="${all_tags:+$all_tags,}$ecr_tags" | |
| fi | |
| echo "tags=$all_tags" >> $GITHUB_OUTPUT | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| - name: Login to Docker Hub | |
| if: env.PUBLISH_DOCKERHUB == 'true' | |
| uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 | |
| with: | |
| registry: docker.io | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Login to GitHub Container Registry | |
| if: env.PUBLISH_GHCR == 'true' | |
| uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ github.token }} | |
| - name: Configure AWS credentials via OIDC | |
| if: env.PUBLISH_ECR == 'true' | |
| uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 | |
| with: | |
| role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} | |
| aws-region: us-east-1 | |
| - name: Login to Amazon ECR Public Gallery | |
| if: env.PUBLISH_ECR == 'true' | |
| run: | | |
| aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws | |
| - name: Build and push | |
| uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 | |
| with: | |
| file: ./${{ matrix.meta.entries[0].directory }}/Dockerfile | |
| push: ${{ env.PUBLISH_DOCKERHUB == 'true' || env.PUBLISH_GHCR == 'true' || env.PUBLISH_ECR == 'true' }} | |
| tags: ${{ steps.modify_tags.outputs.tags }} | |
| platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le | |
| provenance: false | |
| load: false | |
| update-dockerhub-ecr-description-file: | |
| if: | | |
| (github.event_name == 'push' && | |
| github.ref == 'refs/heads/mainline' && | |
| fromJson(needs.generate-jobs.outputs.publish_strategy).matrix.include[0]) | |
| needs: | |
| - generate-jobs | |
| - test | |
| - build_and_push | |
| name: Update Description File | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Update Description File | |
| run: | | |
| echo '${{ needs.generate-jobs.outputs.test_strategy }}' > bashbrew_output.json | |
| python generate-repo-description.py bashbrew_output.json description-template.md | |
| for file in dockerhub-description.md ecr-about.md ecr-usage.md; do | |
| if [ ! -f "$file" ]; then | |
| echo "Error: $file was not created!" | |
| exit 1 | |
| fi | |
| echo "$file exists" | |
| done | |
| - name: Upload description files | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: description-files | |
| path: | | |
| dockerhub-description.md | |
| ecr-about.md | |
| ecr-usage.md | |
| update-descriptions: | |
| if: | | |
| (github.event_name == 'push' && | |
| github.ref == 'refs/heads/mainline' && | |
| fromJson(needs.generate-jobs.outputs.publish_strategy).matrix.include[0] && | |
| (needs.generate-jobs.outputs.publish_dockerhub == 'true' || needs.generate-jobs.outputs.publish_ecr == 'true')) | |
| needs: | |
| - update-dockerhub-ecr-description-file | |
| - generate-jobs | |
| - test | |
| - build_and_push | |
| name: Update Descriptions | |
| permissions: | |
| id-token: write | |
| contents: read | |
| uses: ./.github/workflows/update-descriptions.yml | |
| secrets: | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| DOCKERHUB_REPOSITORY: ${{ secrets.DOCKERHUB_REPOSITORY }} | |
| AWS_ROLE_TO_ASSUME: ${{ secrets.AWS_ROLE_TO_ASSUME }} | |
| ECR_REPOSITORY_NAME: ${{ secrets.ECR_REPOSITORY_NAME }} |