Add a CI workflow, mirroring invoiceninja-sdk's job for job
Now that the SDK dependency resolves from crates.io instead of a sibling checkout, a workflow here needs nothing special to build. Same three jobs as the SDK's own ci.yml: pinned-toolchain test, a build-only msrv job on the declared 1.88 floor, and an advisory stable job that reports red but stays out of required status checks. Verified locally: all four `test`-job commands pass with the pinned 1.99.1 toolchain, and a build+test against an actual rustc 1.88.0 toolchain confirms the msrv job will be green too. Resolves the "own CI" open question in GOALS.md into goal 6; adds the matching "Rust version and CI" section to CLAUDE.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
# Mondays 06:00 UTC. A new Rust release lands on its own schedule, so
|
||||||
|
# without this the advisory `stable` job below only runs when someone
|
||||||
|
# happens to push, and breakage can sit unnoticed for weeks.
|
||||||
|
- cron: '0 6 * * 1'
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Nothing it covers can change on a timer: the toolchain is pinned and
|
||||||
|
# the dependencies are locked. The weekly run is for `stable` only.
|
||||||
|
if: github.event_name != 'schedule'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# Pinned, and kept in step with `devVersion` in flake.nix (which in
|
||||||
|
# turn tracks invoiceninja-sdk's own `devVersion`), so CI and the dev
|
||||||
|
# shell agree and a new stable release cannot turn a lint failure
|
||||||
|
# into an unrelated red build.
|
||||||
|
- uses: dtolnay/rust-toolchain@1.99.1
|
||||||
|
with:
|
||||||
|
components: rustfmt, clippy
|
||||||
|
- run: cargo build --all-targets
|
||||||
|
- run: cargo test
|
||||||
|
- run: cargo fmt --check
|
||||||
|
- run: cargo clippy --all-targets -- -D warnings
|
||||||
|
|
||||||
|
msrv:
|
||||||
|
name: Build on the declared MSRV
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name != 'schedule'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# Must match `rust-version` in Cargo.toml, which in turn is pinned to
|
||||||
|
# invoiceninja-sdk's own MSRV (see the comment there). Build only —
|
||||||
|
# lint and format output varies by release, and pinning those to the
|
||||||
|
# oldest supported toolchain is not useful.
|
||||||
|
- uses: dtolnay/rust-toolchain@1.88.0
|
||||||
|
- run: cargo test
|
||||||
|
|
||||||
|
stable:
|
||||||
|
name: Latest stable (advisory)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Deliberately NOT `continue-on-error`: a failure here should render as
|
||||||
|
# a real red X, not a green check with an annotation nobody reads.
|
||||||
|
#
|
||||||
|
# This job is advisory all the same — it tracks a moving toolchain, so a
|
||||||
|
# new clippy lint can break it through no fault of the change under
|
||||||
|
# test. **Keep it out of the required status checks** in branch
|
||||||
|
# protection; that, rather than a flag in this file, is what stops it
|
||||||
|
# blocking merges. Expect it red sometimes, and fix it when bumping
|
||||||
|
# `devVersion`.
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
components: clippy
|
||||||
|
- run: cargo test
|
||||||
|
- run: cargo clippy --all-targets -- -D warnings
|
||||||
@@ -71,6 +71,43 @@ matching package named `invoiceninja-sdk` found" or an unresolved
|
|||||||
`../invoiceninjars-sdk/Cargo.toml`'s `[package] name`, if you have a
|
`../invoiceninjars-sdk/Cargo.toml`'s `[package] name`, if you have a
|
||||||
checkout) first.
|
checkout) first.
|
||||||
|
|
||||||
|
### Rust version and CI
|
||||||
|
|
||||||
|
| | Version | Declared in |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Dev toolchain | 1.99.1 | `devVersion` in `flake.nix`, `test` job in `.github/workflows/ci.yml` |
|
||||||
|
| MSRV | 1.88 | `rust-version` in `Cargo.toml` (inherited from the SDK's own floor — see the comment there), `msrv` job in `ci.yml` |
|
||||||
|
|
||||||
|
Unlike `invoiceninjars-sdk`'s `flake.nix`, this crate's has no separate
|
||||||
|
`msrvVersion`/toolchain — the `msrv` CI job is the only place 1.88 actually
|
||||||
|
gets built against, not a Nix devShell. If that ever earns its keep, mirror
|
||||||
|
the SDK's `msrvToolchain`/`shellFor` pattern rather than inventing a new one.
|
||||||
|
|
||||||
|
CI runs on GitHub Actions, against the GitHub push mirror (Gitea is
|
||||||
|
canonical — see `.gitea`/remote config — but Actions run on GitHub, the
|
||||||
|
same arrangement as `invoiceninjars-sdk`'s own CI). Three jobs, mirroring
|
||||||
|
the SDK's `ci.yml` job-for-job:
|
||||||
|
|
||||||
|
- **`test`** — the pinned dev toolchain; `cargo build --all-targets`,
|
||||||
|
`cargo test`, `cargo fmt --check`, `cargo clippy --all-targets -- -D
|
||||||
|
warnings`.
|
||||||
|
- **`msrv`** — build and test only, on the declared 1.88 floor. No lint or
|
||||||
|
format check: those vary by release, and pinning them to the oldest
|
||||||
|
supported toolchain isn't useful.
|
||||||
|
- **`stable`** (advisory) — latest stable `rustc`, runs on push/PR and
|
||||||
|
weekly via `schedule` (Mondays 06:00 UTC) so a new Rust release that
|
||||||
|
breaks the build or fires a new clippy lint doesn't sit unnoticed for
|
||||||
|
weeks between pushes. Deliberately **not** `continue-on-error` — a real
|
||||||
|
red X, not a silent annotation — so if branch protection ever requires
|
||||||
|
status checks, keep `stable` **out** of the required list; that setting,
|
||||||
|
not anything in `ci.yml`, is what should stop it blocking merges. Expect
|
||||||
|
it red occasionally through no fault of the change under test, and fix it
|
||||||
|
when bumping `devVersion`.
|
||||||
|
|
||||||
|
The `test` and `msrv` jobs skip scheduled runs (`if: github.event_name !=
|
||||||
|
'schedule'`) — a pinned toolchain against a locked dependency graph can't
|
||||||
|
change on a timer, so the weekly run is for `stable` only.
|
||||||
|
|
||||||
## Common commands
|
## Common commands
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -67,6 +67,16 @@ the SDK doesn't already consider safe. If the SDK decides `POST` isn't
|
|||||||
replayed on a 5xx because it might double-create an invoice, that reasoning
|
replayed on a 5xx because it might double-create an invoice, that reasoning
|
||||||
applies here unchanged — the CLI is not a place to relax it for convenience.
|
applies here unchanged — the CLI is not a place to relax it for convenience.
|
||||||
|
|
||||||
|
### 6. CI mirrors the SDK's, job for job
|
||||||
|
|
||||||
|
`.github/workflows/ci.yml` has the same three jobs as `invoiceninjars-sdk`'s
|
||||||
|
own — pinned-toolchain `test`, build-only `msrv` on the declared floor, and
|
||||||
|
an advisory `stable` that reports red but stays out of required status
|
||||||
|
checks — rather than inventing a different shape for this crate. See
|
||||||
|
`CLAUDE.md`'s "Rust version and CI" for the per-job reasoning; a deviation
|
||||||
|
from this shape should be written down there the same way `update`'s
|
||||||
|
exception is written down in goal 1.
|
||||||
|
|
||||||
## Non-goals
|
## Non-goals
|
||||||
|
|
||||||
- **No Cargo workspace with the SDK.** Explained in `CLAUDE.md`: the SDK is
|
- **No Cargo workspace with the SDK.** Explained in `CLAUDE.md`: the SDK is
|
||||||
@@ -111,12 +121,6 @@ These are genuinely undecided; deciding one is a change to this file.
|
|||||||
`--param key=value` for the rest. A per-resource convenience filter (e.g.
|
`--param key=value` for the rest. A per-resource convenience filter (e.g.
|
||||||
a `--unpaid` shorthand for `client_status=unpaid`) would read nicer but
|
a `--unpaid` shorthand for `client_status=unpaid`) would read nicer but
|
||||||
means hand-picking which filters earn a dedicated flag per resource.
|
means hand-picking which filters earn a dedicated flag per resource.
|
||||||
- **Whether this crate gets its own CI.** No longer blocked on needing a
|
|
||||||
sibling checkout — the SDK dependency switched from a path to a crates.io
|
|
||||||
version requirement (`invoiceninja-sdk = "0.2.0"`) once 0.2.0 was published
|
|
||||||
on 2026-10-25. A workflow here can now just `cargo build` against the
|
|
||||||
registry like any other Rust project; it doesn't need to check out
|
|
||||||
`invoiceninjars-sdk` at all.
|
|
||||||
- **Whether the Nix packaging goes further than this repo's own flake.**
|
- **Whether the Nix packaging goes further than this repo's own flake.**
|
||||||
`flake.nix` now has `packages.default`/`devShells.default` (built with a
|
`flake.nix` now has `packages.default`/`devShells.default` (built with a
|
||||||
pinned `rust-overlay` toolchain, for parity between `nix build` and
|
pinned `rust-overlay` toolchain, for parity between `nix build` and
|
||||||
|
|||||||
Reference in New Issue
Block a user