From f1fe458216423e99e0b80a9e1517c8cb3076b5de Mon Sep 17 00:00:00 2001 From: itzzdev09 Date: Sun, 13 Sep 2026 22:47:59 +0530 Subject: [PATCH 1/3] ci: run tests, lint, bandit, TUI and viewer checks on pull requests The only workflow ran on version tags, so a change could merge without any of the documented checks ever running in GitHub Actions. Add a Checks workflow for pull requests and pushes to main: - ruff check and ruff format --check, using the ruff pinned in uv.lock - bandit with the project config - pytest on every supported Python version (3.12, 3.13, 3.14) - gofmt, go vet and go test -race for the TUI, as in `make tui-lint` and `make tui-test` - a production build of the viewer No job changes files, and none is marked required: #1260's rollout is to land the checks, clear any baseline failure, then require each green check. Type checking stays in typecheck.yml. Refs #1260 Co-Authored-By: Claude Opus 5 --- .github/workflows/checks.yml | 151 +++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 .github/workflows/checks.yml diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 000000000..52c326d1c --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,151 @@ +name: Checks + +# Pull-request validation for #1260. None of these jobs change files, and none +# are required yet: the issue's rollout is to land the checks, clear any +# baseline failure, and only then mark each green check required. +# +# Type checking lives in typecheck.yml, which runs mypy per platform. + +on: + pull_request: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ruff: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false + + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + + - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 + + - name: Install dependencies + run: uv sync --frozen + + # `uv run` uses the ruff pinned in uv.lock, not the older rev in + # .pre-commit-config.yaml, so this matches `make lint` minus --fix. + - name: ruff check + run: uv run ruff check . + + - name: ruff format --check + run: uv run ruff format --check . + + bandit: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false + + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + + - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 + + - name: Install dependencies + run: uv sync --frozen + + - name: bandit + run: uv run bandit -r strix/ -c pyproject.toml + + pytest: + name: pytest (python ${{ matrix.python-version }}) + + strategy: + fail-fast: false + matrix: + # Every version pyproject.toml classifies as supported. + python-version: + - '3.12' + - '3.13' + - '3.14' + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false + + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: ${{ matrix.python-version }} + + - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 + + - name: Install dependencies + run: uv sync --frozen --python ${{ matrix.python-version }} + + - name: pytest + run: uv run --python ${{ matrix.python-version }} pytest -q + + tui: + name: TUI (gofmt, vet, test) + runs-on: ubuntu-latest + + defaults: + run: + working-directory: strix/interface/tui + + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false + + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 + with: + go-version-file: strix/interface/tui/go.mod + cache-dependency-path: strix/interface/tui/go.sum + + # Same commands as `make tui-lint` and `make tui-test`. + - name: gofmt + run: test -z "$(gofmt -l .)" + + - name: go vet + run: go vet ./... + + - name: go test + run: go test -race ./... + + viewer: + name: viewer build + runs-on: ubuntu-latest + + defaults: + run: + working-directory: strix/interface/viewer/frontend + + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false + + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: '24' + + # Build only. Whether the committed output under static/ must match a + # fresh build is a separate policy, so this does not diff against it. + - name: npm ci + run: npm ci --no-audit --no-fund + + - name: npm run build + run: npm run build From 76267dc97e3e10cd31f31d6b568c4ff63c716054 Mon Sep 17 00:00:00 2001 From: itzzdev09 Date: Mon, 14 Sep 2026 12:17:13 +0530 Subject: [PATCH 2/3] fix(pricing): prefer the direct provider when resellers list the same price LiteLLM's cost map now lists grok-4.5 under xai/, perplexity/xai/ and openrouter/x-ai/ at identical prices, so alphabetical order resolved the bare name to openrouter and failed test_resolves_common_bare_model_names. Co-Authored-By: Claude Opus 5 --- strix/report/pricing.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/strix/report/pricing.py b/strix/report/pricing.py index 57c899592..41f9c1bfa 100644 --- a/strix/report/pricing.py +++ b/strix/report/pricing.py @@ -36,7 +36,12 @@ def resolve_litellm_model(model: str) -> str | None: if "/" in normalized: names.append(normalized.rsplit("/", 1)[-1]) for name in names: - matches = sorted(key for key in model_cost if key.endswith(f"/{name}")) + # Prefer the direct provider (``xai/grok-4.5``) over resellers + # listing the same model (``openrouter/x-ai/grok-4.5``). + matches = sorted( + (key for key in model_cost if key.endswith(f"/{name}")), + key=lambda key: (key.count("/"), key), + ) if not matches: continue prices = { From 1b8835a554de516d7996a594c047688816c9e970 Mon Sep 17 00:00:00 2001 From: itzzdev09 Date: Mon, 14 Sep 2026 16:03:12 +0530 Subject: [PATCH 3/3] ci: describe type checking as proposed separately, not present The workflow comment said type checking lives in typecheck.yml, which only exists in the unmerged #1301, so it implied pull requests already get type-check coverage. Co-Authored-By: Claude Opus 5 --- .github/workflows/checks.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 52c326d1c..0e5bd1fb9 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -4,7 +4,8 @@ name: Checks # are required yet: the issue's rollout is to land the checks, clear any # baseline failure, and only then mark each green check required. # -# Type checking lives in typecheck.yml, which runs mypy per platform. +# Type checking is not covered here; a per-platform mypy workflow is proposed +# separately in #1301. on: pull_request: