Skip to content

build(release): add publish metadata + cargo-release tooling - #2

Closed
JustinKovacich wants to merge 6 commits into
mainfrom
chore/cargo-release
Closed

JustinKovacich wants to merge 6 commits into
mainfrom
chore/cargo-release

Conversation

@JustinKovacich

Copy link
Copy Markdown
Contributor

Phase A of DFT→Kellnr: give simple_doip a publishable manifest (license/description/repository/keywords) and standard cargo-release + gated publish workflow (tag v{version}, crates.io, publish=false).

Live publish is gated behind vars.SIMPLE_DOIP_PUBLISH_ENABLED until the Kellnr crates.io proxy (#925 in dft) is live and a crates.io token is provisioned. No publish happens on merge.

Part of the DFT→Kellnr Phase A program (per-repo release model).

@JustinKovacich JustinKovacich self-assigned this Jun 29, 2026
@JustinKovacich
JustinKovacich marked this pull request as ready for review July 10, 2026 15:04
JustinKovacich and others added 3 commits July 10, 2026 11:09
…ckticks)

Newer clippy (1.96) flags two pedantic lints on existing code that the
robust-CI job now enforces with -Dclippy::pedantic:

- duration_suboptimal_units: use from_secs/from_mins over smaller units
  (from_millis(5000)->from_secs(5), from_secs(120)->from_mins(2),
  from_secs(300)->from_mins(5)) - all values unchanged.
- doc_markdown: backtick DoIP, DoIPInt, and SendDiagnosticMessage in docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cargo-semver-checks needs a published baseline on the registry to diff
against; simple_doip has never been published, so the check errors with
"not found in registry (crates.io)". Gate it behind the same variable
that already gates publish - there is no baseline to check until the
first publish happens, once #925's Kellnr proxy is live.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the stale "once #925's proxy is live" precondition from the semver-checks
and publish gate comments. Publishing to crates.io needs only
CARGO_REGISTRY_TOKEN + crates.io reachability; the Kellnr crates.io proxy fronts
crates.io for dft-side consumption of the published crate, a separate concern.
The real gate is the token + the decision to cut a first version (semver-checks
also needs a published baseline to exist first).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@JustinKovacich
JustinKovacich marked this pull request as draft July 13, 2026 17:19
@JustinKovacich

Copy link
Copy Markdown
Contributor Author

Holding — as part of the protocol-stack reframe, this crate is slated to move to a dedicated public repo under a new MicroVision public org (built on the Automotive Wire Codec, consumed internally via the Kellnr proxy). Standing up publish tooling in its current home is therefore on hold pending the org/hosting decision (to be finalized with Zach).

Converting to draft rather than closing so the work is easy to resume once the target repo/org is settled.

@JustinKovacich

Copy link
Copy Markdown
Contributor Author

Superseded by #11 — closing.

main moved under this branch: it now carries the full publish metadata this PR was adding (description, license, repository, readme, keywords, categories, exclude), which is why the diff went CONFLICTING. #11 rewrites the remaining half — release.toml plus a tag-gated release.yml — against current main, and keeps this PR's design: tag-driven publish, gated behind SIMPLE_DOIP_PUBLISH_ENABLED so merging publishes nothing.

Two additions there: a repository guard so a fork pushing a v* tag can't publish under this crate's name, and a tag-vs-manifest version check before the publish runs.

Also worth recording for whoever picks this up — the July hold reason is gone. The Kellnr crates.io proxy this cited as a blocker is verified working and is consumption-side only, irrelevant to publishing. And the org question has effectively been answered in practice: automotive-wire-codec 0.3.0 is on crates.io, published from a luminartech repo, and this crate depends on it.

The semver-checks job from this branch was intentionally dropped rather than carried over — cargo-semver-checks needs a published baseline to diff against, and luminartech/rust_workflow already provides that job for callers, so it belongs with the CI migration rather than the first publish.

JustinKovacich added a commit that referenced this pull request Sep 10, 2026
…mation (#11)

## What

The two things standing between `simple_doip` and a first crates.io
release:
the license texts, and a way to cut a release.

## Why

The crate turned out to be much closer to publishable than the Phase A
notes
suggested. Checked against the live repo:

- `Cargo.toml` on `main` already carries the **full publish metadata** —
`description`, `license`, `repository`, `readme`, `keywords`,
`categories`,
  `exclude`. No `publish = false`.
- CI already runs **`cargo publish --dry-run`** in the `package` job, so
  publishability is verified on every run.
- The only first-party dependency, **`automotive-wire-codec 0.3.0`, is
already
on crates.io** (published 2026-07-17). That was the hard prerequisite —
`cargo publish` refuses a crate whose dependencies aren't on a registry.
- The name **`simple_doip` is unclaimed** on crates.io (both spellings
404).
- DFT's submodule pointer is **identical** to `main` (0 ahead / 0
behind, both
  at 0.5.2), so there's no fork to reconcile first.

