Rewrite lintus in Rust, as a single binary - #3
Merged
Merged
Conversation
A Cargo workspace with two crates, jev and lintus, still empty. The lintus crate carries a conformance suite that runs a lintus binary against temporary projects and a fake Jev API, then checks its output, exit status and requests. LINTUS_BIN picks the binary, so the suite runs against the Ruby implementation through test/support/lintus-ruby, where it passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Noul, choice and score questions, with the answers typed after the question they answer. API error statuses map to the same kinds as the Ruby gem, and rate limits are left to the caller to retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The same command line, config file and output as the Ruby gem, as a single binary. The conformance suite passes against both implementations. Glob matching is a port of Ruby's File.fnmatch, and probabilities are rounded and printed as Ruby floats; both are checked against fixtures generated from Ruby. The config file is read with Psych's YAML 1.1 rules (yes/no booleans, 100_000 integers, merge keys), so existing configs mean the same thing. New: `lintus auth login|status|logout` saves the API key in the user's config directory, readable by its owner only. A run takes the key from --api-key, then JEV_API_KEY, then the saved key. JEV_API_URL points the client at another endpoint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Slim container images such as debian:bookworm-slim ship without CA certificates, and every request failed there. The client still prefers the operating system's store, so private CAs keep working. The crate is published as jev-api, since jev is taken on crates.io; its library is still named jev. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pre-commit installs a language: rust hook with `cargo install --path .` at the repository root, which needs a package there rather than a bare workspace. The hook now builds lintus from source, with a Rust toolchain of its own if the machine has none; checked with `pre-commit try-repo`. The conformance harness no longer relies on Unix-only paths, so the suite can run on Windows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Releases: a tag builds static Linux (x86_64, arm64), macOS (Intel, Apple silicon) and Windows binaries with checksums, attaches them to a GitHub release, and publishes jev-api and lintus to crates.io with trusted publishing. It replaces the gem release. - install.sh installs the right binary for the machine and checks its checksum. - The GitHub Action downloads the binary for the runner, the release matching its own tag by default, instead of setting up Ruby. - CI runs the Rust tests on Linux, macOS and Windows, and the conformance suite against the Ruby implementation. - Lintus lints its own Rust code with the Rust binary. - README and CHANGELOG describe installing the binary and `lintus auth`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Running the Release workflow by hand builds and tests every target without releasing, so the matrix can be checked before a tag exists. The CHANGELOG notes the two places the Rust version behaves differently from the gem. The pre-commit hook needs a C compiler, but no Rust: checked in a container without one. RuboCop is clean on the new Ruby helpers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Rust binary passes the conformance suite that the gem passed. Against the real API, both checked the same 19 files, asked the same rules, and reported the same 8 offenses; the probabilities differed only by model noise (at most 0.12) on byte-identical requests. The gem stays published at 0.2.0. The glob fixture generator says which commit to regenerate it from. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tests built the expected credentials path with a / inside, where the binary rightly uses \ on Windows. CI now runs every test binary even when one fails. Lintus flagged crates/jev/src/client.rs in its own self-lint: an encoding failure surfaced a bare serde message, and a response that broke off was reported as the API being unreachable. Both now say what happened. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lintus no longer needs Ruby: it is a single binary, installed from the GitHub releases, with
install.sh, or withcargo install lintus. Config files, flags, output formats and exit statuses are unchanged.What changes
lintus(repository root) is a port of the gem. Glob matching reproduces Ruby'sFile.fnmatch, rounding reproduces Ruby floats, and YAML is read with Psych's rules, so existing.lintus.ymlfiles mean the same thing.jev-api(crates/jev) is a typed Rust client for the Jev API: noul, choice and score questions. It is imported asjev; thejevname is taken on crates.io.lintus auth login | status | logoutsaves the API key in~/.config/lintus/credentials.json, readable by its owner only. A run takes the key from--api-key, thenJEV_API_KEY, then the saved key.v*tag builds static Linux (x86_64, arm64), macOS (Intel, Apple silicon) and Windows binaries with checksums, attaches them to a GitHub release, and publishes both crates. Running the workflow by hand is a dry run.Two behaviours differ from the gem.
--diffand--stagedtogether are now an error. Skipped and failed files are listed in path order.How it was verified
tests/conformance, 53 tests): runs alintusbinary against temporary projects and a fake Jev API, and checks output, exit status and requests byte for byte. It passed against the Ruby gem before the port, and passes unchanged against the Rust binary.busybox,debian:bookworm-slimandalpineimages; the first two have no CA certificates, so the binary falls back to bundled roots.install.shwas tested against a local server, including a tampered archive.pre-commit try-repobuilds and runs the hook on a machine without Rust.Not verified yet
v0.3.0.🤖 Generated with Claude Code