name: Pages Verify on: pull_request: branches: [main] permissions: contents: read concurrency: group: pages-verify-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: verify-pages-build: name: Verify Pages Build (No Publish) runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Verify signing key consistency (repo + docs) run: ./scripts/ci/verify_signing_key_consistency.sh - name: Prepare advisory artifacts for pre-deploy checks run: | set -euo pipefail mkdir -p public/advisories cp advisories/feed.json public/advisories/feed.json if [ -f advisories/ghsa-without-cve.json ]; then cp advisories/ghsa-without-cve.json public/advisories/ghsa-without-cve.json fi - name: Generate advisory checksums manifest run: | set -euo pipefail FILES_JSON="{}" for file in public/advisories/*.json; do REL_PATH="${file#public/}" FILE_SHA=$(sha256sum "$file" | awk '{print $1}') FILE_SIZE=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file") FILES_JSON=$(jq \ --arg path "$REL_PATH" \ --arg sha "$FILE_SHA" \ --argjson size "$FILE_SIZE" \ '. + {($path): {sha256: $sha, size: $size, path: $path, url: ("https://clawsec.prompt.security/" + $path)}}' \ <<< "$FILES_JSON") done jq -n \ --arg schema_version "1" \ --arg algorithm "sha256" \ --arg version "1.1.0" \ --arg generated "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --arg repo "${{ github.repository }}" \ --argjson files "$FILES_JSON" \ '{ schema_version: $schema_version, algorithm: $algorithm, version: $version, generated_at: $generated, repository: $repo, files: $files }' > public/checksums.json - name: Generate ephemeral signing key for PR verification id: test_key run: | set -euo pipefail KEY_FILE=$(mktemp) openssl genpkey -algorithm Ed25519 -out "$KEY_FILE" { echo "private_key<> "$GITHUB_OUTPUT" rm -f "$KEY_FILE" - name: Sign advisory feed and verify uses: ./.github/actions/sign-and-verify with: private_key: ${{ steps.test_key.outputs.private_key }} input_file: public/advisories/feed.json signature_file: public/advisories/feed.json.sig public_key_output: public/signing-public.pem - name: Sign provisional GHSA feed and verify if: hashFiles('public/advisories/ghsa-without-cve.json') != '' uses: ./.github/actions/sign-and-verify with: private_key: ${{ steps.test_key.outputs.private_key }} input_file: public/advisories/ghsa-without-cve.json signature_file: public/advisories/ghsa-without-cve.json.sig - name: Sign checksums and verify uses: ./.github/actions/sign-and-verify with: private_key: ${{ steps.test_key.outputs.private_key }} input_file: public/checksums.json signature_file: public/checksums.sig - name: Setup Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: '20' cache: 'npm' - name: Install dependencies run: npm ci - name: Build site run: npm run build env: NODE_ENV: production - name: Sanity-check generated artifacts run: | set -euo pipefail test -f dist/index.html test -f public/advisories/feed.json.sig if [ -f public/advisories/ghsa-without-cve.json ]; then test -f public/advisories/ghsa-without-cve.json.sig fi test -f public/checksums.sig test -f public/signing-public.pem