Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
89 changes: 89 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
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
- run: cargo +1.88.0 package --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
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
- run: cargo +1.88.0 publish --locked --registry crates-io
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
53 changes: 53 additions & 0 deletions PACKAGE.md
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
91 changes: 84 additions & 7 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
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
Expand All @@ -34,10 +36,13 @@ 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
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-<version>.crate` into a temporary directory
Expand All @@ -50,9 +55,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).