Tutorial: Setting Up GitHub CI
This tutorial sets up continuous CRA assessment in GitHub Actions — every PR gets scanned, findings appear in Code Scanning, and merges are gated on compliance.
Prerequisites
Section titled “Prerequisites”- Fleet scanner binary available (or use the Docker image)
- GitHub repository with Actions enabled
- Fleet API URL and key (optional, for dashboard integration)
Step 1: Create the Workflow
Section titled “Step 1: Create the Workflow”Create .github/workflows/fleet-cra.yml:
name: CRA Complianceon: pull_request: push: branches: [main]
permissions: contents: read checks: write security-events: write
jobs: cra-scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Run CRA Assessment run: | fleet scan \ --path . \ --ci \ --output json \ --output-file $RUNNER_TEMP/results.json \ --sbom --cbom \ --report $RUNNER_TEMP/cra-report.md
- name: Upload Evidence if: always() uses: actions/upload-artifact@v4 with: name: cra-evidence path: | ${{ runner.temp }}/results.json ${{ runner.temp }}/cra-report.md retention-days: 3650Step 2: Add SARIF for Code Scanning
Section titled “Step 2: Add SARIF for Code Scanning”SARIF integration puts findings directly in GitHub’s Security tab:
- name: Generate SARIF if: always() run: | jq '{ "$schema": "https://json.schemastore.org/sarif-2.1.0.json", version: "2.1.0", runs: [{ tool: { driver: { name: "Fleet CRA Scanner", version: .catalog.version } }, results: [.findings[] | select(.source_locations and (.source_locations | length) > 0) | { ruleId: .requirement_id, message: { text: .message }, level: (if .status == "fail" then "error" else "warning" end), locations: [.source_locations[] | { physicalLocation: { artifactLocation: { uri: .file }, region: { startLine: .line } } }] }] }] }' $RUNNER_TEMP/results.json > $RUNNER_TEMP/results.sarif
- name: Upload SARIF if: always() uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/results.sarifStep 3: Add Compliance Gate
Section titled “Step 3: Add Compliance Gate”Make the scan fail PRs with critical findings:
- name: Compliance Gate run: | FAIL=$(jq '.summary.fail' $RUNNER_TEMP/results.json) if [ "$FAIL" -gt 0 ]; then echo "::error::CRA compliance failed: $FAIL findings" exit 1 fiThen in repository Settings > Branches > Branch protection:
- Enable “Require status checks to pass”
- Add “CRA Compliance / cra-scan” as required
Step 4: Add PR Summary
Section titled “Step 4: Add PR Summary”The --ci flag automatically detects GitHub Actions and adds a Job Summary:
### Fleet CRA Assessment
| Metric | Count ||--------|-------|| Total | 152 || Pass | 55 || Fail | 40 || Needs Review | 57 |Step 5: Evidence Retention
Section titled “Step 5: Evidence Retention”CRA requires 10-year evidence retention. The workflow above uses retention-days: 3650 (10 years) for artifacts. For additional security, upload results to the Fleet API:
- name: Upload to Fleet if: github.ref == 'refs/heads/main' env: FLEET_API_URL: ${{ secrets.FLEET_API_URL }} FLEET_API_KEY: ${{ secrets.FLEET_API_KEY }} run: | fleet scan --path . --ci \ --api-url $FLEET_API_URL \ --api-key $FLEET_API_KEYResult
Section titled “Result”After setup, every PR shows:
- CRA compliance check status (pass/fail)
- Findings in GitHub Code Scanning (Security tab)
- Summary in the Actions job log
- Evidence artifacts retained for 10 years