Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 0 additions & 115 deletions .github/workflows/_build-reusable.yml

This file was deleted.

13 changes: 5 additions & 8 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,15 @@ permissions:
contents: read

jobs:
analyze:
name: Analyze (${{ matrix.language }})
# CONTRACT: org ruleset requires this exact check name 'codeql'
# Do NOT add a 'name:' override or matrix strategy
codeql:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
actions: read
security-events: write
contents: read
strategy:
fail-fast: false
matrix:
language: ["python"]

steps:
- name: Harden runner
Expand All @@ -40,7 +37,7 @@ jobs:
- name: Initialize CodeQL
uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with:
languages: ${{ matrix.language }}
languages: python
queries: +security-extended

- name: Autobuild
Expand All @@ -49,4 +46,4 @@ jobs:
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with:
category: "/language:${{ matrix.language }}"
category: "/language:python"
3 changes: 2 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ permissions: {}

jobs:
build:
uses: ./.github/workflows/_build-reusable.yml
uses: Project-Navi/.github/.github/workflows/_build-reusable.yml@6c4c2d8f200b1b9c3bd651ebc297425e45d5934e
with:
tag_name: ${{ github.ref_name }}
package_name: navi_bootstrap
permissions:
contents: write
id-token: write
Expand Down
73 changes: 5 additions & 68 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,81 +7,18 @@ on:
- cron: "15 6 * * 1" # Monday 06:15 UTC
workflow_dispatch:

permissions: read-all
permissions: {}

concurrency:
group: scorecard
cancel-in-progress: false

jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
timeout-minutes: 15
scorecard:
uses: Project-Navi/.github/.github/workflows/scorecard.yml@6c4c2d8f200b1b9c3bd651ebc297425e45d5934e
permissions:
contents: read
security-events: write
id-token: write
actions: read
steps:
- name: Harden runner
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
with:
egress-policy: audit

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ secrets.SCORECARD_TOKEN || secrets.GITHUB_TOKEN }}

- name: Run Scorecard
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
repo_token: ${{ secrets.SCORECARD_TOKEN || secrets.GITHUB_TOKEN }}
results_file: results.sarif
results_format: sarif
publish_results: true

- name: Upload SARIF to Security tab
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with:
sarif_file: results.sarif

badge:
name: Update badge
needs: analysis
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ secrets.SCORECARD_TOKEN || secrets.GITHUB_TOKEN }}

- name: Run Scorecard (JSON)
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
repo_token: ${{ secrets.SCORECARD_TOKEN || secrets.GITHUB_TOKEN }}
results_file: results.json
results_format: json
publish_results: false

- name: Generate badge
run: |
SCORE=$(jq -r '.score' results.json)
SCORE_INT=${SCORE%.*}
if [ "$SCORE_INT" -ge 8 ]; then COLOR=brightgreen
elif [ "$SCORE_INT" -ge 6 ]; then COLOR=green
elif [ "$SCORE_INT" -ge 4 ]; then COLOR=yellowgreen
else COLOR=red; fi
mkdir -p .github/badges
curl -sf "https://img.shields.io/badge/openssf_scorecard-${SCORE}-${COLOR}" -o .github/badges/scorecard.svg

- name: Commit badge
run: |
git add .github/badges/scorecard.svg
git diff --cached --quiet && exit 0
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git commit -m "ci: update scorecard badge [skip ci]"
git pull --rebase
git push || echo "::warning::Scorecard badge push failed -- will retry on next run"
secrets: inherit
82 changes: 78 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ concurrency:
permissions: {}

jobs:
test:
# ── Test matrix (NOT a required check) ──────────────────────────────
test-run:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
Expand Down Expand Up @@ -53,6 +54,23 @@ jobs:
files: coverage.xml
fail_ci_if_error: false

# ── Required check: test (aggregator) ───────────────────────────────
# CONTRACT: org ruleset requires this exact check name
test:
needs: test-run
if: always()
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Check matrix results
run: |
if [ "${{ needs.test-run.result }}" != "success" ]; then
echo "::error::Test matrix failed"
exit 1
fi

# ── Required check: lint ────────────────────────────────────────────
# CONTRACT: org ruleset requires this exact check name
lint:
runs-on: ubuntu-latest
timeout-minutes: 10
Expand Down Expand Up @@ -85,12 +103,39 @@ jobs:
- name: Format check
run: uv run ruff format --check src/navi_bootstrap/ tests/

- name: Security scan
run: uv run bandit -r src/navi_bootstrap -ll
# ── Required check: typecheck ───────────────────────────────────────
# CONTRACT: org ruleset requires this exact check name
typecheck:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Harden runner
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
with:
egress-policy: audit

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"

- name: Set up uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v5.4.2
with:
enable-cache: true

- name: Install dependencies
run: uv sync

- name: Type check
run: uv run mypy src/navi_bootstrap/

# ── Required check: security ────────────────────────────────────────
# CONTRACT: org ruleset requires this exact check name
security:
runs-on: ubuntu-latest
timeout-minutes: 10
Expand All @@ -101,16 +146,45 @@ jobs:
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
with:
egress-policy: audit

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"

- name: Set up uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v5.4.2
with:
enable-cache: true

- name: Install dependencies
run: uv sync
- name: pip-audit

- name: Security scan (bandit)
run: uv run bandit -r src/navi_bootstrap -ll

- name: Audit dependencies (pip-audit)
run: uvx pip-audit==2.9.0

# ── Required check: quality-gate ────────────────────────────────────
# CONTRACT: org ruleset requires this exact check name
quality-gate:
needs: [test, lint, typecheck, security]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Check all required jobs passed
run: |
for result in \
"${{ needs.test.result }}" \
"${{ needs.lint.result }}" \
"${{ needs.typecheck.result }}" \
"${{ needs.security.result }}"; do
if [ "$result" != "success" ]; then
echo "::error::Required job failed: $result"
exit 1
fi
done
Loading