Skip to content

Image Scan

Image Scan #2968

Workflow file for this run

name: Image Scan
on:
schedule:
# everyday at midnight.
- cron: "0 0 * * *"
workflow_dispatch: {}
push:
# TODO: add this once we have all images in the metadata.yaml
# paths:
# - '**/metadata.yaml'
branches:
- main
paths-ignore:
- ".claude/**"
permissions:
security-events: write
jobs:
build-deps:
name: Build dependencies
outputs:
local-artifact-mirror-image: ${{ steps.local-artifact-mirror.outputs.image }}
operator-image: ${{ steps.operator.outputs.image }}
operator-chart: ${{ steps.operator.outputs.chart }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0 # fetch all history so that we can get the previous tag
- name: Install dagger
run: |
curl -fsSL https://dl.dagger.io/dagger/install.sh | sh
sudo mv ./bin/dagger /usr/local/bin/dagger
- name: Build and push local-artifact-mirror image
id: local-artifact-mirror
run: |
make -C local-artifact-mirror build-ttl.sh
echo "image=$(cat local-artifact-mirror/build/image)" >> $GITHUB_OUTPUT
- name: Build and push operator image
id: operator
run: |
make -C operator build-ttl.sh build-chart-ttl.sh
echo "image=$(cat operator/build/image)" >> $GITHUB_OUTPUT
echo "chart=$(cat operator/build/chart)" >> $GITHUB_OUTPUT
buildtools:
name: Build buildtools
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "**/*.sum"
- name: Build buildtools
run: |
make buildtools
- name: Upload buildtools artifact
uses: actions/upload-artifact@v7
with:
name: buildtools
path: output/bin/buildtools
output-matrix:
name: Build output matrix
runs-on: ubuntu-latest
needs:
- build-deps
- buildtools
outputs:
matrix: ${{ steps.build-matrix.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "**/*.sum"
- name: Install dagger
run: |
curl -fsSL https://dl.dagger.io/dagger/install.sh | sh
sudo mv ./bin/dagger /usr/local/bin/dagger
- name: Download buildtools artifact
uses: actions/download-artifact@v8
with:
name: buildtools
path: output/bin
- name: Update embedded-cluster-operator metadata.yaml
env:
IMAGES_REGISTRY_SERVER: ttl.sh
OPERATOR_CHART: ${{ needs.build-deps.outputs.operator-chart }}
OPERATOR_IMAGE: ${{ needs.build-deps.outputs.operator-image }}
run: |
./scripts/ci-update-operator-metadata.sh
- name: Build
run: |
export LOCAL_ARTIFACT_MIRROR_IMAGE=${{ needs.build-deps.outputs.local-artifact-mirror-image }}
make embedded-cluster-linux-amd64
- name: List images
run: |
./output/bin/embedded-cluster version list-images > images.txt
- name: Upload images artifact
uses: actions/upload-artifact@v7
with:
name: images
path: images.txt
- name: Build images matrix
id: build-matrix
run: |
IMAGES="[$(awk '{print $1}' images.txt | xargs -n1 | awk '{print "\""$1"\","}' | sed '$ s/.$//')]"
echo "matrix=$(jq -cn --argjson images "$IMAGES" '{image: $images}')" >> $GITHUB_OUTPUT
scan:
runs-on: ubuntu-latest
needs: [output-matrix]
strategy:
fail-fast: false
matrix: ${{fromJson(needs.output-matrix.outputs.matrix)}}
steps:
- name: Checkout
uses: actions/checkout@v6
- uses: ./.github/actions/scan-image
id: scan-image
with:
image-ref: "${{ matrix.image }}"
upload-sarif: ${{ github.ref == 'refs/heads/main' }}
fail-build: "false"
severity-cutoff: "medium"
output-file: "results.sarif"
retention-days: "90"
category-prefix: "image-scan-"
only-fixed: "true"
- name: Upload scan output
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v7
with:
name: scan-output-${{ steps.scan-image.outputs.safe-name }}
path: scan-output.txt
retention-days: 1
collect-scan-results:
name: Collect and print image scan results
runs-on: ubuntu-latest
needs: [scan]
# always() prevents GitHub's implicit success() check from skipping this job when
# scan fails due to vulnerabilities. The needs.scan.result check still ensures we
# skip if scan was cancelled or never ran (e.g. output-matrix failed).
if: always() && (needs.scan.result == 'success' || needs.scan.result == 'failure')
steps:
- name: Download all scan outputs
uses: actions/download-artifact@v8
with:
pattern: scan-output-*
path: scan-outputs
merge-multiple: false
- name: Combine into scan-results.txt
run: |
for f in scan-outputs/scan-output-*/scan-output.txt; do
[ -f "$f" ] || continue
cat "$f"
echo ""
done > scan-results.txt
- name: Print image scan results to console
run: |
cat scan-results.txt
echo '## Image Scan Results' >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
cat scan-results.txt >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
- name: Upload scan-results.txt
uses: actions/upload-artifact@v7
with:
name: scan-results
path: scan-results.txt
retention-days: 90