collective

Browse / github.com/storytold/craft-libs / patch

Prepare v0.1.0 with release notes, versioning policy and pinned adoption

Prepare v0.1.0 with release notes, versioning policy and pinned adoption Consumers starting projects need a named dependency baseline they can keep while main evolves. Prepare the coordinated v0.1.0 Git release for craft-atomic, craft-settings, craft-quit, craft-print and craft-ui, with release notes, tag/commit pinning examples, lockfile guidance and an explicit 0.x compatibility policy. Add a workspace release gate on Linux, macOS and Windows (default/all-feature Clippy and tests), a Linux Rust 1.95 library check and UI/settings WASM checks. Windows queue tests are mandatory on the runner. The policy documents platform limits, immutable tags, deliberate upgrades

Status
open
Score
0.00
Adopters
0 other operators
Author
skylartaylor (imported from pull request #41, open)
Base
f03ec27ab2c405969428512178f746183cd55ca0
Size
+252 −2 in 4 files
Review
pending
Shared
2026-10-28
Id
86d05c43a9f6225ee287eee9

How it went

No other operator has reported using it yet.

Diff

raw · .github/workflows/workspace.yml CHANGELOG.md README.md docs/versioning.md

diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.ymlnew file mode 100644--- /dev/null+++ b/.github/workflows/workspace.yml@@ -0,0 +1,75 @@+name: Workspace++on:+  push:+    branches: [main]+    tags: ["v*"]+  pull_request:+  workflow_dispatch:++permissions:+  contents: read++jobs:+  native:+    name: Workspace (${{ matrix.os }})+    timeout-minutes: 30+    strategy:+      fail-fast: false+      matrix:+        os: [ubuntu-latest, windows-latest, macos-latest]+    runs-on: ${{ matrix.os }}+    steps:+      - uses: actions/checkout@v4+      - name: Install software Vulkan renderer+        if: runner.os == 'Linux'+        run: |+          sudo apt-get update+          sudo apt-get install -y mesa-vulkan-drivers libvulkan1+          echo 'WGPU_BACKEND=vulkan' >> "$GITHUB_ENV"+      - uses: dtolnay/rust-toolchain@stable+        with:+          components: rustfmt, clippy+      - uses: Swatinem/rust-cache@v2+        with:+          key: workspace+      - name: Prepare the Windows test driver+        if: runner.os == 'Windows'+        shell: powershell+        run: |+          $ErrorActionPreference = 'Stop'+          Start-Service Spooler+          Add-PrinterDriver -Name 'Generic / Text Only'+      - run: cargo fmt --check+      - run: cargo clippy --workspace --all-targets --locked -- -D warnings+      - run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings+      - run: cargo test --workspace --locked+        env:+          CRAFT_PRINT_REQUIRE_QUEUE: ${{ runner.os == 'Windows' && '1' || '0' }}+      - run: cargo test --workspace --all-features --locked+        env:+          CRAFT_PRINT_REQUIRE_QUEUE: ${{ runner.os == 'Windows' && '1' || '0' }}+  msrv:+    name: Rust 1.95 (Linux libraries)+    runs-on: ubuntu-latest+    timeout-minutes: 15+    steps:+      - uses: actions/checkout@v4+      - uses: dtolnay/rust-toolchain@1.95.0+      - uses: Swatinem/rust-cache@v2+        with:+          key: workspace-msrv+      - run: cargo check --workspace --lib --all-features --locked+  wasm:+    name: UI and settings WASM+    runs-on: ubuntu-latest+    timeout-minutes: 15+    steps:+      - uses: actions/checkout@v4+      - uses: dtolnay/rust-toolchain@stable+        with:+          targets: wasm32-unknown-unknown+      - uses: Swatinem/rust-cache@v2+        with:+          key: workspace-wasm+      - run: cargo check -p craft-ui -p craft-settings --all-features --locked --target wasm32-unknown-unknowndiff --git a/CHANGELOG.md b/CHANGELOG.mdnew file mode 100644--- /dev/null+++ b/CHANGELOG.md@@ -0,0 +1,65 @@+# Changelog++All crates share the workspace version. See [the versioning policy](docs/versioning.md).++## v0.1.0 — 2026-10-12++First coordinated Git release of craft-libs. Applications can pin a named baseline instead of+following development commits. This is an initial 0.x release: compatibility is maintained+within `0.1.x`; changes requiring consumer migration use a new minor version.++### Included crates++- **craft-atomic:** same-directory staged file replacement, exclusive creation, streaming+  writes, transient rename retries and fault-injection support, extracted from PhotoCraft.+- **craft-settings:** app-owned TOML settings with platform/portable paths, atomic saves,+  backups, damaged-file recovery, schema migrations and preservation of unknown fields.+- **craft-quit:** native macOS termination, optional egui close handling and an optional+  application menu. Save decisions and prompts stay with the app.+- **craft-print:** CUPS and native Windows PDF submission, printer discovery, copies, duplex,+  colour and scaling options. Includes bounded PDF sheet handling and the pinned Windows+  completion fix. PDF generation stays with the app.+- **craft-ui:** egui icon buttons, tabs, splits, resize handles, toolbar overflow, transactional+  docking, theme helpers and print-settings controls. Commands, content, localization and+  application state stay with the consumer. Docking serialization is opt-in through `serde`.++### Requirements and adoption++- Rust **1.95+**, edition 2024. Public UI integrations use **egui 0.36**.+- Use `git = "https://github.com/storytold/craft-libs", tag = "v0.1.0"` for each required crate;+  use the same tag everywhere. The [README](README.md#use-a-released-version) has a complete+  manifest example and a commit-pin alternative. Commit application lockfiles.+- No automatic migration from an arbitrary earlier Git revision is implied. Compare the API+  you used with this release and test affected workflows before changing pins.+- For `craft-quit`, run the close hook last in `eframe::App::logic`, after the app's unsaved-work+  decision. Finish asynchronous saves before requesting close; termination does not execute+  code after `run_native`. See the crate's API documentation before adoption.+- This release is distributed through Git only. No crates.io packages are published by it.++### Platform coverage and known limits++The release gate checks the workspace on Linux, macOS and Windows with default and all features,+plus Linux minimum-compiler and UI/settings WASM checks. UI tests include offscreen visual+regressions. Windows print tests exercise a temporary paused spooler queue; those checks do+not establish physical printer fidelity or every application's native GUI behavior.++- `craft-ui` supports native and WASM use. Font coverage, bidirectional text and screen-reader+  behavior still depend on the application and upstream stack; see [#17](https://github.com/storytold/craft-libs/issues/17).+- `craft-settings` persistence is native-only. WASM exposes settings traits, document helpers+  and error types. Concurrent writers are best-effort, last-writer-wins; strict coordination+  needs an application-owned lock.+- `craft-atomic` does not preserve all filesystem metadata during replacement. Directory sync+  is best effort; tests do not prove physical power-loss durability. See its README's contract.+- `craft-quit`'s native behavior is macOS-specific; other platforms keep their normal close+  path. Earlier hardware testing of the close hook is recorded in+  [#3](https://github.com/storytold/craft-libs/issues/3); it does not qualify every consuming app.+- `craft-print` requires CUPS command-line tools on Linux/macOS or the native Windows spooler.+  Browser submission is unsupported. Windows accepts a bounded subset of print-ready PDFs;+  unsupported inputs and driver paper/scaling mismatches return errors. Printing is synchronous,+  so call it from a worker. Physical output needs hardware testing.+- Windows printing retains a pinned Git dependency on the maintained `winprint` fork. Its+  build dependencies require the license/advisory policy exceptions documented in+  [craft-print's README](crates/print/README.md). Registry publication is deferred.++Planned crates and open feature PRs are not part of this release. Existing commit pins remain+valid, and consumers do not need to update simply because `main` changes.diff --git a/README.md b/README.md--- a/README.md+++ b/README.md@@ -15,12 +15,41 @@ A Cargo workspace (edition 2024, resolver 3). Each library is a crate under `cra (`license.workspace = true`, and so on) and `[lints] workspace = true`. Register each crate in `[workspace.dependencies]` in the root `Cargo.toml`. -Apps depend on a crate by git:+## Use a released version++The first coordinated release is **[v0.1.0](https://github.com/storytold/craft-libs/releases/tag/v0.1.0)**.+It gives consumers a fixed baseline while development continues on `main`. All five crates+share this version. They require Rust 1.95 or later; the UI integrations use egui 0.36.++Add only the crates you need, using the same tag for every craft-libs dependency:  ```toml-craft-<name> = { git = "https://github.com/storytold/craft-libs", rev = "<commit>" }+[dependencies]+craft-ui = { git = "https://github.com/storytold/craft-libs", tag = "v0.1.0" }+craft-settings = { git = "https://github.com/storytold/craft-libs", tag = "v0.1.0" }+# Optional, for egui close handling and the macOS application menu:+craft-quit = { git = "https://github.com/storytold/craft-libs", tag = "v0.1.0", features = ["menu"] } ``` +`craft-atomic` and `craft-print` use the same dependency syntax. Enable `craft-ui`'s+`serde` feature if you need to serialize its docking layout. These are Git releases;+crates.io publication is deferred.++Release tags are never moved or reused. For a commit pin, resolve the tag with+`git ls-remote https://github.com/storytold/craft-libs 'refs/tags/v0.1.0^{}'` and replace+`tag = "v0.1.0"` with `rev = "<full commit SHA>"` on every craft-libs dependency.+Use either `tag` or `rev`, not both. An existing commit pin keeps working; switching to this+release may require adapting to changes since that commit.++Commit your application's `Cargo.lock` and build with `cargo build --locked` for reproducible+Rust dependency resolution. A Git pin fixes craft-libs source, not every transitive dependency.+A library's own lockfile does not constrain its downstream consumers. Upgrade deliberately:+read the release notes, update all craft-libs pins together, refresh the lockfile with+`cargo check`, and run your application's tests and affected workflows before committing.++See the [release notes](CHANGELOG.md) for included functionality and known limits, and the+[versioning policy](docs/versioning.md) for compatibility guarantees and release checks.+ ## Libraries  - [`craft-atomic`](crates/atomic/README.md): Crash-safe atomic file writing and replacement with same-directory staging, directory fsync, Apple `F_FULLFSYNC` fallback, transient lock backoff, and fault injection for the Craft suite.diff --git a/docs/versioning.md b/docs/versioning.mdnew file mode 100644--- /dev/null+++ b/docs/versioning.md@@ -0,0 +1,81 @@+# Versioning and releases++craft-libs releases give applications a fixed dependency baseline. Consumers decide when to+upgrade; development on `main` is not a reason to refresh a working application's pins.++## One workspace, one release++All crates inherit `workspace.package.version` and ship together under an annotated `vX.Y.Z`+Git tag. A release contains the crates listed in that tag's README, not proposed crates in+open pull requests. A crate can keep the same implementation across several workspace releases.+Use the same tag or commit for every craft-libs dependency in a consumer's dependency graph;+mixing Git sources can create duplicate crate instances and incompatible Rust types.++Tags identify reviewed commits and are never moved, deleted or reused to fix a release.+Corrections get a new version. The release notes and policy are stored with the source so a+consumer can read the contract that applied to its version. GitHub Releases carry the same notes.+Publishing to crates.io will be a separate step; these tags do not imply registry availability.++## Compatibility while versions are 0.x++The initial release is `0.1.0`. APIs are still developing, but compatibility within a minor+release line is intentional:++- **Patch (`0.1.0` → `0.1.1`):** compatible fixes, documentation and additive APIs that preserve+  existing callers. Keep public signatures, feature defaults, supported targets, minimum Rust+  version and documented behavior compatible. Check that additions do not break exhaustive+  matches, struct literals, trait implementations or other existing source patterns.+- **Minor (`0.1.x` → `0.2.0`):** changes requiring consumer action. This includes removing or+  changing public APIs, incompatible persisted representations, feature/default changes,+  dropping a supported target, raising the minimum Rust version, or upgrading a dependency+  such as egui when its exposed types become incompatible. Explain the before/after and migration.+- **`1.0.0`:** a separate decision that the public contracts are ready for long-term stability.+  After that, breaking changes require a major release; compatible additions use minor releases.++Documented invalid input can be rejected more strictly in a patch to fix a defect or security+issue. Call out any observable change. Do not use “0.x” or “bug fix” to silently break a valid,+documented workflow. App-owned settings schemas and migration policy remain the app's+responsibility; library releases do not automatically migrate consumer data.++For public egui APIs in `0.1.x`, keep the egui 0.36 compatibility line. The minimum Rust version+is 1.95. Compatible transitive updates still need validation and release-note coverage when+observable. Cargo's version-range rules do not select newer Git tags: changing a release pin+is always an explicit manifest edit.++## Support and scope++The newest minor line receives routine fixes. Important fixes to older lines are considered+case by case; there is no promise of maintaining every 0.x line or an LTS schedule. Existing+tags remain available so consumers can upgrade on their own schedule. Release notes identify+known limitations; a tag is not a claim that every driver, OS version or consuming app was tested.++Platform boundaries are crate-specific. See each crate's API/README and the release notes.+In particular, native printing needs the OS spooler, settings persistence is native-only, and+browser UI compatibility does not imply native services work in a browser. Consumers must test+their own save/close flows, accessibility, rendering and printing where they use those services.++## Preparing a release++1. Choose a reviewed commit on `main`. Inspect open defects, changes since the previous tag,+   crate metadata and any changed platform/dependency contracts. Update the shared version+   and lockfile when needed; the first release already uses `0.1.0`.+2. Add a dated `CHANGELOG.md` entry with the included crates, changes, compatibility requirements,+   migration steps and known limits. Update the README's recommended pin. Keep fixes and+   unrelated pending features out of the release preparation unless they block the baseline.+3. Run formatting, workspace Clippy with warnings denied, and workspace tests, both default+   and all features. The `Workspace` workflow runs these on Linux, macOS and Windows, requires+   Windows spooler regression tests, checks the minimum compiler on Linux, and checks the+   documented UI/settings WASM surface. All release jobs must pass for the candidate source.+   Repository-local build commands must also follow the host's storage/allocation rules.+4. Review consumer impact and existing platform evidence. Exercise affected native workflows+   when behavior changes; unit tests and cross-compilation cannot establish GUI or physical+   printer acceptance. Record limitations instead of extending the support claim beyond evidence.+5. Merge the preparation PR and verify the checks for the actual release commit. Create an+   annotated tag on that exact commit (`git tag -a vX.Y.Z FULL_SHA -m "craft-libs vX.Y.Z"`),+   push only that tag, and create a GitHub Release using that version's changelog entry.+   Tag-triggered CI should also pass. Do not publish crates as part of this Git-only release.+6. Verify that the remote tag resolves to the intended commit, the release notes are visible,+   and a small external consumer resolves and checks with the documented pin. Preserve the+   source identity, check results and release URL. Never repair a published tag by moving it.++The workflow validates source; it does not automatically tag or publish on every push.