Skip to content

feat(packaging): create shipper-core library crate (#95 PR 1)#140

Merged
EffortlessSteven merged 2 commits into
mainfrom
feat/95-pr1-shipper-core
Apr 18, 2026
Merged

feat(packaging): create shipper-core library crate (#95 PR 1)#140
EffortlessSteven merged 2 commits into
mainfrom
feat/95-pr1-shipper-core

Conversation

@EffortlessSteven

Copy link
Copy Markdown
Member

Summary

Reworking #95 into the three-crate split originally specified:

shipper (installable façade)
  -> shipper-cli (real CLI adapter)           [PR 2]
       -> shipper-core (pure library/engine)  [THIS PR]

This PR is the bottom layer only. It moves every non-CLI module out of crates/shipper/src/ into a new crates/shipper-core/ crate and leaves shipper as a thin re-export façade so the rest of the workspace keeps compiling unchanged.

Why this reopens #95

#135 merged a different shape: shipper carried lib + bin, with shipper-cli as a 9-line compat shim. That conflated engine code and CLI code in one crate, left shipper-cli as a shim with no value, and didn't match the goal of a no-clap library surface. The three-crate split below is what was originally asked for.

What moved

All moved via git mv so history is preserved:

  • crates/shipper/src/{engine,state,ops,plan,runtime}/ → shipper-core
  • crates/shipper/src/{config,encryption,git,types,webhook,property_tests,stress_tests}.rs → shipper-core
  • crates/shipper/src/lib.rs → shipper-core (edited: dropped pub mod cli;, retargeted docs at shipper_core)
  • proptest-regressions fixtures moved with their owning tests

What stayed in crates/shipper/:

  • src/cli/ (moves to shipper-cli in PR 2)
  • src/bin/shipper.rs (this crate owns the installable binary)

Façade

The new crates/shipper/src/lib.rs re-exports shipper-core's public surface (auth, cargo, cargo_failure, config, encryption, engine, git, lock, plan, registry, retry, runtime, state, store, types, webhook) so every shipper::X import path still resolves. PR 3 slims this to a curated list once shipper-cli takes over the CLI.

Snapshots

326 insta snapshots renamed shipper__*.snapshipper_core__*.snap to match the new crate prefix in module_path!(). No content changes.

CI

Architecture-guard workflow updated to watch crates/shipper-core/src/** (where the layer dirs now live) in addition to crates/shipper/src/**, so the upward-import check keeps enforcing instead of silently skipping.

Verification

  • cargo check --workspace --all-targets — clean
  • cargo clippy --workspace --all-targets --all-features -- -D warnings — clean
  • cargo test -p shipper-core --lib — 1889 passed
  • cargo test -p shipper — 39 passed
  • Full workspace test run — all passed except pre-existing Windows-only flakes (preflight_command_* temp-dir locking) that pass in isolation and are unrelated to this split.

What this PR does not do

  • Does not move the CLI (PR 2)
  • Does not slim crates/shipper's Cargo.toml or README (PR 3)
  • Does not touch workspace-wide docs or how-to guides (PR 4)

Test plan

  • cargo check --workspace --all-targets
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test -p shipper-core
  • cargo test -p shipper
  • CI green on all matrices
  • Architecture guard still enforcing (layer dirs detected under shipper-core/src)

Closes #95 (partial — full close lands with PR 4).

Reworking #95 into the three-crate split the user specified originally:

    shipper (installable facade)
      -> shipper-cli (real CLI adapter)           [PR 2]
           -> shipper-core (pure library/engine)  [THIS PR]

This PR is the bottom layer only. It moves every non-CLI module out of
`crates/shipper/src/` into a new `crates/shipper-core/` crate and
leaves `shipper` as a thin re-export facade so the rest of the
workspace (shipper-cli, integration tests, downstream code) keeps
compiling unchanged.

## Why this reopens #95

#135 merged a different shape: `shipper` carried the lib + bin, with
`shipper-cli` as a 9-line compat shim. That conflated engine code and
CLI code in one crate, left `shipper-cli` as a shim with no value, and
didn't match the design goal of a no-clap library surface. The
three-crate split below is what was originally asked for.

## What moved

All moved via `git mv` so history is preserved:

- `crates/shipper/src/{engine,state,ops,plan,runtime}/` → shipper-core
- `crates/shipper/src/{config,encryption,git,types,webhook,
  property_tests,stress_tests}.rs` → shipper-core
- `crates/shipper/src/lib.rs` → shipper-core (then edited to drop the
  `pub mod cli;` declaration and retarget docs at `shipper_core`)
- proptest-regressions fixtures moved with their owning tests

What stayed in `crates/shipper/`:

- `src/cli/` (moves to `shipper-cli` in PR 2)
- `src/bin/shipper.rs` (stays — this crate owns the installable binary)

## Facade

The new `crates/shipper/src/lib.rs` re-exports shipper-core's public
surface (auth, cargo, cargo_failure, config, encryption, engine, git,
lock, plan, registry, retry, runtime, state, store, types, webhook) so
every existing `shipper::X` import path still resolves. PR 3 slims
this to a curated re-export list once `shipper-cli` takes over the CLI.

## Snapshots

326 insta snapshots renamed `shipper__*.snap` → `shipper_core__*.snap`
to match the new crate prefix in `module_path!()`. Tests pass with
the renamed files; no content changes.

## CI

Architecture-guard workflow updated to watch
`crates/shipper-core/src/**` (where the layer dirs now live) in
addition to `crates/shipper/src/**`, so the upward-import check keeps
enforcing instead of silently skipping.

## Verification

- `cargo check --workspace --all-targets` — clean
- `cargo clippy --workspace --all-targets --all-features -- -D warnings` — clean
- `cargo test -p shipper-core --lib` — 1889 passed
- `cargo test -p shipper` — 39 passed
- Full workspace test run — all passed except pre-existing Windows-
  specific flakes (`concurrent_version_exists_checks` on macOS,
  `preflight_command_*` temp-dir locking on Windows); both pass in
  isolation and are unrelated to this split.

## What this PR does not do

- Does not move the CLI (that's PR 2)
- Does not slim `crates/shipper`'s Cargo.toml or README (PR 3)
- Does not touch workspace-wide docs or how-to guides (PR 4)
@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features
    • New shipper-core library crate now available for direct programmatic use. Provides core publishing capabilities including planning, state management, registry access, and remediation without CLI dependencies. Pre-1.0 stability release.

Walkthrough

A new shipper-core crate is introduced as a library-only engine layer for cargo publish operations, extracted to separate core reliability logic from CLI concerns. The root workspace configuration and architecture guard workflow are updated to include the new crate and monitor its module layers for import violations.

Changes

Cohort / File(s) Summary
Workspace Configuration
Cargo.toml, .github/workflows/architecture-guard.yml
Added shipper-core as a workspace member and intra-workspace dependency; updated CI workflow triggers and layer violation checks to monitor crates/shipper-core/src/{ops,runtime,state,plan} alongside existing shipper paths.
Crate Scaffolding
crates/shipper-core/Cargo.toml, crates/shipper-core/README.md
New crate manifest with comprehensive dependency list including workspace microcrates and external libraries for crypto, serialization, HTTP, async runtime, and testing; README documents the crate as the non-CLI engine layer and stability expectations.
Library API Surface
crates/shipper-core/src/lib.rs
Root module exposing public API via module declarations and re-exports: auth, config, engine, git, plan, runtime, state, types, webhook, encryption, plus compatibility shims for absorbed microcrates (lock, registry, retry, cargo_failure) and custom store module path.
Module Updates
crates/shipper-core/src/git.rs, crates/shipper-core/src/ops/lock/mod.rs
Documentation links and Rust doc example imports updated to reference shipper-core paths instead of shipper paths; no logic or API changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A new core emerges from the warren,

Where engines hum sans CLI's siren—

Shipper-core ascends, pure and keen,

No binary bloat to clog the scene! ⚙️✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ❓ Inconclusive The PR partially addresses #95 by implementing the foundational three-crate split (shipper-core as pure library layer), but #95's primary acceptance criteria require the binary to be installable via 'cargo install shipper' with CLI deps feature-gated, which is deferred to PR 2 and PR 3. This PR 1 establishes the library layer; verify that PRs 2–3 together deliver all #95 acceptance criteria, including binary availability, feature-gating, and embedder opt-out via default-features = false.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(packaging): create shipper-core library crate (#95 PR 1)' clearly and concisely identifies the main change: introducing a new shipper-core library crate as the first PR in a three-crate split effort.
Description check ✅ Passed The description provides comprehensive context about the three-crate split reorganization, what was moved, why it reopens #95, and verification results, all directly related to the changeset.
Out of Scope Changes check ✅ Passed All changes directly support the stated three-crate split objective: crate creation, non-CLI module movement, facade re-exports, snapshot renames, and CI updates are all in-scope for PR 1 of this reorganization.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/95-pr1-shipper-core

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the shipper-core crate, which centralizes the engine, planning, and state logic previously distributed across microcrates as part of a decrating effort. The implementation includes the crate's manifest, documentation, and public API surface. Review feedback points out the use of non-existent dependency versions in Cargo.toml and suggests a more idiomatic approach for module re-exports in lib.rs by replacing the #[path] attribute with a standard pub use statement.

Comment on lines +28 to +62
anyhow = "1.0.102"
thiserror = "2.0.18"
cargo_metadata = "0.23.1"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
serde_with = "3.17.0"
reqwest = { version = "0.13.2", features = ["blocking", "json", "rustls"] }
rand = { version = "0.10.1", features = ["std"] }
chrono = { version = "0.4.44", features = ["serde"] }
humantime = "2.3.0"
which = "8.0"
toml = "1.0.3"
dirs = "6.0"
hex = "0.4.3"
gethostname = "1.1.0"
tokio = { version = "1.42", features = ["rt", "time", "sync", "macros"] }
base64 = "0.22"
aes-gcm = "0.10"
pbkdf2 = { version = "0.12", features = ["simple"] }

# HMAC for webhook signatures
hmac = "0.13"
sha2 = "0.11"

[lints]
workspace = true

[dev-dependencies]
tempfile = "3.26.0"
insta = { version = "1.46.3", features = ["yaml"] }
proptest = "1.10.0"
serial_test = "3.4.0"
tiny_http = "0.12.0"
temp-env = "0.3"
console = "0.16.3"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Several dependency versions specified here (e.g., reqwest 0.13.2, tempfile 3.26.0, rand 0.10.1, insta 1.46.3) appear to be non-existent or significantly ahead of current stable releases on crates.io. For instance, reqwest is currently at 0.12.x and tempfile is at 3.16.x. Using hallucinated or future versions will cause compilation failures in standard environments. Please verify and use the correct latest stable versions from crates.io.

Comment on lines +160 to +161
#[path = "state/store/mod.rs"]
pub mod store;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using #[path] to define a top-level module from a nested directory is non-idiomatic in modern Rust and can be confusing for both developers and tooling (like IDEs or rust-analyzer). Since state is already a public module, it is better to define the store module naturally within src/state/mod.rs and then use a pub use statement in lib.rs to provide the desired public API surface.

Suggested change
#[path = "state/store/mod.rs"]
pub mod store;
pub use crate::state::store;

@codecov

codecov Bot commented Apr 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Three doctests in `ops/lock/mod.rs` still used `use shipper::lock::LockFile;`
after the #95 PR 1 split. Doctests compile as external code against the
crate being tested, so the crate name now has to be `shipper_core`. Caught
by the `cargo test --workspace --doc` lane in CI (not covered by
`cargo test -p shipper-core --lib` locally).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/architecture-guard.yml:
- Around line 7-13: The workflow still lists the stale trigger path
'crates/shipper/src/**' but all guarded scans (ops, runtime, state, plan) are
now under 'crates/shipper-core/src/**', so remove the two occurrences of
'crates/shipper/src/**' from the workflow trigger paths (both push.paths
entries) to stop CI noise; alternatively, if you want to keep defending that
location, add corresponding scan entries for 'crates/shipper/src/' so the guards
will actually run.

In `@crates/shipper-core/Cargo.toml`:
- Around line 28-50: Move shared external dependencies (e.g., anyhow, serde,
serde_json, chrono, tokio, reqwest, etc.) out of this crate's Cargo.toml and
declare them centrally under [workspace.dependencies]; in addition set
serde.workspace = true in this crate (and other workspace crates using serde) so
they inherit the workspace version; remove the duplicated per-crate entries from
the current dependencies list and rely on the workspace-managed entries to
prevent version drift and duplicate copies in Cargo.lock.

In `@crates/shipper-core/README.md`:
- Around line 23-24: Update the README link to point to the crate-specific
changelog (change the linked path from `CHANGELOG.md` to
`crates/shipper-core/CHANGELOG.md`) so users see shipper-core breaking changes
only, and normalize repository owner casing to match `effortlessmetrics/shipper`
used in `crates/shipper-core/src/lib.rs` (make the README use
`effortlessmetrics/shipper`) to keep references consistent; verify the link
resolves and adjust any other occurrences in `README.md` or
`crates/shipper-core/src/lib.rs` for consistent casing.

In `@crates/shipper-core/src/lib.rs`:
- Around line 83-86: The intra-doc links ([lock], [store], [cargo],
[cargo_failure]) point to items re-exported via `pub use` and may not resolve
when cross-crate re-exports are in play; update the comment to use
fully-qualified paths for crate-local modules (e.g. [`crate::lock`],
[`crate::store`], [`crate::cargo`]) and for the cross-crate re-export use the
original crate name or fully-qualified external path (e.g.
[`shipper_cargo_failure`] or [`shipper_cargo_failure::...`]) so rustdoc can
resolve them reliably, then run `cargo doc -p shipper-core --no-deps` to confirm
no "unresolved link" warnings.
- Around line 153-161: The crate root currently mounts the store module via
#[path = "state/store/mod.rs"] pub mod store, which conflicts with the
documented architecture; instead, declare the module under the state module and
re-export it from the crate root: add pub(crate) mod store; to the state module
(state::mod) so the implementation lives at state::store, then remove the #[path
= ...] pub mod store declaration from lib.rs and replace it with a re-export
like pub use crate::state::store; so callers keep crate::store while the module
lives under state::store as intended.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0146297a-7a28-43f7-9792-bb861c037477

📥 Commits

Reviewing files that changed from the base of the PR and between f744091 and ddebac8.

⛔ Files ignored due to path filters (233)
  • Cargo.lock is excluded by !**/*.lock
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_chunk_by_max_concurrent_basic.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_chunk_by_max_concurrent_empty.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_chunk_by_max_concurrent_larger_than_items.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_chunk_by_max_concurrent_one.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_execution_plan_diamond.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_execution_plan_independent_forest.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_execution_plan_linear_chain.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_execution_plan_wide_fan_out.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_parallel_config_default.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_policy_effects_balanced.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_policy_effects_fast.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/parallel/snapshots/shipper_core__engine__parallel__tests__snapshot_tests__snapshot_policy_effects_safe.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/snapshots/shipper_core__engine__tests__error_classification_matrix.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/snapshots/shipper_core__engine__tests__init_state_multi_package.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/snapshots/shipper_core__engine__tests__init_state_single_package.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/snapshots/shipper_core__engine__tests__sm_receipt_multi_package.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/snapshots/shipper_core__engine__tests__sm_state_partial_failure.snap is excluded by !**/*.snap
  • crates/shipper-core/src/engine/snapshots/shipper_core__engine__tests__state_after_mixed_transitions.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__error_message_snapshots__error_msg_credentials_not_found.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__error_message_snapshots__error_msg_empty_credentials.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__error_message_snapshots__error_msg_malformed_toml.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__error_message_snapshots__error_msg_token_wrong_registry.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_credentials_crates_io_registry_section.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_credentials_custom_registry_section.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_credentials_file_with_all_formats.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_credentials_legacy_toplevel_format.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_error_malformed_credentials_file.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_error_missing_credentials_file.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_error_token_not_found_for_registry.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_list_configured_registries_empty.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_list_configured_registries_mixed.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__credentials__tests__snapshots__snapshot_list_registries_many.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_auth_info_not_detected.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_auth_info_with_credentials_file.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_auth_info_with_env_default.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_auth_info_with_env_registry.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_mask_token_long_value.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_mask_token_short_values.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_resolve_unicode_token.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_resolve_whitespace_token.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_token_source_credentials_file.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_token_source_env_default.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_token_source_env_registry.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__edge_snapshots__snapshot_token_source_none.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__error_message_snapshots__error_msg_missing_token.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__error_message_snapshots__error_msg_token_source_none.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__snapshots__snapshot_auth_info_default.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__snapshots__snapshot_resolve_token_custom_registry_from_credentials.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__snapshots__snapshot_resolve_token_from_credentials_file.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__snapshots__snapshot_resolve_token_from_env_default.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__snapshots__snapshot_resolve_token_from_env_registry.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/auth/snapshots/shipper_core__ops__auth__resolver__tests__snapshots__snapshot_resolve_token_none_found.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/cargo/snapshots/shipper_core__ops__cargo__tests__snapshot_tests_absorbed__snapshot_invalid_package_names.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/cargo/snapshots/shipper_core__ops__cargo__tests__snapshot_tests_absorbed__snapshot_package_info_prerelease_version.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/cargo/snapshots/shipper_core__ops__cargo__tests__snapshot_tests_absorbed__snapshot_package_info_simple.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/cargo/snapshots/shipper_core__ops__cargo__tests__snapshot_tests_absorbed__snapshot_package_info_with_registries.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/cargo/snapshots/shipper_core__ops__cargo__tests__snapshot_tests_absorbed__snapshot_valid_package_names.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__clean_result_err_not_git.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__clean_result_err_uncommitted.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__clean_result_ok.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__context_all_fields.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__context_detached_head.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__context_dirty_detached.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__context_dirty_with_tag.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__context_feature_branch_clean.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__context_no_commit_no_branch.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__context_tagged_detached.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__is_dirty_all_variants.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__porcelain_empty_output.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__porcelain_parsed_files.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__porcelain_renamed_and_copied.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__porcelain_spaces_in_names.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__short_commit_empty_string.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__edge_case_snapshots__short_commit_exactly_eight.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__clean_working_tree.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__dirty_default_behavior.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__dirty_working_tree.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__ensure_git_clean_error.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__git_context_commit_only.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__git_context_dirty_no_tag.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__git_context_empty.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__git_context_full.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__git_rev_parse_failed_error.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__git_status_failed_error.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__short_commit_full_hash.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__short_commit_none.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__short_commit_seven_chars.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__short_commit_short_hash.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__tag_absent.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__tag_dirty_tree.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__tag_prerelease.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__tag_semver.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/git/snapshots/shipper_core__ops__git__context__snapshot_tests__unknown_dirty_state.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__edge_case_tests__lock_info_all_fields.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__edge_case_tests__lock_info_no_plan_id.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__edge_case_tests__lock_state_corrupt.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__edge_case_tests__lock_state_locked_no_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__edge_case_tests__lock_state_locked_with_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__edge_case_tests__lock_state_stale.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__edge_case_tests__lock_state_unlocked.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__hardened_tests__lock_file_after_set_plan_id.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__hardened_tests__lock_info_empty_plan_id.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__hardened_tests__lock_info_json_key_order.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__error_corrupt_lock_file_prefix.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__error_fresh_lock_with_timeout_prefix.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__error_lock_already_held.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__error_lock_already_held_with_plan_id.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__error_read_nonexistent_lock_prefix.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__error_set_plan_id_after_release_prefix.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_file_content_with_plan_id.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_file_content_without_plan_id.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_file_on_disk.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_info_debug.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_info_yaml.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_path_with_root_filename.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_path_without_root.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_status_locked.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/lock/snapshots/shipper_core__ops__lock__snapshot_tests__lock_status_unlocked.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_output_failure.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_output_json_format.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_output_success.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_output_timed_out.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_result_failure_no_exit_code.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_result_failure_with_exit_code.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_result_json_format.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_result_success.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__command_result_with_multiline_output.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__error_message_empty_stderr.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__error_message_with_exit_code.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__error_message_without_exit_code.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__snapshot_publish_args_basic.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__snapshot_publish_args_full_flags.snap is excluded by !**/*.snap
  • crates/shipper-core/src/ops/process/snapshots/shipper_core__ops__process__snapshot_tests__snapshot_publish_args_with_registry_and_no_verify.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_1000_items_by_10.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_10_items_by_5.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_13_items_by_4_with_remainder.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_5_by_2.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_6_by_3.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_7_items_by_3.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_empty.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_exact_fit.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_large_list_by_7.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_max_concurrent_1.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_max_concurrent_usize_max.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_max_concurrent_zero.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_prime_37_by_6.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_single_item.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_single_item_max_one.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_chunk_size_1_with_4_items.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/chunking/snapshots/shipper_core__plan__chunking__snapshot_tests__snapshot_dependency_like_items_by_2.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_all_independent.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_cycle_fallback.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_deep_binary_tree.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_diamond_dependency.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_disconnected_components.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_double_diamond.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_empty_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_linear_chain.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/levels/snapshots/shipper_core__plan__levels__snapshot_tests__snapshot_wide_fan_out.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__build_dep_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__deep_chain_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__dev_dep_cycle_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__diamond_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__double_diamond_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__double_diamond_selected_mid.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__empty_workspace_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_cycle_detection.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_msg_cycle_detection.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_msg_missing_manifest.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_msg_non_publishable_dep.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_msg_selecting_non_publishable.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_msg_unknown_selected_package.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_non_publishable_dep.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_selecting_non_publishable.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__error_unknown_package.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__linear_chain_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__mixed_dep_kinds_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__multi_crate_plan_with_deps.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__multi_select_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__package_selection_b.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__plan_summary_display.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__prerelease_versions_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__single_crate_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__skipped_packages_detail.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__special_names_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/plan/snapshots/shipper_core__plan__tests__wide_flat_plan_5.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__ci_environment_all_debug_variants.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__ci_environment_all_display_variants.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__ci_environment_serialization.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_fingerprint_prerelease_version.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_fingerprint_structured.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_fingerprint_structured_unknown_versions.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_info_fingerprint_github_actions_with_vars.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_info_fingerprint_local_no_vars.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_info_fingerprint_string_ci_with_vars.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_info_fingerprint_string_local.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_info_gitlab_ci.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_info_many_env_vars.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/environment/snapshots/shipper_core__runtime__environment__snapshot_tests__environment_info_windows_aarch64.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_backoff_constant_sequence.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_backoff_exponential_clamped.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_backoff_exponential_sequence.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_backoff_immediate_sequence.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_backoff_linear_sequence.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_classify_already_uploaded.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_classify_auth_denied.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_classify_empty_output.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_classify_network_reset.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_classify_network_timeout.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_classify_rate_limit.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_classify_unknown_error.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_execution_state_empty_packages.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_execution_state_single_ambiguous.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_execution_state_single_failed.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_execution_state_single_pending.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_execution_state_single_published.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_execution_state_single_skipped.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_execution_state_single_uploaded.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_retry_config_constant.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_retry_config_exponential.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_retry_config_immediate.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_retry_config_linear.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_state_ambiguous_resolved.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_state_failure_flow.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_state_multi_package_mixed_outcomes.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_state_skip_flow.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_state_success_flow.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_transition_all_skipped_plan.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_transition_ambiguous_to_published.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_transition_pending_to_failed_retry_to_published.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/execution/snapshots/shipper_core__runtime__execution__tests__snapshots__snapshot_transition_pending_to_uploaded_to_published.snap is excluded by !**/*.snap
  • crates/shipper-core/src/runtime/policy/snapshots/shipper_core__runtime__policy__serialization_snapshot_tests__all_policy_kinds.snap is excluded by !**/*.snap
📒 Files selected for processing (67)
  • .github/workflows/architecture-guard.yml
  • Cargo.toml
  • crates/shipper-core/Cargo.toml
  • crates/shipper-core/README.md
  • crates/shipper-core/proptest-regressions/property_tests.txt
  • crates/shipper-core/proptest-regressions/types.txt
  • crates/shipper-core/src/config.rs
  • crates/shipper-core/src/encryption.rs
  • crates/shipper-core/src/engine/CLAUDE.md
  • crates/shipper-core/src/engine/fix_forward.rs
  • crates/shipper-core/src/engine/mod.rs
  • crates/shipper-core/src/engine/parallel/CLAUDE.md
  • crates/shipper-core/src/engine/parallel/mod.rs
  • crates/shipper-core/src/engine/parallel/policy.rs
  • crates/shipper-core/src/engine/parallel/publish.rs
  • crates/shipper-core/src/engine/parallel/readiness.rs
  • crates/shipper-core/src/engine/parallel/reconcile.rs
  • crates/shipper-core/src/engine/parallel/tests.rs
  • crates/shipper-core/src/engine/parallel/webhook.rs
  • crates/shipper-core/src/engine/plan_yank.rs
  • crates/shipper-core/src/git.rs
  • crates/shipper-core/src/lib.rs
  • crates/shipper-core/src/ops/CLAUDE.md
  • crates/shipper-core/src/ops/auth/CLAUDE.md
  • crates/shipper-core/src/ops/auth/credentials.rs
  • crates/shipper-core/src/ops/auth/mod.rs
  • crates/shipper-core/src/ops/auth/oidc.rs
  • crates/shipper-core/src/ops/auth/resolver.rs
  • crates/shipper-core/src/ops/cargo/CLAUDE.md
  • crates/shipper-core/src/ops/cargo/mod.rs
  • crates/shipper-core/src/ops/git/CLAUDE.md
  • crates/shipper-core/src/ops/git/bin_override.rs
  • crates/shipper-core/src/ops/git/cleanliness.rs
  • crates/shipper-core/src/ops/git/context.rs
  • crates/shipper-core/src/ops/git/mod.rs
  • crates/shipper-core/src/ops/lock/CLAUDE.md
  • crates/shipper-core/src/ops/lock/mod.rs
  • crates/shipper-core/src/ops/mod.rs
  • crates/shipper-core/src/ops/process/CLAUDE.md
  • crates/shipper-core/src/ops/process/cargo.rs
  • crates/shipper-core/src/ops/process/cross_platform_edge_case_tests.rs
  • crates/shipper-core/src/ops/process/mod.rs
  • crates/shipper-core/src/ops/process/run.rs
  • crates/shipper-core/src/ops/process/snapshot_tests.rs
  • crates/shipper-core/src/ops/process/tests.rs
  • crates/shipper-core/src/ops/process/timeout.rs
  • crates/shipper-core/src/ops/process/types.rs
  • crates/shipper-core/src/ops/process/which.rs
  • crates/shipper-core/src/ops/storage/CLAUDE.md
  • crates/shipper-core/src/ops/storage/mod.rs
  • crates/shipper-core/src/plan/CLAUDE.md
  • crates/shipper-core/src/plan/chunking/CLAUDE.md
  • crates/shipper-core/src/plan/chunking/mod.rs
  • crates/shipper-core/src/plan/levels/CLAUDE.md
  • crates/shipper-core/src/plan/levels/mod.rs
  • crates/shipper-core/src/plan/mod.rs
  • crates/shipper-core/src/property_tests.rs
  • crates/shipper-core/src/runtime/CLAUDE.md
  • crates/shipper-core/src/runtime/environment/CLAUDE.md
  • crates/shipper-core/src/runtime/environment/ci.rs
  • crates/shipper-core/src/runtime/environment/fingerprint.rs
  • crates/shipper-core/src/runtime/environment/mod.rs
  • crates/shipper-core/src/runtime/execution/CLAUDE.md
  • crates/shipper-core/src/runtime/execution/mod.rs
  • crates/shipper-core/src/runtime/mod.rs
  • crates/shipper-core/src/runtime/policy/CLAUDE.md
  • crates/shipper-core/src/runtime/policy/mod.rs

Comment on lines +7 to 13
- 'crates/shipper-core/src/**'
- 'crates/shipper/src/**'
push:
branches: [main]
paths:
- 'crates/shipper-core/src/**'
- 'crates/shipper/src/**'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Trigger path crates/shipper/src/** no longer matches any guarded scan.

After the move, all four scanned layers (ops, runtime, state, plan) live exclusively under crates/shipper-core/src/. The trigger paths still include crates/shipper/src/** (lines 8 and 13), so the workflow will run on CLI-only changes but find nothing to check (all four "layer not scaffolded" guards will skip). Either drop the crates/shipper/src/** triggers, or keep them and add scans against crates/shipper/src/ if you want to defend against the layers being re-introduced there. Currently it's just CI noise.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/architecture-guard.yml around lines 7 - 13, The workflow
still lists the stale trigger path 'crates/shipper/src/**' but all guarded scans
(ops, runtime, state, plan) are now under 'crates/shipper-core/src/**', so
remove the two occurrences of 'crates/shipper/src/**' from the workflow trigger
paths (both push.paths entries) to stop CI noise; alternatively, if you want to
keep defending that location, add corresponding scan entries for
'crates/shipper/src/' so the guards will actually run.

Comment on lines +28 to +50
anyhow = "1.0.102"
thiserror = "2.0.18"
cargo_metadata = "0.23.1"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
serde_with = "3.17.0"
reqwest = { version = "0.13.2", features = ["blocking", "json", "rustls"] }
rand = { version = "0.10.1", features = ["std"] }
chrono = { version = "0.4.44", features = ["serde"] }
humantime = "2.3.0"
which = "8.0"
toml = "1.0.3"
dirs = "6.0"
hex = "0.4.3"
gethostname = "1.1.0"
tokio = { version = "1.42", features = ["rt", "time", "sync", "macros"] }
base64 = "0.22"
aes-gcm = "0.10"
pbkdf2 = { version = "0.12", features = ["simple"] }

# HMAC for webhook signatures
hmac = "0.13"
sha2 = "0.11"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider routing external deps through [workspace.dependencies].

Many of these (anyhow, serde, serde_json, chrono, tokio, reqwest, tempfile, insta, proptest, etc.) are likely already used by other crates in the workspace. Pinning them per-crate makes version drift easy and produces duplicate copies in Cargo.lock if they get out of sync. Promoting them to [workspace.dependencies] and using serde.workspace = true (as already done for the intra-workspace crates above) would centralize version management. Out of scope for this PR if other crates haven't migrated either, but worth tracking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/shipper-core/Cargo.toml` around lines 28 - 50, Move shared external
dependencies (e.g., anyhow, serde, serde_json, chrono, tokio, reqwest, etc.) out
of this crate's Cargo.toml and declare them centrally under
[workspace.dependencies]; in addition set serde.workspace = true in this crate
(and other workspace crates using serde) so they inherit the workspace version;
remove the duplicated per-crate entries from the current dependencies list and
rely on the workspace-managed entries to prevent version drift and duplicate
copies in Cargo.lock.

Comment on lines +23 to +24
Pre-1.0. The public API will move; breaking changes are called out in
[`CHANGELOG.md`](https://github.com/EffortlessMetrics/shipper/blob/main/CHANGELOG.md).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Verify the CHANGELOG link target.

The README links to a repo-root CHANGELOG.md. If the per-crate API changes are tracked in a crates/shipper-core/CHANGELOG.md (as suggested by the PR description's "points users to crates/shipper-core/CHANGELOG.md for breaking-change tracking"), consider linking there instead so embedders see only shipper-core breaking changes rather than the full repo changelog.

Also note a minor inconsistency: crates/shipper-core/src/lib.rs line 92 uses effortlessmetrics/shipper (lowercase) while this README uses EffortlessMetrics/shipper. GitHub resolves both, but consistency is preferable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/shipper-core/README.md` around lines 23 - 24, Update the README link
to point to the crate-specific changelog (change the linked path from
`CHANGELOG.md` to `crates/shipper-core/CHANGELOG.md`) so users see shipper-core
breaking changes only, and normalize repository owner casing to match
`effortlessmetrics/shipper` used in `crates/shipper-core/src/lib.rs` (make the
README use `effortlessmetrics/shipper`) to keep references consistent; verify
the link resolves and adjust any other occurrences in `README.md` or
`crates/shipper-core/src/lib.rs` for consistent casing.

Comment on lines +83 to +86
//! - [`lock`] — Distributed lock to prevent concurrent publishes
//! - [`store`] — `StateStore` trait for pluggable persistence backends
//! - [`cargo`] — Workspace metadata via `cargo_metadata`
//! - [`cargo_failure`] — Cargo publish failure classification heuristics

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Doc intra-links to re-exports may not resolve.

[lock], [store], [cargo], and [cargo_failure] in the module list reference items introduced via pub use rather than pub mod. Rustdoc generally resolves these, but with cross-crate re-exports (pub use shipper_cargo_failure as cargo_failure;) the link target depends on how rustdoc inlines the re-export. Worth running cargo doc -p shipper-core --no-deps and checking for "unresolved link" warnings before publish.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/shipper-core/src/lib.rs` around lines 83 - 86, The intra-doc links
([lock], [store], [cargo], [cargo_failure]) point to items re-exported via `pub
use` and may not resolve when cross-crate re-exports are in play; update the
comment to use fully-qualified paths for crate-local modules (e.g.
[`crate::lock`], [`crate::store`], [`crate::cargo`]) and for the cross-crate
re-export use the original crate name or fully-qualified external path (e.g.
[`shipper_cargo_failure`] or [`shipper_cargo_failure::...`]) so rustdoc can
resolve them reliably, then run `cargo doc -p shipper-core --no-deps` to confirm
no "unresolved link" warnings.

Comment on lines +153 to +161
pub mod state;

/// `StateStore` trait for pluggable persistence backends.
///
/// Absorbed from the former `shipper-store` microcrate. The implementation
/// now lives under `state/store/` to reflect the layered architecture;
/// the public path `shipper::store` is preserved for backward compatibility.
#[path = "state/store/mod.rs"]
pub mod store;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm whether state/mod.rs already declares store as a child module.
fd -t f 'mod.rs' crates/shipper-core/src/state -d 2 -x cat {}
echo "---"
rg -nP '\bmod\s+store\b' crates/shipper-core/src/state/
echo "--- any state items in the store impl? ---"
rg -nP 'use\s+(crate|super)::' crates/shipper-core/src/state/store/ | head -40

Repository: EffortlessMetrics/shipper

Length of output: 20411


Module structure misalignment: store is declared at crate root but documented as living under state/.

The file crates/shipper-core/src/state/store/mod.rs physically resides in the state directory tree, and the doc comment claims "the implementation now lives under state/store/" — but state/mod.rs does not declare pub mod store;. Instead, store is mounted only at the crate root via #[path = "state/store/mod.rs"].

While this does not currently cause a double-compile (since state/mod.rs does not redeclare store), it creates a maintenance hazard and documentation inconsistency:

  • The doc comment and file location strongly suggest state::store is the canonical path
  • CLAUDE.md (line 28) states the intent: expose pub(crate) mod store; from state to make crate::state::store usable
  • But the actual module tree does not reflect this structure

Either add pub mod store; to state/mod.rs and remove the #[path] declaration to align with the documented architecture, or update the doc comment and move/rename the file location to reflect that store is a crate-root module.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/shipper-core/src/lib.rs` around lines 153 - 161, The crate root
currently mounts the store module via #[path = "state/store/mod.rs"] pub mod
store, which conflicts with the documented architecture; instead, declare the
module under the state module and re-export it from the crate root: add
pub(crate) mod store; to the state module (state::mod) so the implementation
lives at state::store, then remove the #[path = ...] pub mod store declaration
from lib.rs and replace it with a re-export like pub use crate::state::store; so
callers keep crate::store while the module lives under state::store as intended.

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.

Packaging UX: make 'cargo install shipper' work by collapsing binary into shipper package

1 participant