Skip to content

chore: release v0.28.5 - #152

Merged
fxrdhan merged 12 commits into
devfrom
release-v0.28.5
Oct 4, 2026
Merged

fxrdhan merged 12 commits into
devfrom
release-v0.28.5

Conversation

@fxrdhan

@fxrdhan fxrdhan commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Summary

Prepares v0.28.5 from dev at a975736 (#136 through #151). It does three things before the version bump: automates the rest of the release, brings the docs in line with the binary, and bumps the version. The twelve commits are meant to land as they are, so please use Rebase and merge rather than squash.

Release automation

  1. ci(release): take the release notes from CHANGELOG.md
    • The GitHub release notes came from git-cliff over commit titles. Once a pull request is squashed, that leaves one line per PR, so the 45 fixes in test: audit the suite against independent oracles, and fix what it turned up #149 would have shown up as one.
    • The notes are now the version's section of CHANGELOG.md.
    • A Release notes job fails when that section is missing, and, on a tag, when the tag is not the version in Cargo.toml. It runs in the dry run too.
  2. ci(release): bump the Homebrew formula in a job of its own
    • A tap token that cannot write, as on v0.28.4, now fails that job alone, instead of the job that creates the release.
  3. ci(release): publish the crate to crates.io
    • Every release so far reached crates.io through a cargo publish run by hand. The workflow now publishes once the GitHub release is out, so cargo binstall never sees a version without binaries.
    • It authenticates by Trusted Publishing (OIDC), so no registry token is stored.
    • A dry run runs cargo publish --dry-run. For a version that is already published, that only warns, which I checked against 0.28.4.
  4. ci(release): drop a stale note on --no-default-features builds
    • The header said that build does not work. It does, and CI checks it.

Docs checked against the binary

Every flag, environment variable, colour code, config key and theme key in the README, the three man pages, docs/ and the contributor guides was checked against the parser and the built binary.

  • docs(theme)
    • The schema's filekinds.symlink used oneOf. A plain style such as { foreground: Cyan } matches two of its branches, so every theme that styled symlinks failed validation, including the README's own schema example. It is anyOf now, and the schema test pins that.
    • The examples now use is_bold and is_underline, the names the schema and the man pages use.
  • fix(options): -O's help text and the completions said "Mac, BSD, and Windows only". Linux has been supported for a while.
  • docs(readme):
    • --spacing also applies in the long view, and caps at 1000, not 255.
    • There is no recent alias. There is an undocumented relative-recent:DAYS.
    • CLICOLOR, CLICOLOR_FORCE and LEZ_OVERRIDE_AUTO_COLOR are not read at all.
    • The "Syntax highlighting" claim is gone.
    • The duplicate Installation section is merged into one.
  • docs(man) for lez(1):
    • Corrects --spacing, and adds relative-recent and relative-recent:DAYS.
    • --git-repos draws no ~ symbol.
    • Adds --git-ignore to what --no-git overrides. LEZ_OVERRIDE_GIT acts as --no-git in full.
    • An empty NO_COLOR does not turn colours off.
    • Corrects the config precedence: LEZ_CONFIG_FILE replaces discovery, and all four global file names are listed.
    • Adds exit status 2 and LEZ_DEBUG.
    • Moves --stdin and --stdin0 to the meta options.
    • Fixes the auto sentence, which had it backwards ("if run while in a tty").
  • docs(man) for lez_colors(5):
    • Drops ic, which nothing reads.
    • Adds hw and the Finder-tag keys Tn to To.
    • ff covers every platform, and LS_COLORS takes twelve codes, not eleven.
    • Lists every ANSI code the parser accepts, including blink, reverse, backgrounds and 24-bit colour.
  • docs(man) for lez_colors-explanation(5):
    • Adds the theme keys the outline was missing.
    • theme.yaml is read too, music is cyan, and data files get a colour line.
  • docs: Fixes TESTING.md's test path, adds the REUSE command CONTRIBUTING.md promised and the branch to work from, and corrects SECURITY.md's development branch.

The version

Before tagging: one setting on crates.io

On crates.io, open lez → Settings → Trusted Publishing → Add → GitHub and enter:

Field Value
Repository owner fxrdhan
Repository name lez
Workflow filename release.yml
Environment empty

Without this, the crates.io job fails at authentication. The GitHub release and Homebrew are not affected, and cargo publish by hand still works.

After merging

git fetch origin
git push origin origin/dev:main                       # main fast-forwards; it has nothing dev lacks
git tag -a v0.28.5 -m "Release v0.28.5" origin/dev
git push origin v0.28.5                               # starts release.yml: GitHub release, crates.io, Homebrew

After that, update the sha256 in packaging/homebrew/lez.rb, as chore(homebrew) did for v0.28.4.

Found, but not changed here

  • missing_target in theme.yml is ignored, while mi= works. The theme struct has no field for it, so this is code to add, not a typo.
  • --time-style refuses locale and posix-STYLE. TIME_STYLE accepts them, and so does GNU ls --time-style.
  • The powertest snapshots (tests/ptests) are stale. One help snapshot is missing --stdin0, --percent-digits and other flags. The suite does not run in CI, and they are regenerated with just idump, not by hand.
  • --total-size is documented as "unix only", but the code computes it on Windows too. Every test of it is #[cfg(unix)], so that claim is unverified either way.

Type of Change

  • 🐛 Bug fix (non-breaking change fixing an issue)
  • ✨ New feature (non-breaking change adding functionality)
  • ⚡ Performance improvement
  • ♻️ Code refactor / clean-up
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 📝 Documentation / Man pages / Completions
  • 🔧 Build / CI / Dependencies

Related Issues & Upstream References

  • Resolves: none
  • Upstream: none

Feature / Flag Checklist (if adding or modifying CLI flags)

No flags were added. -O's help text changed in src/options/parser.rs and in all five completions, along with their eza copies.

How Has This Been Tested?

  • Testing commands executed, at every commit:
    • cargo fmt --check.
    • cargo clippy --locked --all-targets --features git,inspect-archives -- -D warnings.
    • cargo nextest run --locked --workspace --all-targets --features git,inspect-archives: 1497 passed at each.
  • At HEAD:
    • cargo test --locked --doc.
    • reuse lint and actionlint.
    • cargo publish --dry-run --locked.
    • The README and docs/theme.yml theme examples validated against the schema with jsonschema. A key neither style knows is still rejected.
  • The new notes step, run locally in four cases:
    • A dry run passes.
    • A v0.28.5 tag passes.
    • A v0.28.4 tag fails on the Cargo.toml mismatch.
    • A changelog without the section fails.
  • Every doc correction above was checked against the built binary or the parser that reads the value.
  • Platforms verified: CI on this PR, including the Release dry run (binaries, man pages, notes, and the crates.io package check).

Contributor Checklist

  • Base branch is set to dev (unless this is a release PR targeting main)
  • My commits follow Conventional Commits format
  • Tests covering the changes have been added/updated
  • cargo clippy --all-targets passes with no warnings
  • cargo nextest run (or cargo test) passes
  • cargo fmt --check / nix fmt passes
  • License headers (SPDX / REUSE) are properly preserved/added

🤖 Generated with Claude Code

https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk

claude added 12 commits October 4, 2026 04:20
The notes came from git-cliff over the commit titles since the last tag.
Once a pull request is squashed, that is one line for all of it: the 45
fixes in #149 would have reached the v0.28.5 notes as "Audit the suite
against independent oracles". CHANGELOG.md already holds the section
written for readers, so publish that.

A new job takes the section for the version in Cargo.toml and fails when
there is none, or, on a tag, when the tag is not that version. It runs
in the dry run too, so a missing section or a forgotten bump shows up
before tagging rather than after the binaries are built. The publish job
no longer compiles git-cliff.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
The bump ran as the last step of the job that creates the GitHub
release. When the tap token could not write, as on v0.28.4, that job
went red although the release was out, and anything made to wait on the
release would have been skipped with it. In its own job the failure
stays where it belongs.

The action talks to the GitHub API only, so the job needs no checkout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
Every release so far reached crates.io by a `cargo publish` run by hand
some minutes after the tag, a step nothing in the repository recorded.
Publish it from the release workflow instead, once the GitHub release is
out: `cargo binstall` takes the version from crates.io and the binaries
from that release, so this order never offers a version without them.

It authenticates by Trusted Publishing, which trades the workflow's OIDC
identity for a token that lasts 30 minutes, so no registry token is
stored to leak or expire. The crate's crates.io settings must name this
repository and release.yml as a trusted publisher.

A dry run runs `cargo publish --dry-run`, which packages and builds the
crate. Once a version is out it only warns that the version exists, so
later dry runs stay green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
The README's schema example and docs/theme.yml both failed the schema
they point editors at:

- `filekinds.symlink` took `oneOf` a link style or a plain style, and a
  plain style such as `{ foreground: Cyan }` is both, so every theme
  that styled symlinks was flagged. It is `anyOf` now, which still
  rejects a key neither knows.
- The examples wrote `bold` and `underline`. lez reads those as aliases
  of `is_bold` and `is_underline`, but the schema and the man pages
  name only the `is_` forms, so the examples now use those.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
The help text and the completions read "Mac, BSD, and Windows only",
from before Linux inode flags (`FS_IOC_GETFLAGS`, as `lsattr` shows
them) were supported. The README and lez(1) already say Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
Checked against the binary, the README claimed:

- `--spacing` acts in the grid views and takes 0 to 255. It sets the
  long view's spacing too, where the default is 1, and is capped at
  1000.
- `recent` is an alias of `relative-recent`. lez refuses it; what it
  does take, and nothing documented, is `relative-recent:DAYS`.
- `CLICOLOR` and `CLICOLOR_FORCE` are honoured, and
  `LEZ_OVERRIDE_AUTO_COLOR` exists. lez reads none of them; only
  `NO_COLOR`, and only when it is not empty.
- "Syntax highlighting". lez colours file names by type; it highlights
  no syntax.

It also had two "Installation" sections, the second only a pointer to
INSTALL.md, now a line in the first; and its feature matrix listed
"Custom Column Order (`--blocks`)" as missing although lez has a
`--blocks`, a different one, so the row now names lsd's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
Checked against the binary, lez(1):

- had `--spacing` act in the grid views and take 0 to 255, like the
  README;
- left `relative-recent` out of the time styles, and with it
  `relative-recent:DAYS`, which nothing documented;
- gave `--git-repos` a `~` for an unknown status that is never drawn,
  where a directory outside a repository shows `-`;
- left `--git-ignore` out of what `--no-git` overrides, and described
  `LEZ_OVERRIDE_GIT` as overriding only `--git` and `--git-repos` when
  it acts as `--no-git` in full;
- said `NO_COLOR` turns colours off whatever its value, when an empty
  one does not;
- put `LEZ_CONFIG_FILE` among the global files and listed two of the
  four global names, when the file it names replaces discovery;
- left out exit status 2, for a path that does not exist, and
  `LEZ_DEBUG`;
- listed `--stdin` and `--stdin0` under the long view, which the README
  already moved to the meta options; and
- said `auto` hides indicators and icons "if lez is run while in a
  tty", the opposite of what it does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
Checked against the parser:

- `ic` was documented as the icon's colour, but no code reads it; an
  icon takes its own colour or its name's.
- `hw`, the `--warn-hidden` tally, and `Tn` to `To`, the Finder tag
  colours, are read but were not documented.
- `ff` styles the flags column on every platform `-O` supports, not
  only BSD.
- `LS_COLORS` takes twelve codes, not eleven.
- The list of styles stopped at the foreground colours and `38;5`,
  while blink, reverse, hidden, strikethrough, black, every background
  and 24-bit colours are accepted too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
The list of theme options left out keys the theme file takes and the
schema describes: `filekinds.btrfs_subvol`, `file_type.lossless` and
`file_type.data`, and `symlink_path`, `hidden_warning`, `capability`,
`multi_hardlink`, `tags` and `colourful`.

The page also said the file must be named `theme.yml`, when
`theme.yaml` is read too, and called music "a faint blue" when it is
cyan, and listed no colour for data files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
- TESTING.md named `tests/powertest_config_tests.rs`, which became
  `tests/cli_options/powertest_config.rs` when the suite was split into
  domains.
- CONTRIBUTING.md promised "the following command" for REUSE headers
  and gave none, and never said to branch off `dev`.
- SECURITY.md said lez is developed on `main`, which only receives
  releases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
The header said the `cross` recipe needs a `--no-default-features`
build "which the tree does not currently have". It has one: it builds,
and CI checks it in the Feature Combinations (none) job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1zQZxjBx5aUYbEcuEkXjk
@fxrdhan
fxrdhan merged commit 253deb1 into dev Oct 4, 2026
35 checks passed
@fxrdhan
fxrdhan deleted the release-v0.28.5 branch October 4, 2026 05:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants