Mirror Trivy Databases #131
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: Mirror Trivy Databases | |
| on: | |
| schedule: | |
| # Every 6 hours at :15 to avoid the top-of-hour GitHub scheduler congestion. | |
| # Upstream Trivy databases refresh roughly every 6h, so this stays within | |
| # one refresh window of upstream. | |
| - cron: "15 */6 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| dry_run: | |
| description: "Resolve digests but skip pushing" | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| concurrency: | |
| group: mirror-trivy-db | |
| cancel-in-progress: true | |
| jobs: | |
| resolve: | |
| name: Resolve mirror targets | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.matrix.outputs.matrix }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Install yq | |
| run: | | |
| sudo curl -fsSL -o /usr/local/bin/yq \ | |
| https://github.com/mikefarah/yq/releases/download/v4.45.1/yq_linux_amd64 | |
| sudo chmod +x /usr/local/bin/yq | |
| - name: Build matrix from build.yaml | |
| id: matrix | |
| run: | | |
| matrix="$(yq -o=json -I=0 '{"include": .mirrors}' build.yaml)" | |
| echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" | |
| printf 'Resolved matrix: %s\n' "${matrix}" | |
| mirror: | |
| name: Mirror ${{ matrix.name }} | |
| needs: resolve | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.resolve.outputs.matrix) }} | |
| steps: | |
| - name: Install oras | |
| uses: oras-project/setup-oras@v2 | |
| - name: Install cosign | |
| uses: sigstore/cosign-installer@v4.1.2 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Log in to GHCR for ORAS | |
| run: | | |
| printf '%s' '${{ secrets.GITHUB_TOKEN }}' | oras login ghcr.io \ | |
| --username '${{ github.actor }}' \ | |
| --password-stdin | |
| - name: Resolve upstream digest | |
| id: upstream | |
| run: | | |
| src="${{ matrix.source }}:${{ matrix.tag }}" | |
| digest="$(oras resolve "${src}")" | |
| echo "src=${src}" >> "$GITHUB_OUTPUT" | |
| echo "digest=${digest}" >> "$GITHUB_OUTPUT" | |
| printf 'Upstream %s resolved to %s\n' "${src}" "${digest}" | |
| - name: Copy artifact | |
| id: copy | |
| if: inputs.dry_run != true | |
| run: | | |
| oras copy \ | |
| "${{ steps.upstream.outputs.src }}" \ | |
| "${{ matrix.target }}:${{ matrix.tag }}" | |
| mirrored="$(oras resolve "${{ matrix.target }}:${{ matrix.tag }}")" | |
| if [ "${mirrored}" != "${{ steps.upstream.outputs.digest }}" ]; then | |
| echo "::error::Mirror digest ${mirrored} != upstream ${{ steps.upstream.outputs.digest }}" | |
| exit 1 | |
| fi | |
| echo "digest=${mirrored}" >> "$GITHUB_OUTPUT" | |
| - name: Sign mirrored artifact | |
| if: steps.copy.outputs.digest != '' | |
| env: | |
| COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }} | |
| COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} | |
| run: | | |
| cosign sign --yes --key env://COSIGN_PRIVATE_KEY \ | |
| "${{ matrix.target }}@${{ steps.copy.outputs.digest }}" | |
| - name: Attest mirrored artifact | |
| if: steps.copy.outputs.digest != '' | |
| uses: actions/attest@v4 | |
| with: | |
| subject-name: ${{ matrix.target }} | |
| subject-digest: ${{ steps.copy.outputs.digest }} | |
| push-to-registry: true | |
| - name: Job summary | |
| if: always() | |
| run: | | |
| { | |
| echo "### ${{ matrix.name }}" | |
| echo "" | |
| echo "- Source: \`${{ steps.upstream.outputs.src }}\`" | |
| echo "- Target: \`${{ matrix.target }}:${{ matrix.tag }}\`" | |
| echo "- Upstream: \`${{ steps.upstream.outputs.digest }}\`" | |
| if [ "${{ inputs.dry_run }}" = "true" ]; then | |
| echo "- Result: dry-run (no push)" | |
| else | |
| echo "- Mirror now: \`${{ steps.copy.outputs.digest }}\`" | |
| echo "- Signed: yes (cosign)" | |
| echo "- Attested: yes (actions/attest@v4)" | |
| fi | |
| } >> "$GITHUB_STEP_SUMMARY" |