Docker Image CI #606
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: Docker Image CI | |
on: | |
workflow_dispatch: | |
push: | |
branches: | |
- $default-branch | |
- development | |
- master | |
tags: | |
- "*.*.*-*" | |
# Run tests for any PRs | |
pull_request: | |
schedule: | |
- cron: "43 10 * * 4" | |
env: | |
IMAGE_NAME: calcardbackup | |
jobs: | |
codespell: | |
name: codespell | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Codespell | |
uses: codespell-project/actions-codespell@master | |
with: | |
ignore_words_list: ro,rw | |
skip: .git | |
check_filenames: true | |
check_hidden: true | |
super-linter: | |
name: super-linter | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
# super-linter needs the full git history to get the | |
# list of files that changed across commits | |
fetch-depth: 0 | |
- name: Lint Code Base | |
uses: super-linter/super-linter@v7 | |
env: | |
DEFAULT_BRANCH: master | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
shiftleft: | |
name: shiftleft | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Perform ShiftLeft Scan | |
uses: ShiftLeftSecurity/scan-action@master | |
env: | |
WORKSPACE: "" | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
SCAN_AUTO_BUILD: true | |
with: | |
output: reports | |
# Scan auto-detects the languages in your project. To override uncomment the below variable and set the type | |
# type: credscan,java | |
# type: python | |
- name: Upload report | |
uses: github/codeql-action/upload-sarif@v3 | |
with: | |
sarif_file: reports | |
test-build: | |
needs: | |
- codespell | |
- super-linter | |
- shiftleft | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
with: | |
platforms: linux/amd64 | |
- name: Set up Docker Buildx | |
id: buildx | |
uses: docker/setup-buildx-action@v3 | |
with: | |
driver-opts: network=host | |
- name: Build the Docker image | |
id: docker_test | |
uses: docker/build-push-action@v6 | |
with: | |
builder: ${{ steps.buildx.outputs.name }} | |
push: false | |
outputs: type=docker,dest=/tmp/${{ env.IMAGE_NAME }}-${{ github.run_number }}.tar | |
tags: localhost:5000/foobar/${{ env.IMAGE_NAME }} | |
cache-from: type=local,src=/tmp/.buildx-cache | |
cache-to: type=local,dest=/tmp/.buildx-cache | |
context: . | |
file: ./Dockerfile | |
platforms: linux/amd64 | |
build-args: | | |
BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" | |
BUILD_VERSION="$(git describe --tags)" | |
VCS_REF="$(git rev-parse --short HEAD)" | |
VCS_URL="$(git config --get remote.origin.url)" | |
VCS_BRANCH="$(git rev-parse --abbrev-ref HEAD)" | |
- name: Upload artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ env.IMAGE_NAME }}-${{ github.run_number }} | |
path: /tmp/${{ env.IMAGE_NAME }}-${{ github.run_number }}.tar | |
test: | |
name: Run test | |
needs: | |
- test-build | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
services: | |
registry: | |
image: registry:2 | |
ports: | |
- 5000:5000 | |
steps: | |
- name: Download artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ env.IMAGE_NAME }}-${{ github.run_number }} | |
path: /tmp | |
- name: Load image and push to local registry | |
run: | | |
docker load --input /tmp/${{ env.IMAGE_NAME }}-${{ github.run_number }}.tar | |
docker image ls -a | |
docker push localhost:5000/foobar/${{ env.IMAGE_NAME }} | |
- name: Inspect the Docker image | |
run: | | |
docker buildx imagetools inspect localhost:5000/foobar/${{ env.IMAGE_NAME }} | |
- name: Test the Docker image | |
run: | | |
CONTAINER_OUTPUT="$(docker run --rm -t localhost:5000/foobar/${{ env.IMAGE_NAME }} /opt/calcardbackup/calcardbackup -h)" | |
# shellcheck disable=SC2086 | |
TEST_STRING="$(echo ${CONTAINER_OUTPUT} | grep -c 'START calcardbackup')" | |
if ! [ "${TEST_STRING}" = "1" ]; then exit 1; fi | |
dockle: | |
name: Run Dockle tests | |
needs: | |
- test-build | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
services: | |
registry: | |
image: registry:2 | |
ports: | |
- 5000:5000 | |
steps: | |
- name: Download artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ env.IMAGE_NAME }}-${{ github.run_number }} | |
path: /tmp | |
- name: Load image and push to local registry | |
run: | | |
docker load --input /tmp/${{ env.IMAGE_NAME }}-${{ github.run_number }}.tar | |
docker image ls -a | |
docker push localhost:5000/foobar/${{ env.IMAGE_NAME }} | |
- name: Run dockle container image linter | |
uses: goodwithtech/dockle-action@v0.1.2 | |
with: | |
image: "registry:5000/foobar/${{ env.IMAGE_NAME }}" | |
insecure: true | |
format: "sarif" | |
exit-code: "1" | |
exit-level: "warn" | |
ignore: "CIS-DI-0001,CIS-DI-0010,DKL-DI-0006" | |
output: sarif-reports | |
- name: Upload Reports | |
uses: github/codeql-action/upload-sarif@v3 | |
with: | |
sarif_file: "sarif-reports" | |
trivy: | |
name: Run Trivy tests | |
needs: | |
- test-build | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
services: | |
registry: | |
image: registry:2 | |
ports: | |
- 5000:5000 | |
steps: | |
- name: Download artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ env.IMAGE_NAME }}-${{ github.run_number }} | |
path: /tmp | |
- name: Load image and push to local registry | |
run: | | |
docker load --input /tmp/${{ env.IMAGE_NAME }}-${{ github.run_number }}.tar | |
docker image ls -a | |
docker push localhost:5000/foobar/${{ env.IMAGE_NAME }} | |
- name: Run Trivy vulnerability scanner | |
uses: aquasecurity/trivy-action@master | |
with: | |
image-ref: localhost:5000/foobar/${{ env.IMAGE_NAME }} | |
format: "template" | |
template: "@/contrib/sarif.tpl" | |
output: "trivy-results.sarif" | |
severity: "CRITICAL,HIGH" | |
- name: Upload Reports | |
uses: github/codeql-action/upload-sarif@v3 | |
with: | |
sarif_file: "trivy-results.sarif" | |
anchore: | |
name: Run Anchore tests | |
needs: | |
- test-build | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
services: | |
registry: | |
image: registry:2 | |
ports: | |
- 5000:5000 | |
steps: | |
- name: Download artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ env.IMAGE_NAME }}-${{ github.run_number }} | |
path: /tmp | |
- name: Load image and push to local registry | |
run: | | |
docker load --input /tmp/${{ env.IMAGE_NAME }}-${{ github.run_number }}.tar | |
docker image ls -a | |
docker push localhost:5000/foobar/${{ env.IMAGE_NAME }} | |
- name: Run the Anchore scan action itself with GitHub Advanced Security code scanning integration enabled | |
uses: anchore/scan-action@main | |
with: | |
image: localhost:5000/foobar/${{ env.IMAGE_NAME }} | |
acs-report-enable: true | |
fail-build: false | |
- name: Move reports | |
run: mkdir -p sarif-reports && cp ./*results.sarif ./sarif-reports/ | |
- name: Upload Reports | |
uses: github/codeql-action/upload-sarif@v3 | |
with: | |
sarif_file: "sarif-reports" | |
release-docker: | |
name: Release Docker images | |
needs: | |
- test | |
- dockle | |
- trivy | |
- anchore | |
strategy: | |
fail-fast: false | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Prepare | |
id: prep | |
env: | |
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
QUAY_USERNAME: ${{ secrets.QUAY_USERNAME }} | |
QUAY_TOKEN: ${{ secrets.QUAY_TOKEN }} | |
run: | | |
USER="${GITHUB_REPOSITORY_OWNER}" | |
IMAGE_NAME="$(echo '${{ github.repository }}' | awk -F '/' '{print $2}' | sed s/docker-//)" | |
DOCKER_IMAGE="${USER}/${IMAGE_NAME}" | |
VERSION=edge | |
# running on a tag | |
if [[ $GITHUB_REF == refs/tags/* ]]; then | |
VERSION="${GITHUB_REF#refs/tags/}" | |
fi | |
# running on a branch | |
if [[ "$GITHUB_REF" == refs/heads/* ]]; then | |
VERSION="${GITHUB_REF#refs/heads/}" | |
fi | |
# running on schedule | |
# shellcheck disable=SC2050 | |
if [ "${{ github.event_name }}" = "schedule" ]; then | |
VERSION=nightly | |
fi | |
# running on master branch | |
if [ "$VERSION" = "master" ]; then | |
VERSION=latest | |
fi | |
TAGS="${DOCKER_IMAGE}:${VERSION}" | |
if [[ "$VERSION" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\-[0-9]{1,3}$ ]]; then | |
REALEASE_TAG=true | |
fi | |
TAGS_INT="$TAGS" | |
TAGS="" | |
if [ "$DOCKERHUB_USERNAME" != '' ] && [ "$DOCKERHUB_TOKEN" != '' ]; then | |
if [ "$REALEASE_TAG" = "true" ]; then | |
TAGS="$TAGS_INT,${DOCKER_IMAGE}:latest" | |
else | |
TAGS="$TAGS_INT" | |
fi | |
fi | |
if [ "$GITHUB_TOKEN" != '' ]; then | |
if [ "$REALEASE_TAG" = "true" ]; then | |
TAGS="$TAGS,ghcr.io/$TAGS_INT,ghcr.io/${DOCKER_IMAGE}:latest" | |
else | |
TAGS="$TAGS,ghcr.io/$TAGS_INT" | |
fi | |
fi | |
if [ "$QUAY_USERNAME" != '' ] && [ "$QUAY_TOKEN" != '' ]; then | |
if [ "$REALEASE_TAG" = "true" ]; then | |
TAGS="$TAGS,quay.io/$TAGS_INT,quay.io/${DOCKER_IMAGE}:latest" | |
else | |
TAGS="$TAGS,quay.io/$TAGS_INT" | |
fi | |
fi | |
echo "tags=${TAGS}" >> "$GITHUB_OUTPUT" | |
- name: Download artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ env.IMAGE_NAME }}-${{ github.run_number }} | |
path: /tmp | |
- name: Load image from test job | |
run: | | |
docker load --input /tmp/${{ env.IMAGE_NAME }}-${{ github.run_number }}.tar | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
with: | |
platforms: all | |
- name: Set up Docker Buildx | |
id: buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Cache Docker layers | |
uses: actions/cache@v4 | |
with: | |
path: /tmp/.buildx-cache | |
key: ${{ runner.os }}-buildx-${{ github.sha }} | |
restore-keys: | | |
${{ runner.os }}-buildx- | |
- name: Login to ghcr | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
if: ${{ github.event_name != 'pull_request' && env.GITHUB_TOKEN != '' }} | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${USER} | |
password: ${{ env.GITHUB_TOKEN }} | |
- name: Login to DockerHub Container Registry | |
env: | |
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
if: ${{ github.event_name != 'pull_request' && env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != '' }} | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ env.DOCKERHUB_USERNAME }} | |
password: ${{ env.DOCKERHUB_TOKEN }} | |
- name: Login to Quay Container Registry | |
env: | |
QUAY_USERNAME: ${{ secrets.QUAY_USERNAME }} | |
QUAY_TOKEN: ${{ secrets.QUAY_TOKEN }} | |
if: ${{ github.event_name != 'pull_request' && env.QUAY_USERNAME != '' && env.QUAY_TOKEN != '' }} | |
uses: docker/login-action@v3 | |
with: | |
registry: quay.io | |
username: ${{ env.QUAY_USERNAME }} | |
password: ${{ env.QUAY_TOKEN }} | |
- name: Test | |
id: docker_test | |
uses: docker/build-push-action@v6 | |
with: | |
builder: ${{ steps.buildx.outputs.name }} | |
context: . | |
file: ./Dockerfile | |
platforms: linux/amd64 | |
build-args: | | |
BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" | |
BUILD_VERSION="$(git describe --tags)" | |
VCS_REF="$(git rev-parse --short HEAD)" | |
VCS_URL="$(git config --get remote.origin.url)" | |
VCS_BRANCH="$(git rev-parse --abbrev-ref HEAD)" | |
- name: Build and push | |
id: docker_build | |
uses: docker/build-push-action@v6 | |
with: | |
builder: ${{ steps.buildx.outputs.name }} | |
context: . | |
file: ./Dockerfile | |
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64 | |
push: ${{ github.event_name != 'pull_request' }} | |
tags: | | |
${{ steps.prep.outputs.tags }} | |
cache-from: type=local,src=/tmp/.buildx-cache | |
cache-to: type=local,dest=/tmp/.buildx-cache | |
build-args: | | |
BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" | |
BUILD_VERSION="$(git describe --tags)" | |
VCS_REF="$(git rev-parse --short HEAD)" | |
VCS_URL="$(git config --get remote.origin.url)" | |
VCS_BRANCH="$(git rev-parse --abbrev-ref HEAD)" | |
- name: Image digest | |
run: echo ${{ steps.docker_build.outputs.digest }} |