Build multi-architecture Typesense image and run vulnerability scan #106
Workflow file for this run
This file contains hidden or 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 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' |