Repository navigation
CI #92
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: CI | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| schedule: | |
| # Daily 01:00 UTC — catches advisories that drop between PRs. | |
| - cron: '0 1 * * *' | |
| concurrency: | |
| # One live run per ref. A fresh push to the same PR / branch cancels | |
| # the in-flight run so we don't pay for stale CI. | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| rust: | |
| name: Rust checks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # The rust-toolchain.toml at the repo root pins the channel and the | |
| # required components (clippy, rustfmt). The action reads it, so no | |
| # explicit `toolchain: stable` here. | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy, rustfmt | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Format (rustfmt --check) | |
| run: cargo fmt --all -- --check | |
| - name: Unit tests (lib) | |
| run: cargo test --lib --locked | |
| - name: Clippy gate | |
| # Mirrors the canonical acceptance command pinned in | |
| # devflow-docs/backlog.md (BL-P2-063). Keeping `--lib --tests` | |
| # means test-site regressions can't hide behind the main gate. | |
| # `--locked` matches the test/build steps so a drifted Cargo.lock | |
| # can't silently change the dep tree clippy inspects. | |
| run: cargo clippy --lib --tests --locked -- -D warnings | |
| - name: Binary compile | |
| # The lib-only tests miss `src/main.rs`; compile the bin | |
| # explicitly so a stale main.rs can't merge. | |
| run: cargo build --bin nexttui --locked | |
| audit: | |
| name: Dependency audit (cargo audit) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: rustsec/audit-check@v2 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| # Ownership: BL-P2-080 and BL-P2-081 share this job. Whichever PR merges | |
| # first is the job owner — the other PR only needs `needs: devstack-integration`. | |
| # The `if: false` placeholder below is removed once an actual devstack image | |
| # digest is pinned (see BL-P2-081 activation checklist in backlog.md). | |
| devstack-integration: | |
| name: Devstack integration gate (BL-P2-080 FR-8) | |
| runs-on: ubuntu-latest | |
| # Dedicated concurrency group so a fresh push to the same branch/PR | |
| # cancels the in-flight devstack run without touching the fast `rust` job. | |
| concurrency: | |
| group: devstack-integration-${{ github.ref }} | |
| cancel-in-progress: true | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| # ------------------------------------------------------------------ | |
| # Step: start devstack container | |
| # ------------------------------------------------------------------ | |
| # PLACEHOLDER: The devstack docker image digest has NOT been verified | |
| # in this environment. This step is disabled (`if: false`) until the | |
| # actual image digest is confirmed by the devstack infra owner | |
| # (BL-P2-081 coordination or manual pinning). | |
| # | |
| # When the digest is known, replace the placeholder tag and remove the | |
| # `if: false` guard. Everything else (healthcheck, log upload, test | |
| # invocation) is already wired and will activate automatically. | |
| # | |
| # TODO: pin actual devstack image — BL-P2-080 CI gate | |
| # ------------------------------------------------------------------ | |
| - name: Start devstack container (PLACEHOLDER — currently disabled) | |
| id: devstack-setup | |
| if: false # Disabled until image digest is confirmed (BL-P2-081) | |
| run: | | |
| docker run -d \ | |
| --name devstack \ | |
| -p 5000:5000 \ | |
| -p 5001:5001 \ | |
| opendevstack/devstack:placeholder | |
| # TODO: replace `placeholder` with a pinned tag or digest, e.g.: | |
| # opendevstack/devstack@sha256:<verified-digest> | |
| # Floating `latest` is intentionally forbidden (supply-chain safety). | |
| # ------------------------------------------------------------------ | |
| # Step: wait for Keystone endpoint to become healthy | |
| # ------------------------------------------------------------------ | |
| # This step is also gated on the container being up. It runs only | |
| # when `devstack-setup` ran (i.e., when `if: false` is lifted above). | |
| - name: Wait for Keystone endpoint (localhost:5000) | |
| id: devstack-health | |
| if: steps.devstack-setup.outcome == 'success' | |
| run: | | |
| echo "Waiting for Keystone at localhost:5000 (max 120s)…" | |
| deadline=$(($(date +%s) + 120)) | |
| until nc -z localhost 5000 2>/dev/null; do | |
| if [ "$(date +%s)" -ge "$deadline" ]; then | |
| echo "ERROR: Keystone did not become ready within 120s" | |
| exit 1 | |
| fi | |
| sleep 2 | |
| done | |
| echo "Keystone is up." | |
| # ------------------------------------------------------------------ | |
| # Step: run devstack integration tests | |
| # ------------------------------------------------------------------ | |
| # Requires DEVSTACK_URL and DEVSTACK_TOKEN injected from GHA secrets | |
| # (set up as repo/env secrets when the container is activated). | |
| - name: Run devstack integration tests | |
| id: devstack-test | |
| if: steps.devstack-health.outcome == 'success' | |
| env: | |
| DEVSTACK_URL: ${{ vars.DEVSTACK_URL }} | |
| DEVSTACK_TOKEN: ${{ secrets.DEVSTACK_TOKEN }} | |
| run: | | |
| cargo test \ | |
| --test devstack_directory \ | |
| --features devstack-integration \ | |
| -- --nocapture | |
| # ------------------------------------------------------------------ | |
| # Step: collect docker logs on any failure | |
| # ------------------------------------------------------------------ | |
| - name: Collect devstack container logs on failure | |
| if: failure() | |
| run: | | |
| docker logs devstack > devstack.log 2>&1 || echo "(container not running)" > devstack.log | |
| - name: Upload devstack logs as artifact | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: devstack-logs-${{ github.run_id }} | |
| path: devstack.log | |
| retention-days: 7 |