--- name: Docker Build and Push Image on: # we want pull requests so we can build(test) but not push to image registry pull_request: branches: - 'main' # only build when important files change paths-ignore: - 'README.md' - '.github/workflows/linter.yml' - '.github/linters/**' push: branches: - 'main' # only build when important files change paths-ignore: - 'README.md' - '.github/workflows/linter.yml' - '.github/linters/**' schedule: # re-run monthly to keep image fresh with upstream base images # NOTE: GH will stop cron jobs in a stale repo (60 days) # https://docs.github.com/en/actions/managing-workflow-runs/disabling-and-enabling-a-workflow - cron: '0 12 15 * *' # run whenever we want! # workflow_dispatch: # REUSABLE WORKFLOW with INPUTS # to keep this workflow simple, assumptions are made: # - only able to push to Docker Hub and or GHCR # - Image name is name of GitHub repo # - Dockerfile is in root of repo, named 'Dockerfile' # - Builds on PR with tag of `prNUMBER` (same tag each PR push) # - Builds on push to main branch with tag of `latest` # ???? what else workflow_call: # allow reuse of this workflow in other repos inputs: # TODO: allow dynamic docker hub and ghcr dockerhub-enabled: description: Push images to Docker Hub type: boolean ghcr-enabled: dockerhub-username: description: Docker Hub username required: false type: string context: description: Docker context (path) to start build from required: false type: string default: . target: description: Build stage to target required: false type: string platforms: description: Platforms to build for required: false type: string # common ones: linux/amd64,linux/arm64,linux/arm/v7 default: linux/amd64 # TODO: does this work in calling repos? image-names: description: A list of the account/repo names for docker build required: false type: string # the default will tag it same as repo name (for hub.docker.com) and # ghcr.io/ default: | ${{ github.repository }} ghcr.io/${{ github.repository }} secrets: dockerhub-token: description: Docker Hub token required: false jobs: build-and-push-image: name: Build+Push runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - # we need qemu and buildx so we can build multiple platforms later name: Set up QEMU id: qemu uses: docker/setup-qemu-action@v1.2.0 - # BuildKit (used with `docker buildx`) is the best way to build images name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v1 - name: Login to DockerHub if: ${{ inputs.dockerhub-enabled }} uses: docker/login-action@v1 with: username: ${{ inputs.dockerhub-username }} password: ${{ secrets.dockerhub-token }} - name: Login to GHCR if: ${{ inputs.ghcr-enabled }} uses: docker/login-action@v1 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Docker meta id: docker_meta uses: docker/metadata-action@v3.6.2 with: # list of Docker images to use as base name for tags images: ${{ inputs.image-names }} flavor: | latest=false tags: | type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }} type=ref,event=pr,prefix=pr - # this will build the images, once per platform, # then push to both Docker Hub and GHCR name: Docker Build and Push id: docker_build_and_push uses: docker/build-push-action@v2 with: platforms: ${{ inputs.platforms }} context: ${{ inputs.context }} target: ${{ inputs.target }} builder: ${{ steps.buildx.outputs.name }} # it uses github cache API for faster builds: # https://github.com/crazy-max/docker-build-push-action/blob/master/docs/advanced/cache.md#cache-backend-api cache-from: type=gha cache-to: type=gha,mode=max # for an approved pull_request, only push pr-specific tags push: true tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} - name: Show image digest run: echo ${{ steps.docker_build_and_push.outputs.digest }}