From d0418f294b382fee126c7e6214b9f06e8f5b5fb6 Mon Sep 17 00:00:00 2001 From: PerchAnton <101743951+PerchAnton@users.noreply.github.com> Date: Mon, 26 Oct 2026 23:36:54 +0200 Subject: [PATCH 1/2] Prepare alpha 4 crate and registry publishing workflow --- .github/workflows/ci.yml | 2 +- .github/workflows/publish.yml | 87 +++++++++++++++++++++++++++++++++++ CHANGELOG.md | 8 ++++ Cargo.lock | 2 +- Cargo.toml | 8 ++-- PACKAGE.md | 53 +++++++++++++++++++++ README.md | 5 ++ docs/RELEASING.md | 87 ++++++++++++++++++++++++++++++++--- 8 files changed, 239 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/publish.yml create mode 100644 PACKAGE.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e51fca9..22a51dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,4 +15,4 @@ jobs: - run: cargo +${{ matrix.rust }} run --locked --example retry_command - run: cargo +${{ matrix.rust }} fmt --check - run: cargo +${{ matrix.rust }} clippy --locked --all-targets -- -D warnings - - run: cargo +${{ matrix.rust }} package --locked + - run: cargo +${{ matrix.rust }} publish --dry-run --locked --registry crates-io diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..1fdfaba --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,87 @@ +name: Prepare or publish to crates.io +on: + workflow_dispatch: + inputs: + publish: + description: Upload with Trusted Publishing (only after the first manual upload) + type: boolean + default: false + +permissions: + contents: read +concurrency: + group: crates-io-publication + cancel-in-progress: false + +jobs: + verify: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + persist-credentials: false + - name: Require a matching release tag on main for an upload + if: inputs.publish + env: + RELEASE_REF: ${{ github.ref }} + run: | + python3 - <<'PY' + import os, tomllib + from pathlib import Path + version = tomllib.loads(Path('Cargo.toml').read_text())['package']['version'] + if os.environ['RELEASE_REF'] != 'refs/tags/v' + version: + raise SystemExit('Upload requires a tag matching the crate version') + PY + git merge-base --is-ancestor HEAD origin/main + - run: rustup toolchain install 1.88.0 --profile minimal --component rustfmt,clippy + - run: cargo +1.88.0 test --locked + - run: cargo +1.88.0 run --locked --example retry_command + - run: cargo +1.88.0 fmt --check + - run: cargo +1.88.0 clippy --locked --all-targets -- -D warnings + - run: cargo +1.88.0 publish --dry-run --locked --registry crates-io + - name: Check the packaged tests and record the archive + run: | + mkdir packaged + tar -xzf target/package/edit-session-*.crate -C packaged + cd packaged/edit-session-* + cargo +1.88.0 test --locked + cargo +1.88.0 run --locked --example retry_command + cd ../.. + sha256sum target/package/*.crate > SHA256SUMS + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: crates-io-candidate + path: | + target/package/*.crate + SHA256SUMS + if-no-files-found: error + + publish: + if: inputs.publish && startsWith(github.ref, 'refs/tags/v') && github.repository == 'PerchAnton/edit-session' + needs: verify + runs-on: ubuntu-24.04 + environment: + name: crates-io + url: https://crates.io/crates/edit-session + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - run: rustup toolchain install 1.88.0 --profile minimal + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: crates-io-candidate + path: verified + - name: Recheck the archive before requesting a publish token + run: | + cargo +1.88.0 publish --dry-run --locked --registry crates-io + sha256sum --check verified/SHA256SUMS + - uses: rust-lang/crates-io-auth-action@3268eb413133e2960fa4ae0e963ca76380c54cd9 # v1.0.6 + id: auth + - run: cargo +1.88.0 publish --locked --registry crates-io + env: + CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8654242..5f79e74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.1.0-alpha.4 — unpublished candidate + +- Prepare crates.io publication with an explicit registry allowlist, a package + landing page, dry-run CI and a manual workflow for later Trusted Publishing. +- Document the one-time token-based first upload required by crates.io. +- Public API, behavior, Rust 1.88 minimum and zero runtime dependencies are unchanged. + Existing GitHub archives and tags remain unchanged. + ## 0.1.0-alpha.3 - Add a runnable host command recovery example and eight native Rust tests covering diff --git a/Cargo.lock b/Cargo.lock index 6c04e50..b84cef9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,4 +4,4 @@ version = 4 [[package]] name = "edit-session" -version = "0.1.0-alpha.3" +version = "0.1.0-alpha.4" diff --git a/Cargo.toml b/Cargo.toml index d416c5a..1af6e77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,16 +1,16 @@ [package] name = "edit-session" -version = "0.1.0-alpha.3" +version = "0.1.0-alpha.4" edition = "2024" rust-version = "1.88" description = "Toolkit-independent preview, validation and commit lifecycle" license = "MIT OR Apache-2.0" repository = "https://github.com/PerchAnton/edit-session" -readme = "README.md" -publish = false +readme = "PACKAGE.md" +publish = ["crates-io"] keywords = ["editing", "draft", "validation", "undo", "no-std"] categories = ["no-std", "gui"] -include = ["src/**", "tests/**", "examples/**", "docs/**", "README.md", "CHANGELOG.md", "LICENSE-*", "Cargo.toml", "Cargo.lock"] +include = ["src/**", "tests/**", "examples/**", "docs/**", "README.md", "PACKAGE.md", "CHANGELOG.md", "LICENSE-*", "Cargo.toml", "Cargo.lock"] [[example]] name = "retry_command" diff --git a/PACKAGE.md b/PACKAGE.md new file mode 100644 index 0000000..39f85ca --- /dev/null +++ b/PACKAGE.md @@ -0,0 +1,53 @@ +# edit-session + +A small, toolkit-independent Rust library for preview, validation and commit +lifecycles. **`no_std`, zero runtime dependencies, Rust 1.88+.** MIT OR Apache-2.0. + +Use it when several controls edit one draft and the host should commit one final +change. The host owns validation, preview rendering, commands, undo and document +identity. This crate does not provide widgets or an undo stack. + +## Installation + +Add a published copy of this prerelease to your dependencies: + +```toml +[dependencies] +edit-session = "=0.1.0-alpha.4" +``` + +This is an experimental alpha. Pin an exact version and keep `Cargo.lock` for +applications. Read the +[compatibility policy](https://github.com/PerchAnton/edit-session/blob/main/docs/RELEASING.md#alpha-compatibility) +before upgrading. For other distribution options and current publication status, +see the [project README](https://github.com/PerchAnton/edit-session#use-from-another-project). + +## Example + +```rust +use edit_session::EditSession; + +let context = ("document-7", "layer-2", 42_u64); +let live_opacity = 100_u8; +let mut draft = EditSession::new(live_opacity, context); +draft.propose::<&str>(Ok(75)).unwrap(); +draft.propose::<&str>(Ok(50)).unwrap(); + +if let Some(change) = draft.finish(&live_opacity, &context).unwrap() { + assert_eq!(change.after, 50); + // Send change.after to the host's validated command once. +} +``` + +`finish` consumes the session. If the host command can reject a change and the UI +must retain the draft for retry, use the borrowed-preview/check pattern in the +[tested recovery example](https://github.com/PerchAnton/edit-session/blob/main/examples/retry_command.rs). +Check the live value and context again on every attempt. + +- [API source and contracts](https://github.com/PerchAnton/edit-session/blob/main/src/lib.rs) +- [Changelog](https://github.com/PerchAnton/edit-session/blob/main/CHANGELOG.md) +- [Integration evidence and limits](https://github.com/PerchAnton/edit-session/blob/main/docs/ADOPTION.md) +- [Report a bug](https://github.com/PerchAnton/edit-session/issues/new?template=bug_report.yml) + +The separate [interaction-check](https://github.com/PerchAnton/interaction-check) +runner is optional and is not a dependency of this crate. diff --git a/README.md b/README.md index ffbde3c..bdc84ac 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,11 @@ sequence and shared report help your consumer. The [API contracts](src/lib.rs) a ## Use from another project +**Crates.io candidate: `0.1.0-alpha.4` (not published yet).** After publication, +use `edit-session = "=0.1.0-alpha.4"` in `[dependencies]` and commit `Cargo.lock`. +The [publishing guide](docs/RELEASING.md#registry-publication) covers the first upload +and later Trusted Publishing. Until then, use the existing Git release below. + Add this entry to your crate's `[dependencies]` to use the published alpha 3 at its fixed release commit: ```toml diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 3005ddc..a4bc878 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -6,14 +6,15 @@ was published on **26 October 2026**, with a source `.crate` archive and SHA-256 checksums. Its public library API and behavior are unchanged from alpha.2; it adds the tested recovery example, documentation and package verification. The crate is -not published on crates.io; `publish = false` remains explicit. +not published on crates.io. The separate alpha.4 candidate enables the `crates-io` +registry in its manifest; this does not publish anything. ## Alpha compatibility - Alpha releases are experimental. Public types, methods, trait bounds and behavior may change between releases, even within `0.1.0`. Alpha.3 matching alpha.2 does not promise compatibility with every future alpha. -- Pin a full Git revision and keep the application's lockfile. Before upgrading, +- Pin a full Git revision (or an exact crate version once published) and keep the application's lockfile. Before upgrading, read the [changelog](../CHANGELOG.md) and run the host's draft, stale-context, no-op and command-retry tests. Library tests do not replace those integration tests. - Breaking changes, including a raised minimum Rust version, must be called out @@ -34,7 +35,7 @@ cargo run --locked --example retry_command cargo fmt --check cargo clippy --locked --all-targets -- -D warnings cargo package --locked --list -cargo package --locked +cargo publish --dry-run --locked --registry crates-io ``` Run these from a clean checkout. `cargo package` verifies the extracted crate builds. @@ -50,9 +51,81 @@ Do not present an alpha release as the latest stable release. ## Registry publication -Crates.io publication is a separate decision: confirm name/account ownership, approve -the registry target, change `publish = false` to the intended registry, then run -`cargo publish --dry-run` before an authenticated upload. No registry upload or publish -credentials are configured. +### Prepared candidate + +`0.1.0-alpha.4` is prepared, **not published**. The API, behavior, Rust 1.88 minimum +and runtime dependencies are unchanged. Package metadata/docs change, so the candidate +uses a new version; alpha.3 tags and archives stay untouched. `publish = ["crates-io"]` +limits the registry target. `PACKAGE.md` is the registry landing page and uses absolute +links so it works outside GitHub. + +The public crates.io API returned HTTP 404 for `edit-session` on 26 October 2026. +This does not reserve the name or guarantee acceptance; check it again before upload. + +### First upload: owner action + +Crates.io currently requires an API token for a crate's **first** publication. Trusted +Publishing can only be configured after the crate exists. There is no token in this +repository and the OIDC workflow cannot bootstrap a new crate. + +1. Sign in to [crates.io](https://crates.io/) with the intended GitHub owner account + and verify the email in Account Settings. +2. Once publication is approved, create a short-lived API token restricted to + publishing the new `edit-session` crate. Enter it through `cargo login --registry + crates-io` at its private prompt; do not paste it into a chat, command argument or log. +3. Require green CI on the exact release commit and tag it `v0.1.0-alpha.4`. From a + clean checkout of that tag, inspect the manifest/version, then run: + + ```sh + cargo publish --dry-run --locked --registry crates-io + cargo publish --locked --registry crates-io + ``` + +4. Verify the registry version, owner, license, Rust minimum and README. Compare its + downloaded `.crate` SHA-256 with the local archive from the actual upload. Revoke + the bootstrap token in crates.io and run `cargo logout --registry crates-io`. + +The second command uploads permanently; it is deliberately outside the default +rehearsal. Do not run it merely to test credentials or reserve a name. + +### Subsequent releases: Trusted Publishing + +In the published crate's **Settings → Trusted Publishing**, add: + +| Field | Value | +| --- | --- | +| Repository owner | `PerchAnton` | +| Repository name | `edit-session` | +| Workflow filename | `publish.yml` | +| Environment | `crates-io` | + +Create the `crates-io` GitHub environment, require owner approval and allow release +tags (`v*`). These repository files do not configure the account or environment. +The workflow uses the Rust project's OIDC action; no permanent CI token is needed. + +Run **Prepare or publish to crates.io** from `main` with `publish=false` (default) +to rehearse: Rust 1.88 tests/Clippy, `cargo publish --dry-run`, packaged tests and the +retry example, plus a saved `.crate` and SHA-256 checksum. Pushes and PRs never upload. +Ordinary CI also checks stable Rust and performs a registry dry-run. + +For a later approved version, require green CI and a matching version tag whose +commit is contained in `main`. Run the workflow from that tag with `publish=true`. +It rechecks the package before requesting the short-lived publish token. Do not use +the workflow to re-upload alpha.4 after its manual first publication. + +### Verify installation after publication + +Use a fresh consumer project and the exact prerelease dependency: + +```toml +[dependencies] +edit-session = "=0.1.0-alpha.4" +``` + +Run `cargo check`, confirm `Cargo.lock` names the crates.io source (not a path/Git +override), and check the [API documentation](https://docs.rs/edit-session/0.1.0-alpha.4/). +Only then mark the README/changelog as published and add registry badges. Never +overwrite a published version; fixes require a new version. Reference: [Cargo's publishing guide](https://doc.rust-lang.org/cargo/reference/publishing.html). +See also [crates.io Trusted Publishing](https://crates.io/docs/trusted-publishing). From 16d523d1e159d95fbf336e9a4fc1236095ec5ee9 Mon Sep 17 00:00:00 2001 From: PerchAnton <101743951+PerchAnton@users.noreply.github.com> Date: Mon, 26 Oct 2026 23:38:53 +0200 Subject: [PATCH 2/2] Save the crate explicitly after the registry dry run --- .github/workflows/publish.yml | 2 ++ docs/RELEASING.md | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1fdfaba..ae77272 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,6 +40,7 @@ jobs: - run: cargo +1.88.0 fmt --check - run: cargo +1.88.0 clippy --locked --all-targets -- -D warnings - run: cargo +1.88.0 publish --dry-run --locked --registry crates-io + - run: cargo +1.88.0 package --locked --registry crates-io - name: Check the packaged tests and record the archive run: | mkdir packaged @@ -79,6 +80,7 @@ jobs: - name: Recheck the archive before requesting a publish token run: | cargo +1.88.0 publish --dry-run --locked --registry crates-io + cargo +1.88.0 package --locked --registry crates-io sha256sum --check verified/SHA256SUMS - uses: rust-lang/crates-io-auth-action@3268eb413133e2960fa4ae0e963ca76380c54cd9 # v1.0.6 id: auth diff --git a/docs/RELEASING.md b/docs/RELEASING.md index a4bc878..0cd42a3 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -14,7 +14,8 @@ registry in its manifest; this does not publish anything. - Alpha releases are experimental. Public types, methods, trait bounds and behavior may change between releases, even within `0.1.0`. Alpha.3 matching alpha.2 does not promise compatibility with every future alpha. -- Pin a full Git revision (or an exact crate version once published) and keep the application's lockfile. Before upgrading, +- Pin a full Git revision (or an exact crate version once published) and keep the + application's lockfile. Before upgrading, read the [changelog](../CHANGELOG.md) and run the host's draft, stale-context, no-op and command-retry tests. Library tests do not replace those integration tests. - Breaking changes, including a raised minimum Rust version, must be called out @@ -36,9 +37,12 @@ cargo fmt --check cargo clippy --locked --all-targets -- -D warnings cargo package --locked --list cargo publish --dry-run --locked --registry crates-io +cargo package --locked --registry crates-io ``` Run these from a clean checkout. `cargo package` verifies the extracted crate builds. +It also leaves an archive at the documented path; `cargo publish --dry-run` may keep +its intermediate archive elsewhere, depending on the Cargo version. The archive includes sources, licenses, tests, examples and their documentation. CI checks the source and example on Rust 1.88 and stable. To validate packaged tests too, unpack the new `target/package/edit-session-.crate` into a temporary directory