Skip to content

Merge pull request #98 from LinuxJedi/test/cputest-cycles #2

Merge pull request #98 from LinuxJedi/test/cputest-cycles

Merge pull request #98 from LinuxJedi/test/cputest-cycles #2

Workflow file for this run

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