Skip to content

Releases: abdulwahed-sweden/rustio-admin

v0.28.0 — One declaration per model

08 Jun 17:04
v0.28.0
1d377f6

Choose a tag to compare

All four crates ship 0.28.0 (rustio-admin, rustio-admin-macros, rustio-admin-cli, rio-theme).

rustio-admin = "0.28.0"

Changed

  • #[derive(RustioAdmin)] now generates impl Model too. The derive already walked every field to build AdminModel; it now emits the orm::Model impl (TABLE, COLUMNS, INSERT_COLUMNS, id, from_row, insert_values) from the same walk. Models are declared once — the hand-written ORM glue that had to be kept in sync with the struct by hand is gone. Two struct-level escape hatches cover what the field walk can't infer: #[rustio(table = "…")] when the SQL table name differs from the auto slug (e.g. Addressaddresses), and #[rustio(extra_columns = ["…"])] for generated/virtual columns that aren't struct fields (e.g. a Postgres tsvector).
  • Runtime dependencies are re-exported from rustio_admin. chrono, rust_decimal, uuid, and sqlx (plus the Decimal / DateTime / Utc / NaiveDate / NaiveTime / Uuid type aliases) are now re-exported. The derive's generated code routes through these paths, so a model crate can depend on rustio-admin alone; the scaffold's Cargo.toml drops its direct chrono / uuid / rust_decimal / sqlx dependencies. One resolved copy of each, no version skew.

Internal

  • Two drift-guard tests with no machine check before: one asserts the admin.css @import manifest matches the ADMIN_CSS concat!(include_str!(…)) bundle in routes.rs; one asserts rustio_admin_macros::HUMANISE_ACRONYMS is byte-identical to admin::render::HUMANISE_ACRONYMS.

⚠️ Upgrading from 0.27.x (breaking)

  • Delete any hand-written impl Model blocks for types that derive RustioAdmin — they now collide with the generated impl. If a model needs a non-default table name or virtual columns, use the new #[rustio(table = "…")] / #[rustio(extra_columns = ["…"])] attributes instead.
  • You can drop direct chrono / uuid / rust_decimal / sqlx dependencies from a model crate's Cargo.toml and route through rustio_admin's re-exports.

Full changelog: https://github.com/abdulwahed-sweden/rustio-admin/blob/v0.28.0/CHANGELOG.md

v0.27.6 — CSV-import guidance + admin redesign

05 Jun 16:32
v0.27.6
3de8e97

Choose a tag to compare

All four crates ship 0.27.6 (rustio-admin, rustio-admin-macros, rustio-admin-cli, rio-theme).

rustio-admin = "0.27.6"

Fixed

  • CSV import no longer dead-ends on an unrecognised column. A header with columns the model doesn't declare used to return a bare 400 Bad request, even though the importer was already built to skip them. The handler now matches that design: unknown columns are skipped, reported on the result page, and turned into a ready-to-run ALTER TABLE migration plus the matching struct / from_row / insert_values snippet — with column types inferred from the column names. Removes the now-unused ParseError::UnknownColumns variant.

Changed

  • Admin pages restyled. The framework-docs index, the markdown doc viewer, the API surface, the account-sessions page, the audit log, and the CSV-import result page were redesigned with the shared card / badge / glyph component language (page heads, colored status/method badges, avatar cells, typeset documentation prose). Token-only; secondary accents read var(--rio-accent2, var(--rio-accent)) so a project that defines an amber secondary picks it up while the framework default falls back to its accent.

Documentation

  • getting-started.md rewritten example-first; modeladmin.md gains a worked example; cli.md new description corrected.

Internal

  • examples/ reorganised into two admin projects: the canonical multi-crate reference renamed clinic-adminclinic, the unused axum clinic demo dropped, and a new single-crate shop (e-commerce admin) added.

Built with this release

  • shop v0.1.0 — a standalone e-commerce admin example released on this version: nine related models with inline relations, a navy + amber theme, redesigned admin pages, and seeded demo data. See its release notes.

Full changelog: https://github.com/abdulwahed-sweden/rustio-admin/blob/v0.27.6/CHANGELOG.md

v0.22.0 — CLI binary renamed `rustio` → `rustio-admin`

28 May 23:54
v0.22.0
c346f5e

Choose a tag to compare

