Merge pull request #98 from LinuxJedi/test/cputest-cycles #2
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: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| build-test: | |
| name: Build, test, lint | |
| # Copperline is developed and tested on macOS; the Linux and Windows | |
| # paths are not yet verified, so CI runs on macOS to match. The runner's | |
| # Metal stack also makes the headless render path (the smoke job below) | |
| # reliable. Linux/Windows jobs can be added once those paths are verified. | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Formatting | |
| # Not --all: that would reach into the vendored MIT m68k crate, which | |
| # keeps its own formatting. | |
| run: cargo fmt --check | |
| - name: Clippy | |
| # Hold the binary, tests, examples, and diagnostic feature gates to | |
| # the same warning-clean standard used for release checks. | |
| run: cargo clippy --all-targets --all-features --locked -- -D warnings | |
| - name: Build (release) | |
| run: cargo build --release --locked | |
| - name: Unit tests | |
| # The integration tests under tests/ are #[ignore]d and need local | |
| # ROM/disk assets, so they are intentionally not run here; this is | |
| # the asset-free unit suite, which also proves a clean checkout | |
| # builds and tests without the gitignored vendor fixtures. | |
| run: cargo test --release --locked | |
| - name: m68k core tests | |
| # The vendored CPU core (crates/m68k) is a path dependency, not a | |
| # workspace member, so the root `cargo test` above never reaches its | |
| # suites -- including the MMU walker, access-fault frame, exception, | |
| # and per-model architecture tests. Two suites are excluded because | |
| # they include_bytes! gitignored fixture binaries and do not compile | |
| # on a clean checkout (cross_cpu, musashi); the SingleStepTests | |
| # suite compiles and skips itself here, and runs for real in the | |
| # m68k-singlestep job below. No --locked: the crate's own Cargo.lock | |
| # is deliberately gitignored (the root lockfile pins it when built | |
| # as a dependency). | |
| working-directory: crates/m68k | |
| run: | | |
| ls tests/*.rs | xargs -n1 basename | sed 's/\.rs$//' \ | |
| | grep -v -e '^cross_cpu_tests$' -e '^musashi_tests$' \ | |
| | sed 's/^/--test /' \ | |
| | xargs cargo test --release --lib | |
| m68k-singlestep: | |
| name: m68k SingleStepTests (68000 fixtures) | |
| # Runs the per-instruction 68000 fixture suite against the real | |
| # SingleStepTests data (MIT, generated from MAME's microcoded core): | |
| # every opcode's final register/memory state, plus address-error | |
| # behavior. The fixture clone is ~1 GB, so it lives in its own job and | |
| # does not gate the main build. | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Fetch SingleStepTests m68000 fixtures | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: SingleStepTests/m68000 | |
| path: sst-m68000 | |
| - name: Run fixture suite | |
| working-directory: crates/m68k | |
| env: | |
| M68K_SST_FIXTURES: ${{ github.workspace }}/sst-m68000/v1 | |
| run: cargo test --release --test singlestep_m68000_v1_tests | |
| docs: | |
| name: Docs build (HTML + PDF) | |
| # Independent of the Rust build: catches MyST/cross-reference breakage | |
| # (e.g. duplicate labels that only collide in the single-document PDF). | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install MyST CLI | |
| run: npm install -g mystmd | |
| - name: Install Typst (PDF renderer) | |
| # MyST shells out to Typst for PDF export; brew matches docs/README.md. | |
| run: brew install typst | |
| - name: Build HTML | |
| working-directory: docs | |
| run: myst build --html --ci --strict --check-links | |
| - name: Build PDF | |
| working-directory: docs | |
| # The PDF export merges every chapter into one document, so it is the | |
| # build that surfaces duplicate-label and cross-reference errors. | |
| # Assert the artifact exists and is non-empty so the job fails even if | |
| # the CLI ever returns success on a partial render. | |
| run: | | |
| myst build --pdf --ci --strict | |
| test -s _build/exports/copperline.pdf | |
| - name: Upload PDF | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: copperline-docs-pdf | |
| path: docs/_build/exports/copperline.pdf | |
| if-no-files-found: ignore | |
| gdb-remote: | |
| name: GDB remote protocol tests | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: RSP unit tests | |
| run: cargo test --locked gdbstub | |
| diagrom-smoke: | |
| name: DiagROM boot smoke | |
| needs: build-test | |
| runs-on: macos-latest | |
| # Opt-in. DiagROM is freely redistributable but not committed, so CI | |
| # fetches it at run time. Set the DIAGROM_URL repository variable to a | |
| # direct URL for the DiagROM ROM image to enable this job; until then it | |
| # is skipped. | |
| if: ${{ vars.DIAGROM_URL != '' }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Build (release) | |
| run: cargo build --release --locked | |
| - name: Fetch DiagROM | |
| run: curl -fsSL "${{ vars.DIAGROM_URL }}" -o diagrom.rom | |
| - name: Boot smoke (headless screenshot) | |
| # No config and no positional ROM: the built-in defaults point at | |
| # ./diagrom.rom, so this boots DiagROM, renders a frame after 6 | |
| # emulated seconds, and exits. A non-empty PNG means it booted | |
| # without halting. | |
| run: | | |
| ./target/release/copperline --noaudio --screenshot-after 6 diag.png | |
| test -s diag.png | |
| - name: Upload boot screenshot | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: diagrom-boot | |
| path: diag.png | |
| if-no-files-found: ignore |