Merge https://github.com/cisagov/skeleton-docker into lineage/skeleton #861
This file contains 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: build | ||
on: | ||
merge_group: | ||
types: | ||
- checks_requested | ||
pull_request: | ||
push: | ||
branches: | ||
- "**" | ||
tags: | ||
- "v*.*.*" | ||
repository_dispatch: | ||
# Respond to rebuild requests. See: https://github.com/cisagov/action-apb/ | ||
types: | ||
- apb | ||
schedule: | ||
- cron: "0 10 * * *" # everyday at 10am | ||
workflow_dispatch: | ||
inputs: | ||
image-tag: | ||
default: "dispatch" | ||
description: "Tag to apply to pushed images" | ||
required: true | ||
remote-shell: | ||
default: "false" | ||
description: "Debug with remote shell" | ||
required: true | ||
# Set a default shell for any run steps. The `-Eueo pipefail` sets errtrace, | ||
# nounset, errexit, and pipefail. The `-x` will print all commands as they are | ||
# run. Please see the GitHub Actions documentation for more information: | ||
# https://docs.github.com/en/actions/using-jobs/setting-default-values-for-jobs | ||
defaults: | ||
run: | ||
shell: bash -Eueo pipefail -x {0} | ||
env: | ||
BUILDX_CACHE_DIR: ~/.cache/buildx | ||
<<<<<<< HEAD | ||
CURL_CACHE_DIR: ~/.cache/curl | ||
IMAGE_NAME: cisagov/saver | ||
======= | ||
IMAGE_NAME: cisagov/example | ||
>>>>>>> 0d48ebd47a28a887868ea3093e675e95f3843561 | ||
PIP_CACHE_DIR: ~/.cache/pip | ||
PRE_COMMIT_CACHE_DIR: ~/.cache/pre-commit | ||
RUN_TMATE: ${{ secrets.RUN_TMATE }} | ||
TERRAFORM_DOCS_REPO_BRANCH_NAME: improvement/support_atx_closed_markdown_headers | ||
TERRAFORM_DOCS_REPO_DEPTH: 1 | ||
TERRAFORM_DOCS_REPO_URL: https://github.com/mcdonnnj/terraform-docs.git | ||
jobs: | ||
diagnostics: | ||
name: Run diagnostics | ||
# This job does not need any permissions | ||
permissions: {} | ||
runs-on: ubuntu-latest | ||
steps: | ||
# Note that a duplicate of this step must be added at the top of | ||
# each job. | ||
- uses: GitHubSecurityLab/actions-permissions/monitor@v1 | ||
with: | ||
# Uses the organization variable unless overridden | ||
config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} | ||
# Note that a duplicate of this step must be added at the top of | ||
# each job. | ||
- id: harden-runner | ||
name: Harden the runner | ||
uses: step-security/harden-runner@v2 | ||
with: | ||
egress-policy: audit | ||
- id: github-status | ||
name: Check GitHub status | ||
uses: crazy-max/ghaction-github-status@v4 | ||
- id: dump-context | ||
name: Dump context | ||
uses: crazy-max/ghaction-dump-context@v2 | ||
lint: | ||
# Checks out the source and runs pre-commit hooks. Detects coding errors | ||
# and style deviations. | ||
name: Lint sources | ||
needs: | ||
- diagnostics | ||
permissions: | ||
# actions/checkout needs this to fetch code | ||
contents: read | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: GitHubSecurityLab/actions-permissions/monitor@v1 | ||
with: | ||
# Uses the organization variable unless overridden | ||
config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} | ||
- id: harden-runner | ||
name: Harden the runner | ||
uses: step-security/harden-runner@v2 | ||
with: | ||
egress-policy: audit | ||
- id: setup-env | ||
uses: cisagov/setup-env-github-action@develop | ||
- uses: actions/checkout@v4 | ||
- id: setup-python | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: ${{ steps.setup-env.outputs.python-version }} | ||
# We need the Go version and Go cache location for the actions/cache step, | ||
# so the Go installation must happen before that. | ||
- id: setup-go | ||
uses: actions/setup-go@v5 | ||
with: | ||
# There is no expectation for actual Go code so we disable caching as | ||
# it relies on the existence of a go.sum file. | ||
cache: false | ||
go-version: ${{ steps.setup-env.outputs.go-version }} | ||
- id: go-cache | ||
name: Lookup Go cache directory | ||
run: | | ||
echo "dir=$(go env GOCACHE)" >> $GITHUB_OUTPUT | ||
- uses: actions/cache@v4 | ||
env: | ||
BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\ | ||
py${{ steps.setup-python.outputs.python-version }}-\ | ||
go${{ steps.setup-go.outputs.go-version }}-\ | ||
packer${{ steps.setup-env.outputs.packer-version }}-\ | ||
tf${{ steps.setup-env.outputs.terraform-version }}-" | ||
with: | ||
key: "${{ env.BASE_CACHE_KEY }}\ | ||
${{ hashFiles('**/requirements-test.txt') }}-\ | ||
${{ hashFiles('**/requirements.txt') }}-\ | ||
${{ hashFiles('**/.pre-commit-config.yaml') }}" | ||
# Note that the .terraform directory IS NOT included in the | ||
# cache because if we were caching, then we would need to use | ||
# the `-upgrade=true` option. This option blindly pulls down the | ||
# latest modules and providers instead of checking to see if an | ||
# update is required. That behavior defeats the benefits of caching. | ||
# so there is no point in doing it for the .terraform directory. | ||
path: | | ||
${{ env.PIP_CACHE_DIR }} | ||
${{ env.PRE_COMMIT_CACHE_DIR }} | ||
${{ steps.go-cache.outputs.dir }} | ||
restore-keys: | | ||
${{ env.BASE_CACHE_KEY }} | ||
- uses: hashicorp/setup-packer@v3 | ||
with: | ||
version: ${{ steps.setup-env.outputs.packer-version }} | ||
- uses: hashicorp/setup-terraform@v3 | ||
with: | ||
terraform_version: ${{ steps.setup-env.outputs.terraform-version }} | ||
- name: Install go-critic | ||
env: | ||
PACKAGE_URL: github.com/go-critic/go-critic/cmd/gocritic | ||
PACKAGE_VERSION: ${{ steps.setup-env.outputs.go-critic-version }} | ||
run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} | ||
- name: Install goimports | ||
env: | ||
PACKAGE_URL: golang.org/x/tools/cmd/goimports | ||
PACKAGE_VERSION: ${{ steps.setup-env.outputs.goimports-version }} | ||
run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} | ||
- name: Install gosec | ||
env: | ||
PACKAGE_URL: github.com/securego/gosec/v2/cmd/gosec | ||
PACKAGE_VERSION: ${{ steps.setup-env.outputs.gosec-version }} | ||
run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} | ||
- name: Install staticcheck | ||
env: | ||
PACKAGE_URL: honnef.co/go/tools/cmd/staticcheck | ||
PACKAGE_VERSION: ${{ steps.setup-env.outputs.staticcheck-version }} | ||
run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} | ||
# TODO: https://github.com/cisagov/skeleton-generic/issues/165 | ||
# We are temporarily using @mcdonnnj's forked branch of terraform-docs | ||
# until his PR: https://github.com/terraform-docs/terraform-docs/pull/745 | ||
# is approved. This temporary fix will allow for ATX header support when | ||
# terraform-docs is run during linting. | ||
- name: Clone ATX headers branch from terraform-docs fork | ||
run: | | ||
git clone \ | ||
--branch $TERRAFORM_DOCS_REPO_BRANCH_NAME \ | ||
--depth $TERRAFORM_DOCS_REPO_DEPTH \ | ||
--single-branch \ | ||
$TERRAFORM_DOCS_REPO_URL /tmp/terraform-docs | ||
- name: Build and install terraform-docs binary | ||
run: | | ||
go build \ | ||
-C /tmp/terraform-docs \ | ||
-o $(go env GOPATH)/bin/terraform-docs | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip setuptools wheel | ||
pip install --upgrade --requirement requirements-test.txt | ||
- name: Set up pre-commit hook environments | ||
run: pre-commit install-hooks | ||
- name: Run pre-commit on all files | ||
run: pre-commit run --all-files | ||
- name: Setup tmate debug session | ||
uses: mxschmitt/action-tmate@v3 | ||
if: env.RUN_TMATE | ||
prepare: | ||
# Generate Docker image metadata using the docker/metadata-action GitHub Action. | ||
name: Prepare build variables | ||
needs: | ||
- diagnostics | ||
outputs: | ||
labels: ${{ steps.generate-metadata.outputs.labels }} | ||
tags: ${{ steps.generate-metadata.outputs.tags }} | ||
permissions: | ||
# actions/checkout needs this to fetch code | ||
contents: read | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: GitHubSecurityLab/actions-permissions/monitor@v1 | ||
with: | ||
# Uses the organization variable unless overridden | ||
config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} | ||
- id: harden-runner | ||
name: Harden the runner | ||
uses: step-security/harden-runner@v2 | ||
with: | ||
egress-policy: audit | ||
- uses: actions/checkout@v4 | ||
- id: generate-metadata | ||
name: Generate Docker image metadata | ||
uses: docker/metadata-action@v5 | ||
with: | ||
images: | | ||
${{ env.IMAGE_NAME }} | ||
ghcr.io/${{ env.IMAGE_NAME }} | ||
tags: | | ||
type=edge | ||
type=raw,event=workflow_dispatch,value=${{ github.event.inputs.image-tag }} | ||
type=ref,event=branch | ||
type=ref,event=pr | ||
type=ref,event=tag | ||
type=schedule | ||
type=semver,pattern={{major}} | ||
type=semver,pattern={{major}}.{{minor}} | ||
type=semver,pattern={{version}} | ||
type=sha | ||
- name: Setup tmate debug session | ||
uses: mxschmitt/action-tmate@v3 | ||
if: github.event.inputs.remote-shell == 'true' || env.RUN_TMATE | ||
build: | ||
# Builds a single test image for the native platform. This image is saved | ||
# as an artifact and loaded by the test job. | ||
name: Build test image | ||
needs: | ||
- diagnostics | ||
- prepare | ||
permissions: | ||
# actions/checkout needs this to fetch code | ||
contents: read | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: GitHubSecurityLab/actions-permissions/monitor@v1 | ||
with: | ||
# Uses the organization variable unless overridden | ||
config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} | ||
- id: harden-runner | ||
name: Harden the runner | ||
uses: step-security/harden-runner@v2 | ||
with: | ||
egress-policy: audit | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Set up QEMU | ||
uses: docker/setup-qemu-action@v3 | ||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
- name: Cache Docker layers | ||
uses: actions/cache@v4 | ||
env: | ||
BASE_CACHE_KEY: buildx-${{ runner.os }}- | ||
with: | ||
key: ${{ env.BASE_CACHE_KEY }}${{ github.sha }} | ||
path: ${{ env.BUILDX_CACHE_DIR }} | ||
restore-keys: | | ||
${{ env.BASE_CACHE_KEY }} | ||
- name: Create dist directory | ||
run: mkdir -p dist | ||
- name: Build image | ||
id: docker_build | ||
uses: docker/build-push-action@v6 | ||
with: | ||
cache-from: type=local,src=${{ env.BUILDX_CACHE_DIR }} | ||
cache-to: type=local,dest=${{ env.BUILDX_CACHE_DIR }} | ||
context: . | ||
file: ./Dockerfile | ||
labels: ${{ needs.prepare.outputs.labels }} | ||
outputs: type=docker,dest=dist/image.tar | ||
# Uncomment the following option if you are building an image for use | ||
# on Google Cloud Run or AWS Lambda. The current default image output | ||
# is unable to run on either. Please see the following issue for more | ||
# information: https://github.com/docker/buildx/issues/1533 | ||
# provenance: false | ||
tags: ${{ env.IMAGE_NAME }}:latest # not to be pushed | ||
# For a list of pre-defined annotation keys and value types see: | ||
# https://github.com/opencontainers/image-spec/blob/master/annotations.md | ||
- name: Compress image | ||
run: gzip dist/image.tar | ||
- name: Upload artifacts | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: dist | ||
path: dist | ||
- name: Setup tmate debug session | ||
uses: mxschmitt/action-tmate@v3 | ||
if: env.RUN_TMATE | ||
test: | ||
# Executes tests on the single-platform image created in the "build" job. | ||
name: Test image | ||
needs: | ||
- diagnostics | ||
- build | ||
permissions: | ||
# actions/checkout needs this to fetch code | ||
contents: read | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: GitHubSecurityLab/actions-permissions/monitor@v1 | ||
with: | ||
# Uses the organization variable unless overridden | ||
config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} | ||
- id: harden-runner | ||
name: Harden the runner | ||
uses: step-security/harden-runner@v2 | ||
with: | ||
egress-policy: audit | ||
- id: setup-env | ||
uses: cisagov/setup-env-github-action@develop | ||
- uses: actions/checkout@v4 | ||
- id: setup-python | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: ${{ steps.setup-env.outputs.python-version }} | ||
- name: Cache testing environments | ||
uses: actions/cache@v4 | ||
env: | ||
BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\ | ||
py${{ steps.setup-python.outputs.python-version }}-" | ||
with: | ||
key: "${{ env.BASE_CACHE_KEY }}\ | ||
${{ hashFiles('**/requirements-test.txt') }}-\ | ||
${{ hashFiles('**/requirements.txt') }}" | ||
path: ${{ env.PIP_CACHE_DIR }} | ||
restore-keys: | | ||
${{ env.BASE_CACHE_KEY }} | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip setuptools wheel | ||
pip install --upgrade --requirement requirements-test.txt | ||
- name: Download docker image artifact | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: dist | ||
path: dist | ||
- name: Load docker image | ||
run: docker load < dist/image.tar.gz | ||
- name: Run tests | ||
env: | ||
RELEASE_TAG: ${{ github.event.release.tag_name }} | ||
run: pytest --runslow | ||
- name: Setup tmate debug session | ||
uses: mxschmitt/action-tmate@v3 | ||
if: env.RUN_TMATE | ||
build-push-all: | ||
# Builds the final set of images for each of the platforms specified in the | ||
# "platforms" input for the docker/build-push-action Action. These images | ||
# are tagged with the Docker tags calculated in the "prepare" job and | ||
# pushed to Docker Hub and the GitHub Container Registry. The contents of | ||
# README.md are pushed as the image's description to Docker Hub. This job | ||
# is skipped when the triggering event is a pull request. | ||
if: github.event_name != 'pull_request' | ||
name: Build and push all platforms | ||
needs: | ||
- diagnostics | ||
- lint | ||
- prepare | ||
- test | ||
permissions: | ||
# actions/checkout needs this to fetch code | ||
contents: read | ||
# When Dependabot creates a PR it requires this permission in | ||
# order to push Docker images to ghcr.io. | ||
packages: write | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: GitHubSecurityLab/actions-permissions/monitor@v1 | ||
with: | ||
# Uses the organization variable unless overridden | ||
config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} | ||
- id: harden-runner | ||
name: Harden the runner | ||
uses: step-security/harden-runner@v2 | ||
with: | ||
egress-policy: audit | ||
- name: Login to Docker Hub | ||
uses: docker/login-action@v3 | ||
with: | ||
password: ${{ secrets.DOCKER_PASSWORD }} | ||
username: ${{ secrets.DOCKER_USERNAME }} | ||
- name: Login to GitHub Container Registry | ||
uses: docker/login-action@v3 | ||
with: | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Set up QEMU | ||
uses: docker/setup-qemu-action@v3 | ||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
- name: Cache Docker layers | ||
uses: actions/cache@v4 | ||
env: | ||
BASE_CACHE_KEY: buildx-${{ runner.os }}- | ||
with: | ||
key: ${{ env.BASE_CACHE_KEY }}${{ github.sha }} | ||
path: ${{ env.BUILDX_CACHE_DIR }} | ||
restore-keys: | | ||
${{ env.BASE_CACHE_KEY }} | ||
- name: Create cross-platform support Dockerfile-x | ||
run: ./buildx-dockerfile.sh | ||
- name: Build and push platform images to registries | ||
id: docker_build | ||
uses: docker/build-push-action@v6 | ||
with: | ||
cache-from: type=local,src=${{ env.BUILDX_CACHE_DIR }} | ||
cache-to: type=local,dest=${{ env.BUILDX_CACHE_DIR }} | ||
context: . | ||
file: ./Dockerfile-x | ||
labels: ${{ needs.prepare.outputs.labels }} | ||
platforms: | | ||
linux/amd64 | ||
linux/arm/v6 | ||
linux/arm/v7 | ||
linux/arm64 | ||
linux/ppc64le | ||
linux/s390x | ||
# Uncomment the following option if you are building an image for use | ||
# on Google Cloud Run or AWS Lambda. The current default image output | ||
# is unable to run on either. Please see the following issue for more | ||
# information: https://github.com/docker/buildx/issues/1533 | ||
# provenance: false | ||
push: true | ||
tags: ${{ needs.prepare.outputs.tags }} | ||
# For a list of pre-defined annotation keys and value types see: | ||
# https://github.com/opencontainers/image-spec/blob/master/annotations.md | ||
- name: Publish README.md to Docker Hub | ||
env: | ||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | ||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | ||
run: ./push_readme.sh | ||
- name: Setup tmate debug session | ||
uses: mxschmitt/action-tmate@v3 | ||
if: env.RUN_TMATE |