213 lines
8.8 KiB
YAML
213 lines
8.8 KiB
YAML
# This workflow automates the building and pushing of Docker images based on user-defined inputs. It includes:
|
|
# - Accepting various inputs like image name, Dockerfile path, target, and additional Rust-related parameters.
|
|
# - Authenticates with Google Cloud and logs into Google Artifact Registry and DockerHub.
|
|
# - Uses Docker Buildx for improved build performance and caching.
|
|
# - Builds the Docker image and pushes it to both Google Artifact Registry and potentially DockerHub, depending on release type.
|
|
# - Manages caching strategies to optimize build times across different branches.
|
|
# - Uses Docker Scout to display vulnerabilities and recommendations for the latest built image.
|
|
name: Build docker image
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
image_name:
|
|
required: true
|
|
type: string
|
|
dockerfile_path:
|
|
required: true
|
|
type: string
|
|
dockerfile_target:
|
|
required: true
|
|
type: string
|
|
short_sha:
|
|
required: false
|
|
type: string
|
|
rust_backtrace:
|
|
required: false
|
|
type: string
|
|
rust_lib_backtrace:
|
|
required: false
|
|
type: string
|
|
# defaults to: vars.RUST_LOG
|
|
rust_log:
|
|
required: false
|
|
type: string
|
|
# defaults to: vars.RUST_PROD_FEATURES
|
|
features:
|
|
required: false
|
|
type: string
|
|
# defaults to: vars.RUST_TEST_FEATURES (and entrypoint.sh adds vars.RUST_PROD_FEATURES)
|
|
test_features:
|
|
required: false
|
|
type: string
|
|
latest_tag:
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
tag_suffix:
|
|
required: false
|
|
type: string
|
|
no_cache:
|
|
description: 'Disable the Docker cache for this build'
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
|
|
outputs:
|
|
image_digest:
|
|
description: 'The image digest to be used on a caller workflow'
|
|
value: ${{ jobs.build.outputs.image_digest }}
|
|
|
|
|
|
env:
|
|
FEATURES: ${{ inputs.features || vars.RUST_PROD_FEATURES }}
|
|
TEST_FEATURES: ${{ inputs.test_features || vars.RUST_TEST_FEATURES }}
|
|
RUST_LOG: ${{ inputs.rust_log || vars.RUST_LOG }}
|
|
CARGO_INCREMENTAL: ${{ vars.CARGO_INCREMENTAL }}
|
|
|
|
jobs:
|
|
build:
|
|
name: Build images
|
|
timeout-minutes: 210
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
image_digest: ${{ steps.docker_build.outputs.digest }}
|
|
image_name: ${{ fromJSON(steps.docker_build.outputs.metadata)['image.name'] }}
|
|
permissions:
|
|
contents: 'read'
|
|
id-token: 'write'
|
|
pull-requests: write # for `docker-scout` to be able to write the comment
|
|
env:
|
|
DOCKER_BUILD_SUMMARY: ${{ vars.DOCKER_BUILD_SUMMARY }}
|
|
steps:
|
|
- uses: actions/checkout@v4.2.1
|
|
with:
|
|
persist-credentials: false
|
|
- uses: r7kamura/rust-problem-matchers@v1.5.0
|
|
|
|
- name: Inject slug/short variables
|
|
uses: rlespinasse/github-slug-action@v4
|
|
with:
|
|
short-length: 7
|
|
|
|
# Automatic tag management and OCI Image Format Specification for labels
|
|
- name: Docker meta
|
|
id: meta
|
|
uses: docker/metadata-action@v5.5.1
|
|
with:
|
|
# list of Docker images to use as base name for tags
|
|
# We only publish images to DockerHub if a release is not a pre-release
|
|
# Ref: https://github.com/orgs/community/discussions/26281#discussioncomment-3251177
|
|
images: |
|
|
us-docker.pkg.dev/${{ vars.GCP_PROJECT }}/zebra/${{ inputs.image_name }}
|
|
zfnd/${{ inputs.image_name }},enable=${{ github.event_name == 'release' && !github.event.release.prerelease }}
|
|
# appends inputs.tag_suffix to image tags/names
|
|
flavor: |
|
|
suffix=${{ inputs.tag_suffix }}
|
|
latest=${{ inputs.latest_tag }}
|
|
# generate Docker tags based on the following events/attributes
|
|
tags: |
|
|
# These DockerHub release tags support the following use cases:
|
|
# - `latest`: always use the latest Zebra release when you pull or update
|
|
# - `v1.x.y` or `1.x.y`: always use the exact version, don't automatically upgrade
|
|
#
|
|
# `semver` adds a "latest" tag if `inputs.latest_tag` is `true`.
|
|
type=semver,pattern={{version}}
|
|
type=ref,event=tag
|
|
# DockerHub release and CI tags.
|
|
# This tag makes sure tests are using exactly the right image, even when multiple PRs run at the same time.
|
|
type=sha,event=push
|
|
# These CI-only tags support CI on PRs, the main branch, and scheduled full syncs.
|
|
# These tags do not appear on DockerHub, because DockerHub images are only published on the release event.
|
|
type=ref,event=pr
|
|
type=ref,event=branch
|
|
type=edge,enable={{is_default_branch}}
|
|
type=schedule
|
|
|
|
- name: Authenticate to Google Cloud
|
|
id: auth
|
|
uses: google-github-actions/auth@v2.1.6
|
|
with:
|
|
workload_identity_provider: '${{ vars.GCP_WIF }}'
|
|
service_account: '${{ vars.GCP_ARTIFACTS_SA }}'
|
|
token_format: 'access_token'
|
|
# Some builds might take over an hour, and Google's default lifetime duration for
|
|
# an access token is 1 hour (3600s). We increase this to 3 hours (10800s)
|
|
# as some builds take over an hour.
|
|
access_token_lifetime: 10800s
|
|
|
|
- name: Login to Google Artifact Registry
|
|
uses: docker/login-action@v3.3.0
|
|
with:
|
|
registry: us-docker.pkg.dev
|
|
username: oauth2accesstoken
|
|
password: ${{ steps.auth.outputs.access_token }}
|
|
|
|
- name: Login to DockerHub
|
|
uses: docker/login-action@v3.3.0
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
# Setup Docker Buildx to use Docker Build Cloud
|
|
- name: Set up Docker Buildx
|
|
id: buildx
|
|
uses: docker/setup-buildx-action@v3.7.1
|
|
with:
|
|
version: "lab:latest"
|
|
driver: cloud
|
|
endpoint: "zfnd/zebra"
|
|
|
|
# Build and push image to Google Artifact Registry, and possibly DockerHub
|
|
- name: Build & push
|
|
id: docker_build
|
|
uses: docker/build-push-action@v6.9.0
|
|
with:
|
|
target: ${{ inputs.dockerfile_target }}
|
|
context: .
|
|
file: ${{ inputs.dockerfile_path }}
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
build-args: |
|
|
SHORT_SHA=${{ env.GITHUB_SHA_SHORT }}
|
|
RUST_LOG=${{ env.RUST_LOG }}
|
|
FEATURES=${{ env.FEATURES }}
|
|
TEST_FEATURES=${{ env.TEST_FEATURES }}
|
|
push: true
|
|
# It's recommended to build images with max-level provenance attestations
|
|
# https://docs.docker.com/build/ci/github-actions/attestations/
|
|
provenance: mode=max
|
|
sbom: true
|
|
# Don't read from the cache if the caller disabled it.
|
|
# https://docs.docker.com/engine/reference/commandline/buildx_build/#options
|
|
no-cache: ${{ inputs.no_cache }}
|
|
|
|
# For the latest built image, display:
|
|
# - the vulnerabilities (ignoring the base image, and only displaying vulnerabilities with a critical or high security severity)
|
|
# - the available recommendations
|
|
# - compare it to the latest image indexed in Docker Hub (only displaying changed packages and vulnerabilities that already have a fix)
|
|
#
|
|
# Record the image to Scout environment based on the event type, for example:
|
|
# - `prod` for a release event
|
|
# - `stage` for a push event to the main branch
|
|
# - `dev` for a pull request event
|
|
- name: Docker Scout
|
|
id: docker-scout
|
|
uses: docker/scout-action@v1.14.0
|
|
# We only run Docker Scout on the `runtime` target, as the other targets are not meant to be released
|
|
# and are commonly used for testing, and thus are ephemeral.
|
|
# TODO: Remove the `contains` check once we have a better way to determine if just new vulnerabilities are present.
|
|
# See: https://github.com/docker/scout-action/issues/56
|
|
if: ${{ inputs.dockerfile_target == 'runtime' && contains(github.event.pull_request.title, 'Release v') }}
|
|
with:
|
|
command: cves,recommendations,compare,environment
|
|
image: us-docker.pkg.dev/${{ vars.GCP_PROJECT }}/zebra/${{ inputs.image_name }}:${{ steps.meta.outputs.version }}
|
|
to: zfnd/zebra:latest
|
|
ignore-base: true
|
|
ignore-unchanged: true
|
|
only-fixed: true
|
|
only-severities: critical,high
|
|
environment: ${{ (github.event_name == 'release' && !github.event.release.prerelease && 'prod') || (github.event_name == 'push' && github.ref_name == 'main' && 'stage') || (github.event_name == 'pull_request' && 'dev') }}
|
|
organization: zfnd
|
|
github-token: ${{ secrets.GITHUB_TOKEN }} # to be able to write the comment
|