What was actually missing was the license files and the release
plumbing.

## Commits

1. **`docs(license)`** — adds `LICENSE-MIT` + `LICENSE-APACHE`, copied
verbatim
from `uds_protocol` so the protocol libraries carry identical wording.
The
manifest has declared `MIT OR Apache-2.0` for a while with no text in
the
repo; GitHub's API reported `license: null` for exactly that reason.
Both
   files land inside the published `.crate`.
2. **`build(release)`** — originally cargo-release plus a hand-rolled
tag-driven `release.yml`. **Superseded:** see "Release tooling" below.
   Both files are deleted; `release-plz.toml` replaces them.

## Release tooling: release-plz, matching the sibling repos

`uds_protocol` and `automotive_wire_codec` both release with
release-plz, off
a `release-plz.toml` that is **byte-identical between them**, and
neither has
a release workflow of its own — the jobs live in
`luminartech/rust_workflow`.
This repo was the odd one out. It now carries the same config verbatim,
and
`release.toml` + `.github/workflows/release.yml` are gone.

The switch itself (`use-release-plz: true`, permissions, secrets) lands
one
layer up in **#13**, which owns `main.yml`.

What this changes in practice: **no version is bumped by hand and no tag
is
pushed by hand.** A push to `main` maintains an open release PR; merging
that
PR publishes, tags, and cuts the GitHub release.

### The one real regression

The deleted `release.yml` published through **crates.io trusted
publishing** —
OIDC, no stored registry credential anywhere. The reusable workflow's
release-plz job takes a `CARGO_REGISTRY_TOKEN` secret instead. Matching
the
org is the point of this change, so that's the trade accepted here, but
it is
a step backwards on that one axis and the right place to fix it is
`rust_workflow`, not this repo: one `id-token: write` plus a
`crates-io-auth-action` step would give trusted publishing to every repo
on
the shared workflow at once.

**Merging this still publishes nothing** — the release-plz jobs need
secrets
and a `crates-io` environment this repo does not have yet (listed in
#13).

## `CONTRIBUTING.md` gains a Releases section

Because the repo squash-merges with `squash_merge_commit_title:
PR_TITLE`, the
**PR title** is the commit subject on `main` — so PR titles, not branch
commits, are what release-plz computes the version from. The new section
spells that out with the type-to-bump table, and calls out the trap that
bit
this stack: pre-1.0 a breaking change is a *minor* bump, `!` is the only
thing
that produces one from a `fix:`, and `cargo-semver-checks` reads the API
surface so it will not catch a behavioral break for you.

## How it was tested

- `cargo publish --dry-run` — packages 77 files / 106.6 KiB compressed,
verifies the packaged crate, resolves `automotive-wire-codec 0.3.0` from
  crates.io. **This is the proof that 0.5.2 is publishable as-is.**
- `cargo package --list` — confirms `LICENSE-APACHE` and `LICENSE-MIT`
are
  in the `.crate`.
- `cargo fmt -- --check` and `cargo clippy --all-features -- -D warnings
  -Dclippy::pedantic` — both clean.
- `release-plz.toml` parses, and its values `diff` clean against
  `uds_protocol`'s and `automotive_wire_codec`'s copies.
- `cargo package --list` confirms `release-plz.toml` and
`rust-toolchain.toml`
stay out of the packaged crate (the `exclude` entry was updated with the
  rename).
- The three cargo-release 0.25 behaviors this depends on were verified
  empirically during Phase A: the `publish` subcommand overrides
  `publish = false`; `--allow-branch '*'` is required on a tag-push
(detached-HEAD) run; and `--version '^0.25'` is needed because cargo
rejects
  a bare `--version 0.25`.

## Still needs a decision (not in this PR)

1. **crates.io owner + token.** `simple_doip` has no repo secrets at
all.
The precedent next door is a personal account — both `uds_protocol` and
`automotive-wire-codec` are owned on crates.io by `zheylmun`. A
crates.io
**team owner** (`github:luminartech:<team>`) would be the durable
answer.
   `CARGO_REGISTRY_TOKEN` then goes in this repo's secrets.
(Worth noting: `uds_protocol` is at 0.1.0 on `main` but still 0.0.2 on
crates.io, and has no `CARGO_REGISTRY_TOKEN` in its secrets — its merged
   release tooling has never actually published either.)
2. **First-publish version.** 0.5.2 as-is works. Worth being deliberate,
   because the version number is spent permanently once published.
3. **`luminartech/rust_workflow`.** The org-wide reusable workflow
(`rust-ci.yml@v1`) already does tag-gated publish, a
`publish-repository`
   fork guard, a `publish-environment` approval gate and `cargo
semver-checks` — `uds_protocol` and `automotive_wire_codec` are both
thin
   callers of it. Adopting it here would replace this repo's hand-rolled
   `ci.yml` *and* this `release.yml`, and it needs scaffolding this repo
   doesn't have yet (pre-commit config, `deny.toml`, `.typos.toml`,
`.config/nextest.toml`, fuzz targets) — much of which is what #1 adds.
That migration is worth doing, but it's a bigger change than unblocking
a
   first publish, so this PR deliberately doesn't touch `ci.yml`.
