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
38 changes: 24 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
fetch-depth: 0 # full history so diff-cover can diff the PR against origin/develop (#286)
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.11"
Expand All @@ -29,13 +30,16 @@ jobs:
export UV_INSTALL_DIR="$HOME/.local/bin" # deterministic install dir (runners may set CARGO_HOME)
curl -LsSf https://astral.sh/uv/0.10.10/install.sh | sh
echo "$UV_INSTALL_DIR" >> "$GITHUB_PATH"
- name: Run pytest with coverage gate (deps from uv.lock)
working-directory: build/dashboard
run: uv run --locked --extra test python -m pytest --cov=mining_dashboard --cov-report=term-missing --cov-fail-under=80
- name: Dashboard tests + coverage gate (emits coverage.xml)
run: make test-dashboard
- name: "Patch-coverage gate — changed lines >=90% (diff-cover vs origin/develop, #286)"
run: |
git fetch --no-tags origin develop
make test-patch-coverage
- name: Fake-daemon contract test (real clients vs controllable fakes)
# Points the real Monero/Tari clients at the integration fakes and asserts they parse
# every state (synced/syncing/down). Docker-free, so it runs on every PR (issue #54).
run: uv run --locked --project build/dashboard --extra test python -m pytest tests/integration/fakes -q
run: make test-fakes

frontend:
name: Frontend logic tests (node --test)
Expand Down Expand Up @@ -100,11 +104,12 @@ jobs:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Install hadolint
- name: "Install hadolint (pinned + sha256-verified, #286)"
run: |
sudo curl -fsSL -o /usr/local/bin/hadolint \
curl -fsSL -o /tmp/hadolint \
https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64
sudo chmod +x /usr/local/bin/hadolint
echo "56de6d5e5ec427e17b74fa48d51271c7fc0d61244bf5c90e828aab8362d55010 /tmp/hadolint" | sha256sum -c -
sudo install -m 0755 /tmp/hadolint /usr/local/bin/hadolint
- name: Lint all build/* Dockerfiles (config in .hadolint.yaml)
run: hadolint build/*/Dockerfile

Expand Down Expand Up @@ -173,15 +178,20 @@ jobs:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: "Install shfmt (pinned — RigForge convention, #281)"
- name: "Install shellcheck + shfmt (pinned + sha256-verified, #286)"
# Direct upstream-release downloads with a sha256 check (RigForge convention) instead of the
# runner's preinstalled shellcheck / apt — reproducible, and immune to the apt-mirror
# flakiness of #64. Keep these pins in sync with the local-dev tooling.
run: |
sudo curl -fsSL -o /usr/local/bin/shfmt \
curl -fsSL -o /tmp/shfmt \
https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_linux_amd64
sudo chmod +x /usr/local/bin/shfmt
# shellcheck is preinstalled on ubuntu-* runners, so we invoke it directly.
# Avoid `apt-get update`, which refreshes every configured source (incl.
# unrelated third-party mirrors like dl.google.com) and intermittently fails
# the job when one is briefly out of sync — see issue #64.
echo "fb096c5d1ac6beabbdbaa2874d025badb03ee07929f0c9ff67563ce8c75398b1 /tmp/shfmt" | sha256sum -c -
sudo install -m 0755 /tmp/shfmt /usr/local/bin/shfmt
curl -fsSL -o /tmp/sc.tar.xz \
https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz
echo "8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198 /tmp/sc.tar.xz" | sha256sum -c -
tar -xJf /tmp/sc.tar.xz -C /tmp
sudo install -m 0755 /tmp/shellcheck-v0.11.0/shellcheck /usr/local/bin/shellcheck
- name: Lint pithead, build/* container scripts, and test scripts (shellcheck + shfmt)
# Single source of truth: the Makefile `lint-sh` target (so the file list can't drift
# between here and the Makefile). Covers build/*/*.sh — the entrypoints + healthchecks that
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ __pycache__/
*.pyc
.pytest_cache/
.coverage
coverage.xml
htmlcov/
*.egg-info/
.eggs/
Expand Down
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ then runs `ruff` (plus a few hygiene hooks) on your changed files. If you change
non-Python tools run via `npx`/`uvx`/`docker`, so a contributor needs **Node, uv, and Docker**
on PATH (plus `shfmt`); `pre-commit` runs the same checks on changed files. Link-checking
(`lychee`) runs on a weekly schedule, not per-PR.
- **test-dashboard** — the dashboard `pytest` suite (must stay ≥ the **80% coverage gate**).
- **test-dashboard** — the dashboard `pytest` suite (must stay ≥ the **80% total coverage gate**).
CI also runs **`make test-patch-coverage`** (`diff-cover`): new/changed lines must be **≥ 90%**
covered vs `origin/develop` — the real ratchet that stops coverage rotting at the margin.
- **test-stack** — the `pithead` shell test suite.
- **test-compose** — `docker-compose.yml` interpolation validation.
- **test-integration-selftest** — the integration harness's own pure logic.
Expand Down
10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# Local test entry points (mirror the GitHub Actions CI jobs).
.PHONY: test test-dashboard test-stack test-compose test-integration test-integration-selftest test-fakes test-mini-stack lint lint-sh lint-py lint-js lint-yaml lint-md lint-proto lint-toml release
.PHONY: test test-dashboard test-patch-coverage test-stack test-compose test-integration test-integration-selftest test-fakes test-mini-stack lint lint-sh lint-py lint-js lint-yaml lint-md lint-proto lint-toml release

test: lint test-dashboard test-stack test-compose test-integration-selftest test-fakes ## Run everything that doesn't need a server/docker

test-dashboard: ## Dashboard unit/component tests with coverage gate (deps from uv.lock)
test-dashboard: ## Dashboard unit/component tests with coverage gate (deps from uv.lock); emits coverage.xml
cd build/dashboard && uv run --locked --extra test python -m pytest \
--cov=mining_dashboard --cov-report=term-missing --cov-fail-under=80
--cov=mining_dashboard --cov-report=term-missing --cov-report=xml --cov-fail-under=80

test-patch-coverage: ## diff-cover (#286): new/changed lines must be >=90% covered (run after test-dashboard)
cd build/dashboard && uv run --locked --extra test \
diff-cover coverage.xml --compare-branch=origin/develop --fail-under=90

test-stack: ## pithead shell test suite
bash tests/stack/run.sh
Expand Down
2 changes: 2 additions & 0 deletions build/dashboard/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ test = [
"pytest-mock>=3.14",
"pytest-cov>=5",
"pytest-aiohttp>=1.0",
# diff-cover (#286): patch-coverage gate — new/changed lines must be >=90% covered.
"diff-cover>=9",
]
# Developer tooling (Wave 7, #280). Pinned so local, pre-commit, and CI all run the SAME ruff
# — lint output is version-sensitive, so a floor would let CI and a contributor disagree.
Expand Down
Loading