ci: run workflows for PRs to any branch #339
Workflow file for this run
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
| --- | |
| # This workflow is intended to work with all our organization Docker projects. A readme named `DOCKER_README.md` | |
| # will be used to update the description on Docker hub. | |
| # custom comments in dockerfiles: | |
| # `# platforms: ` | |
| # Comma separated list of platforms, i.e. `# platforms: linux/386,linux/amd64`. Docker platforms can alternatively | |
| # be listed in a file named `.docker_platforms`. | |
| # `# platforms_pr: ` | |
| # Comma separated list of platforms to run for PR events, i.e. `# platforms_pr: linux/amd64`. This will take | |
| # precedence over the `# platforms: ` directive. | |
| # `# artifacts: ` | |
| # `true` to extract artifacts from the `/artifacts` directory to the GitHub runner. | |
| name: Docker (called) | |
| permissions: | |
| contents: read | |
| on: | |
| pull_request: | |
| workflow_call: | |
| inputs: | |
| maximize_build_space: | |
| description: 'Maximize build space.' | |
| required: false | |
| type: boolean | |
| default: false | |
| publish_release: | |
| required: true | |
| type: string | |
| release_commit: | |
| required: true | |
| type: string | |
| release_tag: | |
| required: true | |
| type: string | |
| release_version: | |
| required: true | |
| type: string | |
| secrets: | |
| DOCKER_HUB_USERNAME: | |
| description: 'Docker Hub username to use for the workflow.' | |
| required: false | |
| DOCKER_HUB_PASSWORD: | |
| description: 'Docker Hub password to use for the workflow.' | |
| required: false | |
| DOCKER_HUB_ACCESS_TOKEN: | |
| description: 'Docker Hub access token to use for the workflow.' | |
| required: false | |
| GH_BOT_NAME: | |
| description: 'GitHub bot name to use for the workflow.' | |
| required: false | |
| GH_BOT_TOKEN: | |
| description: 'GitHub bot token to use for the workflow.' | |
| required: false | |
| GH_TOKEN: | |
| description: 'GitHub token to use for the workflow.' | |
| required: false | |
| jobs: | |
| check_dockerfiles: | |
| name: Check Dockerfiles | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Find dockerfiles | |
| id: find | |
| run: | | |
| dockerfiles=$(find . -type f -iname "Dockerfile" -o -iname "*.dockerfile") | |
| echo "found dockerfiles: ${dockerfiles}" | |
| # shellcheck disable=SC2086 # do not quote to keep this as a single line | |
| echo dockerfiles=${dockerfiles} >> "${GITHUB_OUTPUT}" | |
| MATRIX_COMBINATIONS="" | |
| for FILE in ${dockerfiles}; do | |
| # extract tag from file name | |
| tag=$(echo "${FILE}" | sed -r -z -e 's/(\.\/)*.*\/(Dockerfile)/None/gm') | |
| if [[ "${tag}" == "None" ]]; then | |
| MATRIX_COMBINATIONS="${MATRIX_COMBINATIONS} {\"dockerfile\": \"${FILE}\"}," | |
| else | |
| tag=$(echo "${FILE}" | sed -r -z -e 's/(\.\/)*.*\/(.+)(\.dockerfile)/-\2/gm') | |
| MATRIX_COMBINATIONS="${MATRIX_COMBINATIONS} {\"dockerfile\": \"${FILE}\", \"tag\": \"${tag}\"}," | |
| fi | |
| done | |
| # removes the last character (i.e. comma) | |
| MATRIX_COMBINATIONS=${MATRIX_COMBINATIONS::-1} | |
| # setup matrix for later jobs | |
| matrix=$( ( | |
| echo "{ \"include\": [${MATRIX_COMBINATIONS}] }" | |
| ) | jq -c .) | |
| echo "${matrix}" | |
| echo "${matrix}" | jq . | |
| echo "matrix=${matrix}" >> "${GITHUB_OUTPUT}" | |
| - name: Additional Outputs | |
| id: additional_outputs | |
| run: | | |
| # set outputs for later jobs | |
| REPOSITORY="${{ github.repository }}" | |
| BASE_TAG=$(echo ${REPOSITORY} | tr '[:upper:]' '[:lower:]') | |
| echo "base_tag=${BASE_TAG}" >> "${GITHUB_OUTPUT}" | |
| outputs: | |
| base_tag: ${{ steps.additional_outputs.outputs.base_tag }} | |
| dockerfiles: ${{ steps.find.outputs.dockerfiles }} | |
| matrix: ${{ steps.find.outputs.matrix }} | |
| docker: | |
| name: Docker${{ matrix.tag }} | |
| if: needs.check_dockerfiles.outputs.dockerfiles | |
| needs: | |
| - check_dockerfiles | |
| permissions: | |
| contents: read | |
| packages: write | |
| runs-on: ubuntu-22.04 | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.check_dockerfiles.outputs.matrix) }} | |
| steps: | |
| - name: More space | |
| if: inputs.maximize_build_space | |
| uses: LizardByte/actions/actions/more_space@v2025.1028.23217 | |
| with: | |
| analyze-space-savings: true | |
| clean-all: true | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| - name: Prepare | |
| id: prepare | |
| env: | |
| BRANCH: ${{ github.ref }} | |
| COMMIT: ${{ inputs.release_commit }} | |
| NEW_TAG: ${{ inputs.release_tag }} | |
| shell: bash | |
| run: | | |
| # get variables | |
| branch="${BRANCH:-master}" | |
| commit="${COMMIT:-${{ github.sha }}}" | |
| clone_url="${{ github.event.repository.clone_url }}" | |
| if [ "${{ github.event_name }}" == "push" ]; then | |
| echo "This is a PUSH event" | |
| branch="${{ github.ref_name }}" | |
| fi | |
| # setup the tags | |
| BASE_TAG="${{ needs.check_dockerfiles.outputs.base_tag }}" | |
| TAGS="${BASE_TAG}:${commit:0:7}${{ matrix.tag }},ghcr.io/${BASE_TAG}:${commit:0:7}${{ matrix.tag }}" | |
| if [[ "${branch}" == refs/heads/master ]]; then | |
| TAGS="${TAGS},${BASE_TAG}:latest${{ matrix.tag }},ghcr.io/${BASE_TAG}:latest${{ matrix.tag }}" | |
| TAGS="${TAGS},${BASE_TAG}:master${{ matrix.tag }},ghcr.io/${BASE_TAG}:master${{ matrix.tag }}" | |
| else | |
| TAGS="${TAGS},${BASE_TAG}:test${{ matrix.tag }},ghcr.io/${BASE_TAG}:test${{ matrix.tag }}" | |
| fi | |
| if [[ "${NEW_TAG}" != "" ]]; then | |
| TAGS="${TAGS},${BASE_TAG}:${NEW_TAG}${{ matrix.tag }},ghcr.io/${BASE_TAG}:${NEW_TAG}${{ matrix.tag }}" | |
| fi | |
| # parse custom directives out of dockerfile | |
| # try to get the platforms from the dockerfile custom directive, i.e. `# platforms: xxx,yyy` | |
| # directives for PR event, i.e. not push event | |
| if [ "${{ github.event_name }}" == "pull_request" ]; then | |
| while read -r line; do | |
| if [[ $line == "# platforms_pr: "* && $PLATFORMS == "" ]]; then | |
| # echo the line and use `sed` to remove the custom directive | |
| PLATFORMS=$(echo -e "$line" | sed 's/# platforms_pr: //') | |
| elif [[ $PLATFORMS != "" ]]; then | |
| # break while loop once all custom "PR" event directives are found | |
| break | |
| fi | |
| done <"${{ matrix.dockerfile }}" | |
| fi | |
| # directives for all events... above directives will not be parsed if they were already found | |
| while read -r line; do | |
| if [[ $line == "# platforms: "* && $PLATFORMS == "" ]]; then | |
| # echo the line and use `sed` to remove the custom directive | |
| PLATFORMS=$(echo -e "$line" | sed 's/# platforms: //') | |
| elif [[ $line == "# artifacts: "* && $ARTIFACTS == "" ]]; then | |
| # echo the line and use `sed` to remove the custom directive | |
| ARTIFACTS=$(echo -e "$line" | sed 's/# artifacts: //') | |
| elif [[ $line == "# no-cache-filters: "* && $NO_CACHE_FILTERS == "" ]]; then | |
| # echo the line and use `sed` to remove the custom directive | |
| NO_CACHE_FILTERS=$(echo -e "$line" | sed 's/# no-cache-filters: //') | |
| elif [[ $PLATFORMS != "" && $ARTIFACTS != "" && $NO_CACHE_FILTERS != "" ]]; then | |
| # break while loop once all custom directives are found | |
| break | |
| fi | |
| done <"${{ matrix.dockerfile }}" | |
| # if PLATFORMS is blank, fall back to the legacy method of reading from the `.docker_platforms` file | |
| if [[ $PLATFORMS == "" ]]; then | |
| # read the platforms from `.docker_platforms` | |
| PLATFORMS=$(<.docker_platforms) | |
| fi | |
| # if PLATFORMS is still blank, fall back to `linux/amd64` | |
| if [[ $PLATFORMS == "" ]]; then | |
| PLATFORMS="linux/amd64" | |
| fi | |
| { | |
| echo "branch=${branch}"; | |
| echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')"; | |
| echo "clone_url=${clone_url}"; | |
| echo "artifacts=${ARTIFACTS}"; | |
| echo "no_cache_filters=${NO_CACHE_FILTERS}"; | |
| echo "platforms=${PLATFORMS}"; | |
| echo "tags=${TAGS}"; | |
| } >> "${GITHUB_OUTPUT}" | |
| - name: Set Up QEMU | |
| uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 | |
| - name: Set up Docker Buildx | |
| id: buildx | |
| uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 | |
| - name: Cache Docker Layers | |
| uses: actions/cache@v5 | |
| with: | |
| path: /tmp/.buildx-cache | |
| key: Docker-buildx${{ matrix.tag }}-${{ github.sha }} | |
| restore-keys: | | |
| Docker-buildx${{ matrix.tag }}- | |
| - name: Log in to Docker Hub | |
| if: inputs.publish_release == 'true' # PRs do not have access to secrets | |
| uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| username: ${{ secrets.DOCKER_HUB_USERNAME }} | |
| password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} | |
| - name: Log in to the Container registry | |
| if: inputs.publish_release == 'true' # PRs do not have access to secrets | |
| uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ secrets.GH_BOT_NAME }} | |
| password: ${{ secrets.GH_BOT_TOKEN }} | |
| - name: Add problem matcher | |
| shell: bash | |
| run: | | |
| if [ -f "${{ github.workspace }}/.github/matchers/docker.json" ]; then | |
| echo "::add-matcher::${{ github.workspace }}/.github/matchers/docker.json" | |
| fi | |
| - name: Build and push | |
| id: build | |
| uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 | |
| with: | |
| context: ./ | |
| file: ${{ matrix.dockerfile }} | |
| push: ${{ inputs.publish_release }} | |
| platforms: ${{ steps.prepare.outputs.platforms }} | |
| build-args: | | |
| BRANCH=${{ steps.prepare.outputs.branch }} | |
| BUILD_DATE=${{ steps.prepare.outputs.build_date }} | |
| BUILD_VERSION=${{ inputs.release_version }} | |
| COMMIT=${{ inputs.release_commit }} | |
| CLONE_URL=${{ steps.prepare.outputs.clone_url }} | |
| RELEASE=${{ inputs.publish_release }} | |
| tags: ${{ steps.prepare.outputs.tags }} | |
| cache-from: type=local,src=/tmp/.buildx-cache | |
| cache-to: type=local,dest=/tmp/.buildx-cache | |
| no-cache-filters: ${{ steps.prepare.outputs.no_cache_filters }} | |
| outputs: ${{ steps.prepare.outputs.artifacts == 'true' && 'type=local,dest=image' || '' }} | |
| - name: Arrange Artifacts | |
| if: steps.prepare.outputs.artifacts == 'true' | |
| shell: bash | |
| run: | | |
| # create artifacts directory | |
| mkdir -p artifacts | |
| # artifacts will be in sub directories named after the docker target platform, e.g. `linux_amd64` | |
| # so move files to the artifacts directory | |
| # https://unix.stackexchange.com/a/52816 | |
| echo "::group::Moving artifacts" | |
| find \ | |
| ./image \ | |
| -mindepth 1 \ | |
| -maxdepth 3 \ | |
| -type d \ | |
| -name 'artifacts' \ | |
| -exec bash -c 'cp -rv "$1"/* ./artifacts/' _ {} \; | |
| echo "::endgroup::" | |
| echo "::group::Artifacts" | |
| ls -la ./artifacts/ | |
| echo "::endgroup::" | |
| - name: Upload Artifacts | |
| if: steps.prepare.outputs.artifacts == 'true' | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: build-Docker${{ matrix.tag }} | |
| path: artifacts/ | |
| if-no-files-found: error | |
| release: | |
| name: Release | |
| if: > | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/master' | |
| runs-on: ubuntu-latest | |
| needs: | |
| - check_dockerfiles | |
| - docker | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| DOCKER_README.md | |
| sparse-checkout-cone-mode: false | |
| - name: Update Docker Hub Description | |
| uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0 | |
| with: | |
| username: ${{ secrets.DOCKER_HUB_USERNAME }} | |
| password: ${{ secrets.DOCKER_HUB_PASSWORD }} # token is not currently supported | |
| repository: ${{ needs.check_dockerfiles.outputs.base_tag }} | |
| short-description: ${{ github.event.repository.description }} | |
| readme-filepath: ./DOCKER_README.md |