4. **#1 and #2.** #2 (mine) is superseded by this PR — `main` grew the
publish
metadata it was adding. #1 (@gavin-dunlap-luminar) is a different
question:
its hand-rolled 297-line `main.yml` is superseded by `rust_workflow`,
but
   its scaffolding is a prerequisite for adopting it. Both are currently
   `CONFLICTING` against `main`.

## Pre-publication audit (commits 3-10)

A pass over the whole repo for things that would ship visibly wrong.
Commits
3-5 needed no decisions:

3. **`build(cargo)`** — **docs.rs would have published a nearly empty
API
reference.** `default = []`, and docs.rs builds default features only,
so
`client`, `server`, `codec`, `alloc` and `std` — most of what the README
points a reader at — would have been absent from the docs page. Fixed
with
   `[package.metadata.docs.rs] all-features = true`; verified that the
`client`, `server` and `message_codec` modules now render. The same
commit
stops shipping `release.toml` and `rust-toolchain.toml` inside the
`.crate`
   (77 files → 75).
4. **`chore(vscode)`** — all six debug configurations passed
`--package=doip`,
   the crate's pre-rename name, so every one of them failed.
5. **`chore(deps)`** — `futures-util 0.3.28` is yanked on crates.io, so
every
   `cargo publish` run warned about it; moved to 0.3.34. Lockfile only.

Commits 6-8 then closed the documentation gaps the audit turned up, and
9-10
settled how the crate actually gets published:

6. **`docs`** — adds `CHANGELOG.md` (110 lines), reconstructed from the
release
history, so the crate does not arrive on crates.io with the 0.2.0
zero-copy
core, the 0.4.0 server API break and the 0.5.x client fixes behind it
and no
   record of any of them.
7. **`docs`** — adds `SECURITY.md` (a stated way to report a
vulnerability in
an automotive diagnostics library) and `CONTRIBUTING.md` (a stated
position
   on outside contributions, plus the Releases section described above).
8. **`docs(readme)`** — replaces the 45-line "Status" known-gaps
inventory with
a "Scope and limitations" section. The README is the crate's front page
on
   crates.io; it is now 144 lines.
9. **`ci(release)`** — moved the hand-rolled `release.yml` onto
crates.io
trusted publishing. **Superseded** by commit 10, which deletes that
file.
10. **`build(release)`** — hands versioning and publishing to
release-plz. See
"Release tooling" above, including the trusted-publishing regression
this
    trade accepts.

Also updated the repo's GitHub **description** (was "Crate for Rust
DoIP") to
match the manifest, and added **topics** (`doip`, `iso13400`,
`automotive`,
`diagnostics`, `no-std`, `rust`).

### Clean

Worth recording, since the audit went looking: no Luminar branding
anywhere
except the org name in the repository URL; no internal hostnames, IP
addresses,
ticket numbers or names in any file; no
`dbg!`/`println!`/`#[allow(...)]` in
`src/`; `#![warn(missing_docs, missing_debug_implementations)]` is on;
all 16
symbols the README names exist; examples are clean.

### Still open, needs a decision

Four bullets that stood here are now closed: `CHANGELOG.md`,
`SECURITY.md` and
`CONTRIBUTING.md` are added by commits 6-7, the README's known-gaps
inventory is
replaced by commit 8, and **`v0.5.2` is now tagged and pushed at
`304d014`**, so
the tag history no longer has a hole in front of a first publish. What
is left:

- **Six naked TODOs in `src/`** (`connection.rs`,
`routing_activation_request.rs`,
  and four in `server.rs`), notably `server.rs:631`
(`LogicalAddress(0x0000), // TODO fix this constant`) — the same defect
the
README documents as `ClientConnectionInfo::logical_address` always being
  `0x0000`. Fixed one layer up in #12; the rest are fix-or-drop.
- **`strum` is a major behind** (0.27 vs 0.28.0); bumping likely forces
a
  matching bump in dft's workspace.
- **CI has no cargo-audit, cargo-deny, cargo-semver-checks or typos
check.**
semver-checks is the one that matters once published — it's what stops
an
accidental breaking release. All four come free with `rust_workflow`,
which
  #13 adopts.

One audit finding was **withdrawn**: `ARCHITECTURE.md` §7.1 is marked
"RESOLVED
in 0.4.0" while sitting under "Known issues and deferred work", which
looked
stale — but §7's own preamble states the policy deliberately ("Resolved
entries
are kept because the analysis that led to the fix is still the fastest
way to
understand the shape the API ended up with"). Left alone. Renumbering
would
also have broken the `§7.2` references in `src/client_inner.rs` and
`tests/integration_test.rs`.

## Review status

Marked ready for review; not reviewed by anyone yet. CI is green — 7
pass.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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