The rustio-admin-cli crate now produces a binary named rustio-admin instead of rustio. crates.io package names are unchanged; only the emitted executable changes.

Why

The bare rustio name collided at the shell level with an earlier unrelated upstream RustIO project that also publishes a rustio binary. Back-to-back cargo install runs on the same machine silently overwrote each other with no diagnostic. Renaming the bin to match the crate (rustio-admin-clirustio-admin) clears the ambiguity.

What changed

  • [[bin]] name in crates/rustio-admin-cli/Cargo.toml, the clap name, the WELCOME_HELP banner shown by --help.
  • Every user-facing rustio <verb> example across README, ROADMAP, CLAUDE.md, active design docs, the bundled scaffold templates (newly-scaffolded projects' READMEs and main.rs comments reference rustio-admin), library doc comments, admin-template empty-state CTAs (/admin, /admin/health, /admin/db-browser), examples/.env, the CI scaffold-pin-guard comment, and CLI error / hint strings.

What is deliberately NOT renamed

These are on-disk / runtime contracts with already-deployed projects. Renaming them would silently break running deployments or diverge newly-generated files from previously-generated ones for any project that scaffolds across the version bump.

  • The @generated by rustio <ver> codegen sentinel in builder/codegen.rs (the SchemaHash header in _generated/ files).
  • The .rustio/ state directory (draft.toml, history.jsonl, builder.lock).
  • The // rustio: insertion markers in scaffolded src/main.rs files.
  • The rustio_admin_actions audit table name.
  • The RUSTIO_TEMPLATE_DIR / RUSTIO_SECRET_KEY environment variables.

Migration

After upgrading, cargo install rustio-admin-cli lands ~/.cargo/bin/rustio-admin. The previous ~/.cargo/bin/rustio from older installs is left as-is — cargo uninstall rustio-admin-cli from an earlier install removes it, or delete it by hand.

Shell scripts, CI steps, Dockerfiles, and project docs that invoke the binary directly need a one-token find-and-replace:

```sh

before

rustio startproject myapp
rustio migrate apply

after

rustio-admin startproject myapp
rustio-admin migrate apply
```

No library API change; the rustio-admin crate is byte-identical except for the version bump.

Full notes: CHANGELOG.md

v0.21.1 — Admin list-page redesign

26 May 14:16

Choose a tag to compare

[0.21.1] — 2026-05-26

Admin list-page redesign. Pure CSS + template + render-context
change; no Rust public-API impact, no schema, no auth or permission
behaviour shift.

Toolbar split

The pre-0.21 "View ▾" overflow dropdown collapsed Sort, Per-page,
CSV export, and CSV import into one mega-menu — operators had to
scan a 17-row list (8 fields × 2 directions + Default + 4 per-page

  • Export + Import) to find any single operation. 0.21.1 splits the
    toolbar into two zones with distinct intent:
  • Row 1 "Find" — search input (flex:1, ≥360px), up to two
    promoted filter chips, a "More filters" overflow for the rest, a
    Reset link that surfaces only when there's state to reset
    (search OR ≥1 active filter).
  • Row 2 "Arrange" — Sort field menu, direction toggle, Rows
    per page, Saved view, then a flex spacer, then Export / Import
    pinned to the trailing edge. Every control carries icon + label.

Find panel surface

.rlp-find sits inside an accent-tinted card (--rio-accent-soft
fill, --rio-accent-border, framework radius). No heading or icon
above the panel — the surface itself is the cue. Arrange stays
transparent so the visual weight stays on Find.

Dark table header

.rio-list-page .rio-table th re-skins to --rio-surface-chrome
(the same slate-900 the sidebar uses). The thead scope locally
redefines --rio-text-strong / --rio-text / --rio-text-muted
/ --rio-text-subtle to slate-50…500 and lifts --rio-accent to
teal-400 — same chrome-cascade trick layout/shell.css already
uses on the sidebar, so hover and active-sort copy stay legible
without per-selector overrides. The header bar reads as one
continuous frame with the sidebar; data rows now contrast hard
against the chrome instead of fading into a neutral.

Sort menu — field-once + direction toggle

SortFieldCtx (one entry per sortable field) replaces the
field×direction menu pattern. Clicking a field row activates
ascending sort; a sibling direction toggle flips to descending and
reads field-type-aware copy:

Field type Asc label Desc label
DateTime oldest first newest first
String / FilePath A → Z Z → A
I32 / I64 lowest first highest first
Bool off → on on → off

Numeric copy (lowest first / highest first) is new in 0.21.1;
0.21.0 fell back to the generic ascending / descending strip.
The unit test was updated to match the new copy.

Empty state

The pre-0.21 <p class="rio-empty">No <model> yet</p> floated as a
single sentence inside a large blank card. 0.21.1 ships a centered
empty-state block: a tinted-disc inbox icon, an h2 title
("No appointments yet"), a 16px body sentence ("Add the first
appointment to get started."), and the primary Add CTA. Copy
substitutes the model's plural / singular display name so the
same block reads correctly for every model with no project-side
override.

Bottom bar

Row count + pagination move out of the toolbar into a footer-style
bar below the table card. Showing N of M <model-plural> plus
pagination nav; hidden in the empty state because zero-of-zero is
noise.

Responsive

.rio-list-page page padding cascades: 32px desktop ≥1280px →
24px tablet 768–1279px → 16px mobile <768px, driven by a
.rio-main:has(> .rio-list-page) selector so non-list pages keep
their existing padding. The toolbar's flex-wrap lets Row 1 and
Row 2 reflow vertically below 768px without code; the table card
remains the only horizontal-scroll surface.

Render-context additions

ListCtx gains:

  • sort_fields: Vec<SortFieldCtx> — one entry per sortable field.
  • current_sort_field_label: String — Sort chip caption.
  • current_sort_dir_label: &'static str — direction toggle text.
  • sort_dir_toggle_link: String — flips the active sort's direction.
  • default_sort_link: String — Sort menu's reset row URL.

The legacy sort_options / current_sort_label fields are kept
for back-compat with project templates that haven't migrated to
the new layout.

Assets

  • New stylesheet assets/static/admin/pages/list.css, scoped
    under .rio-list-page. Wired into both the admin.css @import
    manifest and the ADMIN_CSS concat block in routes.rs;
    tests/cascade_lockstep.rs verifies the two lists stay aligned.
  • New icons: inbox (empty-state disc), rotate-ccw (Reset chip),
    arrow-up-down (direction toggle decoration). All inline lucide
    stroke paths, no external library.

Known issue (carried forward, not introduced by 0.21.1)

A foreign-key filter declared in ModelAdmin::list_filter() is
silently dropped when the RelationRegistry doesn't carry the
relation — infer_filters_with_registry falls through to
FilterKind::NumericExact, then the list handler hits a _ => {}
catch-all with no rendered widget. Pre-existing in 0.21.0; the
new toolbar makes the gap more visible (the "More filters"
dropdown is the natural place to surface secondary filters and
will obviously be empty when only the FK was configured). Fix
requires real widget design for NumericExact / RelationSelect
and belongs in a later phase, not a UI patch release.

Migration

Existing 0.21.0 projects update by bumping
rustio-admin = "0.21.0" to "0.21.1" in their Cargo.toml and
running cargo update -p rustio-admin. No schema migration. No
template override required — the new layout ships as the embedded
default. Projects that override templates/admin/list.html
locally will continue to use their override; remove it to pick up
the new layout.

v0.21.0 — Stage 2 (startapp --field, permission defaults, docs discoverability)

25 May 13:22

Choose a tag to compare

Stage 2 of the FTUX redesign. Four PRs bundle into one release: rustio startapp --field, structural permission defaults, a startapp pluralization + spatial-orientation fix, and rustio docs becoming a useful command.

No API breaks. Existing 0.20.x projects update by bumping rustio-admin = "0.20.0" to "0.21.0" in their Cargo.toml. Schema unchanged.

What ships

rustio startapp <name> --field <name>:<type> (PR 2.1)

Closed 8-token vocabulary — str / text / int / bigint / bool / timestamp / json / fk:<Model>. Generates a real model file with the declared fields, a matching CREATE TABLE migration, and a ModelAdmin impl whose list_display / search_fields defaults are derived from the declaration. Interactive prompt loop at TTY when no flags are passed. The "paste these lines into src/main.rs" handshake from prior releases is preserved — startapp deliberately does not edit your main.rs.

timestamp produces TIMESTAMPTZ NOT NULL (no implicit DEFAULT NOW()). json produces JSONB NOT NULL (no implicit DEFAULT '{}'). Either default would imply created_at / settings semantics that don't fit every use.

Structural permission defaults (PR 2.2)

Three groups seeded on fresh databases:

Group Permission scope Audience
administrator Full system access Owner, operator
editor add / change / view on content models. No delete. No user / group / permission management. Content team
viewer view only Auditors, read-only stakeholders

rustio user create --role accepts two new values: editor and viewer (both map to Role::User internally; authority comes from group membership). Group names lock to --role values via a CI-enforced lockstep test. The seed is guarded — projects with user-defined groups pick up zero changes on upgrade.

New doctrine doc: docs/design/DESIGN_PERMISSIONS.md.

Startapp pluralization + spatial orientation

The naive +s pluralizer that produced classs / categorys / buss was replaced with proper English rules (classes / categories / buses). Applied to both the migration filename and the admin URL.

Three new insertion markers in the scaffolded main.rs:

// rustio: modules
// rustio: imports
// rustio: models

rustio startapp output redesigned to orient the developer spatially against the markers:

MODEL CREATED  Task  (2 fields)
  ✓ src/task.rs
  ✓ migrations/0001_create_tasks.sql

3 edits in src/main.rs
  under  // rustio: modules  add  mod task;
  under  // rustio: imports   add  use task::Task;
  under  // rustio: models    add  .model::<Task>()

  $ rustio migrate apply
  $ cargo run
  admin  http://127.0.0.1:8000/admin/tasks

Operational values (paths, commands, URLs) styled via console::style — paths cyan, commands green, URL cyan-underlined, markers dim. NO_COLOR / non-TTY environments strip ANSI cleanly. Missing-marker warning fires when any of the three is absent (older projects).

rustio docs becomes useful (PR 2.4)

Probes /admin/health with a 500ms timeout. The printed output reflects whether the local docs are actually reachable right now:

RustIO docs are running on this project.

  local   http://127.0.0.1:8000/admin/docs
  online  https://docs.rs/rustio-admin

(pass --open to open the local docs in your browser)

New --open flag launches the local docs in your default browser (open / xdg-open / cmd /c start). Exits 1 if the server is unreachable. Health probe uses raw TcpStream (no HTTP-client dep) and requires the framework's x-correlation-id response header so a foreign HTTP service bound to port 8000 doesn't fool it.

Homepage gains one muted line — sign in required — under the three nav pills to explain why clicking them redirects to login when not signed in.

What was deliberately cut

PR 2.3 (doctor onboarding mode + .rustio/onboarding.json state machine) was cut per the Stage 1 Reality Audit. The audit found that rustio doctor already reads clean, and a state file would introduce hidden framework state to solve a problem nobody has.

Upgrade

# Cargo.toml
[dependencies]
rustio-admin = "0.21.0"
cargo update -p rustio-admin

Optional but recommended: the three new insertion markers (// rustio: modules / imports / models) make rustio startapp output much more useful. Add them to your existing main.rs once and the spatial-orientation output gates against them automatically.


Full per-PR detail in CHANGELOG.md.

v0.20.0 — Stage 1 FTUX + Polish & Trust

25 May 01:11

Choose a tag to compare

Headline release of Stage 1. The first-time-developer experience overhaul, plus the Polish & Trust runtime fixes from the Stage 1 Reality Audit, shipped together so external users see a coherent new experience from cargo install rustio-admin-cli.

No API breaks. Existing 0.19.0 projects update by bumping rustio-admin = "0.19.0" to "0.20.0" in their Cargo.toml. Schema unchanged.

First-time developer experience

  • rustio new <name> — friendly alias for startproject. Identical files, same exit codes. The Builder bootstrap that used to live in this slot moved to rustio builder new.
  • Interactive TTY wizard — calm three-prompt flow: project name → project type → database name. Auto-generates .env with a working local DATABASE_URL. Bypassed under --no-interactive, non-TTY stdin/stdout, or CI=1.
  • Welcoming rustio --help — beginner-surface welcome banner above the full command list; full surface preserved untouched below.
  • Four-part humanised onboarding errorsProblem / Why / Fix / Retry shape with the verbatim sqlx text preserved in an indented Details: block. Covers the five onboarding-critical failures: DATABASE_URL missing, PostgreSQL unreachable, database missing, migration SQL failure, invalid --role.
  • Calm progress spinner — ASCII | / - \ on stderr during long ops (Db::connect, migrate apply, doctor connect). One sober ✓ / ✗ marker on completion. Respects --quiet, --no-progress, CI, NO_COLOR, non-TTY. Feedback, not theatre.
  • First-boot homepage at / — calm 130-line inline-CSS landing page baked into the binary via include_str!. Three CSS custom properties at the top (--brand, --text, --muted) make re-skinning a 3-line edit.
  • Project-type-aware subtitle — wizard's project_type choice (custom / clinic / school / inventory / blog) drives a single {{type_phrase}} line on the homepage.
  • Project name in admin chrome — scaffolded main.rs now calls Admin::new().app_name(...). Login tab title, login h1, and dashboard tab title carry the project name instead of generic "Admin".

Operational trust (Polish & Trust)

  • Postgres NOTICE chatter silenced. Db::connect_with sets client_min_messages = warning on every pooled connection. First-boot log drops from 65 lines to 2. WARNING / ERROR / LOG bands unaffected.
  • Duplicate listening log removed. Server::run no longer emits its own rustio listening on …. Scaffolded projects already log their canonical URL with conflicting paths was an audit finding.
  • Admin empty-state CLI handshake. Dashboard's "No models registered yet" now leads with rustio startapp <name> before the Rust line.
  • Scaffold README restructured into five layered sections (1. First run2. First model3. Admin usage4. Common commands5. Advanced topics) matching the new wizard reality. Drops the cp .env.example .env and cargo install rustio-admin-cli steps the wizard already handles.

Project identity

  • Default scaffold is neutral. src/post.rs and migrations/0001_create_posts.sql moved into the blog preset. A clinic / school / inventory / custom project ships zero domain modelsrustio startapp <name> adds the first when the developer decides what they're actually building.

Terminal compatibility

  • Spinner switched from Braille to ASCII. Braille (U+2800-U+28FF) triggered font fallback in some mixed RTL/LTR locales.
  • Em-dashes in CLI strings reduced to --. Two ASCII hyphens — conventional em-dash substitute. Doc comments and documentation untouched.

Doctrine

  • New: docs/design/DESIGN_ONBOARDING.md — Stage 0 constitution governing the FTUX surface. Same shape as DESIGN_AUDIT.md / DESIGN_SESSIONS.md. PRs against the onboarding stack are reviewed against this doctrine.

Upgrade

# Cargo.toml
[dependencies]
rustio-admin = "0.20.0"
cargo update -p rustio-admin

Recommended (one-line opt-in to project ownership): chain .app_name("Your Project") onto your Admin::new() call.


Full per-PR detail in CHANGELOG.md.

v0.19.0 — visual overhaul (Quiet Expert)

24 May 13:22

Choose a tag to compare

A six-turn redesign of every admin UI surface under the Quiet Expert design language. Calm, dense, professional — Stripe Dashboard / Linear / Vercel discipline applied to every page.

No backend change. Every Rust handler, route, model, SQLx query, and migration is identical to 0.18.x. The diff is CSS / templates / JS / one new icon.

New design primitives

Primitive Role
.rio-section Page-level content rhythm — eyebrow label + counted title + body
.rio-empty-state Icon + headline + lead + CTA — replaces one-paragraph .rio-empty
.rio-confirm (+ --danger / --neutral) Block for every destructive / mutating action — left-edge stripe + icon badge + lead + items list
.rio-env-chip Env / version metadata next to a page title
.rio-page-actions__group Secondary-button cluster next to a primary CTA on the page header
Refined .rio-card Lighter shadow ambient + --quiet / --elevated opt-ins

Unified across every page

  • Page header pattern: breadcrumb · title · primary action · lead — every list / form / detail / settings / admin-tool page now uses one shape.
  • Stat tiles: drop the cycling pastel background fills (festive) for one consistent white surface + 3-px accent rail (semantic). Color is reserved for SEMANTIC meaning now, not per-tile decoration.
  • Empty states: every .rio-empty paragraph upgraded to a proper .rio-empty-state block.
  • Confirmation flow: every delete / bulk-confirm / lock / disable-MFA / password-change success uses the same .rio-confirm block. Cancel button moved to the left of the action row so the destructive primary doesn't sit next to the cursor's natural arrival point.
  • Section wrapping: list pages all use .rio-section with eyebrow + counted title (e.g. "All groups · 3 groups").

Per-page work

Turn Templates
1 — Foundation + Dashboard index.html, cards.css, dashboard.css
2 — List pages list.html, users_list, groups_list, log_entries, notifications
3 — Form + confirm form.html, user_{new,edit,view}, group_{new,edit}, confirm_delete, user_confirm_delete, group_confirm_delete, lock_user, bulk_confirm_{delete,action}, confirm_admin_action
4 — Settings + auth account_sessions, password_change, mfa_{enroll,disable,regenerate,enroll_complete,regenerate_complete}. MFA settings pages migrated from the auth-style .rio-login centered shell to the in-chrome settings pattern — sidebar shows correctly now.
5 — Admin tools docs_index, apis_index, feature_flags, db_browser, object_history, csv_import_result
6 — Polish user_view final empty-state polish, version bump, CHANGELOG

What rolls into this release

Two earlier in-progress passes (v0.18.6 polish + bug-fix bundle) ship together with the visual overhaul as one minor bump:

  • 0.18.6 polish (committed under a875ec4): topbar search trigger goes wide (flex:1), list-toolbar 2-row reflow, per-row kebab dropdown, dashboard greeting trimmed, smooth area-chart sparkline.
  • 0.18.6 bug fixes (committed under 2a43d59 as pre-tested drop-in files): --rio-z-* ladder, kebab JS via <details> + JS upgrade to escape table overflow, shared _row_actions.html partial, focus-visible polish, post-seed demo rows.

Compatibility

  • Library, macros, CLI public surface: unchanged.
  • Projects that override --rio-* tokens in their own stylesheet: no change, overrides still cascade.
  • Templates that depend on the dropped .rio-dashboard-greeting* or .rio-dashboard-section-* selectors need to switch to the unified .rio-page-header / .rio-section. None of the framework's own templates still emit them.
  • .rio-empty is kept in the cascade for back-compat but the framework's own templates all use .rio-empty-state now.
  • MSRV: 1.88 (unchanged).

See CHANGELOG.md for the full per-section record.

v0.18.4 — first publish since v0.13.0

23 May 17:55

Choose a tag to compare

All four workspace crates published to crates.io at 0.18.4. First publish since v0.13.0 — closes the 5-minor gap between the local workspace and the registry.

What was blocking publish

crates/rustio-admin/src/admin/docs.rs was reaching include_str!("../../../../docs/<file>.md") outside the crate root. Worked in-tree but failed cargo publish verification: the published tarball contains only the crate's own files, so the path didn't resolve. The bug was latent since v0.16.0 (introduced by 8817234); never surfaced because no version ≥ 0.14.0 had been published.

The fix

Copied architecture.md, modeladmin.md, and public-api.md into crates/rustio-admin/assets/docs/ and updated the three include_str! paths to ../../assets/docs/<file>.md (now inside the crate root, so they survive the publish tarball).

The workspace docs/ directory remains the canonical source for the human-facing site and IDE access; the in-crate copies are bundled at release time. Future doc edits should update both.

Side fix

A doc passage in architecture.md literally documents the Tier-2 symbol grep pattern — which then matched its own self-described regex when the doc moved inside crates/. The Tier-2 guard now excludes crates/*/assets/** (it scans code, not documentation).

Published crates

Crate crates.io Notes
rustio-admin 0.18.4 17 total versions
rustio-admin-macros 0.18.4 17 total versions
rustio-admin-cli 0.18.4 14 total versions
rio-theme 0.18.4 first release — name claimed

What this unlocks

  • rustio startproject now works against the unmodified crates.io registry — no [patch.crates-io] workaround needed.
  • The full theme engine (rio-theme) is available as a standalone build-time crate for any Rust project, not just rustio-admin consumers.
  • All the work since v0.14.0 — Builder MVP, visual identity overhaul, dark-frame chrome, Operations & i18n surfaces, theme engine — is now accessible via cargo add rustio-admin.

Compatibility

  • No public API change vs 0.18.3.
  • Drop-in upgrade for anyone tracking the workspace; the v0.13.0 → v0.18.4 jump is a five-minor bundle whose per-release detail is in CHANGELOG.md.
  • MSRV: 1.88 (unchanged since v0.14.0).

v0.18.3 — green CI bundle

23 May 16:06

Choose a tag to compare

Patch release on top of v0.18.2.

Why this exists

v0.18.2 was tagged correctly but the tagged tree carried two pre-existing CI blockers that the prior releases never caught (CI had been red on the last five commits for unrelated reasons). Verifying the new template-pin guard fires on the runner surfaced them. v0.18.3 cuts a tag that ships with all 15 CI steps green.

Fixed

  • cargo fmt --check clean on the whole workspace. Pre-existing rustfmt drift in crates/rio-theme/ (introduced with the crate in 0.17.0 and never run through fmt locally) plus the CLI's theme.rs. Mechanical reformat, no behavior change.

  • clippy::uninlined-format-args violation in crates/rio-theme/src/color.rs. CI pins rustc 1.88, whose clippy enforces this as a hard error under -D warnings; newer local toolchains are lenient.

    -format!(\"#{:02x}{:02x}{:02x}\", r, g, b)
    +format!(\"#{r:02x}{g:02x}{b:02x}\")

    Same lint class that bit bcdf9b6 last quarter — flagging for the release checklist.

Verified

  • All 15 CI steps green on run 26337327486 (the v0.18.3 release commit itself): fmt, clippy, build, test, Tier-2 symbol guard, four Builder Doctrine guards, and the new scaffold-template-pin guard.
  • The template-pin guard's FAIL path independently verified on run 26337205216 via throwaway PR #2 (closed without merge): every other step green, only the guard step failed with the expected actionable error message:
    ::error::Workspace version (0.18.2) and scaffold template pin (0.16.0) have drifted.
    Update crates/rustio-admin-cli/templates/project/Cargo.toml.tmpl to read
    'rustio-admin = \"0.18.2\"'. See v0.18.1 release notes for the convention.
    

Compatibility

  • No library API change.
  • No CLI surface change.
  • Drop-in upgrade from 0.18.2.
  • Release checklist note: run cargo +1.88 clippy and cargo fmt --check locally before tagging. CI catches it but earlier feedback is cheaper.

v0.18.2 — CI guard for template-pin drift

23 May 15:47

Choose a tag to compare

Patch release on top of v0.18.1.

What's new

A CI guard that prevents the kind of drift v0.18.1 patched. The scaffold template pin is now structurally locked to the workspace minor — silent stale pins can't ship again.

The guard

New step in .github/workflows/ci.yml:

- name: scaffold template pin tracks workspace minor
  run: |
    set -eu
    workspace=$(awk '
      /^\[workspace\.package\]/ { in_section = 1; next }
      /^\[/                     { in_section = 0 }
      in_section && $1 == "version" { gsub(/"/, "", $3); print $3; exit }
    ' Cargo.toml)
    template=$(grep -E '^rustio-admin\s*=\s*"' \
      crates/rustio-admin-cli/templates/project/Cargo.toml.tmpl \
      | head -1 | cut -d'"' -f2)
    if [ "$workspace" != "$template" ]; then
      echo "::error::Workspace version ($workspace) and scaffold template pin ($template) have drifted..."
      exit 1
    fi
    echo "OK: workspace and scaffold template both pin $workspace"

Why it matters

For three releases (0.17.0, 0.17.1, 0.18.0) the workspace bumped to a new minor while the bundled rustio startproject template kept pinning rustio-admin = "0.16.0" — a version that never existed on crates.io. Every fresh scaffold hit a registry resolve failure. The bug was silent because the template file isn't compiled — it's read at scaffold time, well after CI is done.

This guard catches the drift at the source: any PR that bumps the workspace version without bumping the template pin fails CI immediately.

Verification

Tested locally:

  • In-sync (0.18.2 ↔ 0.18.2): OK: workspace and scaffold template both pin 0.18.2.
  • Drift simulated (template reverted to 0.16.0): ::error::Workspace version (0.18.1) and scaffold template pin (0.16.0) have drifted. Update crates/rustio-admin-cli/templates/project/Cargo.toml.tmpl to read 'rustio-admin = "0.18.1"'. → exit 1.

This release exercises the guard at its own bump — proof the system works end-to-end.

Compatibility

  • No library API change.
  • No CLI surface change.
  • CI workflow only.
  • Drop-in upgrade from 0.18.1.