Skip to content

Build multi-architecture Typesense image and run vulnerability scan #106

Build multi-architecture Typesense image and run vulnerability scan

Build multi-architecture Typesense image and run vulnerability scan #106

name: Build multi-architecture Typesense image and run vulnerability scan
on:
schedule:
# 0521 AWST, Mon-Fri
- cron: '21 21 * * 1-5'
push:
branches:
- master
tags:
- '*'
env:
GHCR_IMAGE: ghcr.io/${{ github.repository_owner }}/typesense
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
# The build job builds the Docker image for each platform specified in the matrix.
strategy:
fail-fast: true
matrix:
platform:
- linux/amd64
- linux/arm64
permissions:
attestations: write
actions: read
checks: write
contents: write
deployments: none
id-token: write
issues: read
discussions: read
packages: write
pages: none
pull-requests: read
repository-projects: read
security-events: read
statuses: read
runs-on: ${{ matrix.platform == 'linux/amd64' && 'ubuntu-latest' || matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' }}
name: Build Docker image for ${{ matrix.platform }}
steps:
- name: Prepare environment for current platform
# The environment variable PLATFORMS_PAIR will be used later in the workflow.
id: prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Harden the GitHub runner
uses: step-security/harden-runner@v2.16.0
with:
egress-policy: audit
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Docker meta default
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.GHCR_IMAGE }}
- name: Set up Docker Context for Buildx
id: buildx-context
run: |
docker context create builders
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
with:
endpoint: builders
platforms: ${{ matrix.platform }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v7
env:
DOCKER_BUILDKIT: 1
with:
context: .
file: ./Dockerfile.typesense
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true,oci-mediatypes=true
cache-from: type=gha,scope=${{ github.repository }}-${{ github.ref_name }}-${{ matrix.platform }}
cache-to: type=gha,scope=${{ github.repository }}-${{ github.ref_name }}-${{ matrix.platform }}
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v7
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
# This job merges the Docker manifests for the different platforms built in the previous job.
name: Merge Docker manifests
runs-on: ubuntu-latest
permissions:
attestations: write
actions: read
checks: read
contents: read
deployments: none
id-token: write
issues: read
discussions: read
packages: write
pages: none
pull-requests: read
repository-projects: read
security-events: read
statuses: read
needs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v8
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Docker meta
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.GHCR_IMAGE }}
annotations: |
type=org.opencontainers.image.description,value=${{ github.event.repository.description || 'No description provided' }}
tags: |
type=raw,value=latest,enable=${{ github.ref_name == 'master' }}
type=raw,value=30.1,enable=true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
with:
driver-opts: |
network=host
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get execution timestamp with RFC3339 format
id: timestamp
run: |
echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
- name: Create manifest list and pushs
working-directory: /tmp/digests
id: manifest-annotate
continue-on-error: true
run: |
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
--annotation='index:org.opencontainers.image.description=${{ github.event.repository.description }}' \
--annotation='index:org.opencontainers.image.created=${{ steps.timestamp.outputs.timestamp }}' \
--annotation='index:org.opencontainers.image.url=${{ github.event.repository.url }}' \
--annotation='index:org.opencontainers.image.source=${{ github.event.repository.url }}' \
$(printf '${{ env.GHCR_IMAGE }}@sha256:%s ' *)
- name: Create manifest list and push without annotations
if: steps.manifest-annotate.outcome == 'failure'
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.GHCR_IMAGE }}@sha256:%s ' *)
- name: Inspect image
id: inspect
run: |
docker buildx imagetools inspect '${{ env.GHCR_IMAGE }}:${{ steps.meta.outputs.version }}'
scan:
# This job scans the merged Docker manifest produced in the previous job for security vulnerabilities
# and uploads any to the GitHub Security tab.
name: Docker image vulnerability scan
runs-on: ubuntu-latest
needs:
- merge
permissions:
contents: read
packages: read
security-events: write
steps:
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.35.0
env:
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db
with:
scan-type: 'image'
scanners: 'vuln'
image-ref: ${{ env.GHCR_IMAGE }}
vuln-type: 'library'
severity: 'HIGH,CRITICAL'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: 'trivy-results.sarif'