Skip to content

Commit 828348b

Browse files
fix(release): make harmont-cli crates.io-publishable (or drop the dead channel) and fix install docs (#129)
1 parent 2d7d1a6 commit 828348b

3 files changed

Lines changed: 91 additions & 19 deletions

File tree

.github/workflows/release.yml

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,46 @@ jobs:
3434
VERSION="${GITHUB_REF_NAME#v}"
3535
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
3636
37-
# Bump crate versions
37+
# Bump crate versions. Every workspace member that harmont-cli
38+
# depends on (directly or transitively) must be published, so each
39+
# one needs the tagged version stamped in.
3840
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-util/Cargo.toml
3941
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-pipeline-ir/Cargo.toml
42+
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-config/Cargo.toml
4043
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-plugin-protocol/Cargo.toml
44+
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-render/Cargo.toml
45+
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-vm/Cargo.toml
46+
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-exec/Cargo.toml
4147
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-plugin-cloud/Cargo.toml
4248
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm-dsl-engine/Cargo.toml
4349
sed -i "0,/version = \"0.0.0-dev\"/s//version = \"$VERSION\"/" crates/hm/Cargo.toml
4450
4551
# Rewrite workspace.dependencies pins so dependents resolve to the
4652
# tagged version (cargo publish strips path deps; the version field
4753
# is what consumers will receive).
48-
sed -i "s|hm-util = { path = \"crates/hm-util\", version = \"0.0.0-dev\" }|hm-util = { path = \"crates/hm-util\", version = \"$VERSION\" }|" Cargo.toml
49-
sed -i "s|hm-pipeline-ir = { path = \"crates/hm-pipeline-ir\", version = \"0.0.0-dev\" }|hm-pipeline-ir = { path = \"crates/hm-pipeline-ir\", version = \"$VERSION\" }|" Cargo.toml
54+
sed -i "s|hm-exec = { path = \"crates/hm-exec\", version = \"0.0.0-dev\" }|hm-exec = { path = \"crates/hm-exec\", version = \"$VERSION\" }|" Cargo.toml
5055
sed -i "s|hm-plugin-protocol = { path = \"crates/hm-plugin-protocol\", version = \"0.0.0-dev\" }|hm-plugin-protocol = { path = \"crates/hm-plugin-protocol\", version = \"$VERSION\" }|" Cargo.toml
5156
sed -i "s|hm-plugin-cloud = { path = \"crates/hm-plugin-cloud\", version = \"0.0.0-dev\" }|hm-plugin-cloud = { path = \"crates/hm-plugin-cloud\", version = \"$VERSION\" }|" Cargo.toml
57+
sed -i "s|hm-pipeline-ir = { path = \"crates/hm-pipeline-ir\", version = \"0.0.0-dev\" }|hm-pipeline-ir = { path = \"crates/hm-pipeline-ir\", version = \"$VERSION\" }|" Cargo.toml
58+
sed -i "s|hm-util = { path = \"crates/hm-util\", version = \"0.0.0-dev\" }|hm-util = { path = \"crates/hm-util\", version = \"$VERSION\" }|" Cargo.toml
59+
sed -i "s|hm-config = { path = \"crates/hm-config\", version = \"0.0.0-dev\" }|hm-config = { path = \"crates/hm-config\", version = \"$VERSION\" }|" Cargo.toml
5260
sed -i "s|hm-dsl-engine = { path = \"crates/hm-dsl-engine\", version = \"0.0.0-dev\" }|hm-dsl-engine = { path = \"crates/hm-dsl-engine\", version = \"$VERSION\" }|" Cargo.toml
61+
sed -i "s|hm-render = { path = \"crates/hm-render\", version = \"0.0.0-dev\" }|hm-render = { path = \"crates/hm-render\", version = \"$VERSION\" }|" Cargo.toml
62+
sed -i "s|hm-vm = { path = \"crates/hm-vm\", version = \"0.0.0-dev\" }|hm-vm = { path = \"crates/hm-vm\", version = \"$VERSION\" }|" Cargo.toml
5363
5464
cargo check --workspace --exclude hm-fixtures
5565
66+
- name: Publishability guard (dry-run package the whole graph)
67+
# Fail fast before any real `cargo publish` if the dependency graph
68+
# isn't publishable — e.g. a publishable crate depending on a
69+
# `publish = false` crate, or a missing version bump. `cargo package
70+
# --workspace` resolves sibling path deps locally (no index lookup,
71+
# unlike `cargo publish --dry-run`, which the not-yet-published deps
72+
# would fail), so it catches exactly the publish=false / unpublished-dep
73+
# class of regression. `--no-verify` skips the per-crate rebuild;
74+
# `cargo check --workspace` above already proved it compiles.
75+
run: cargo package --workspace --exclude hm-fixtures --allow-dirty --no-verify
76+
5677
- name: Publish hm-util
5778
run: |
5879
if curl -sf -A "harmont-release-ci (github-actions)" "https://crates.io/api/v1/crates/hm-util/$VERSION" > /dev/null 2>&1; then
@@ -75,6 +96,17 @@ jobs:
7596
- name: Wait for crates.io index
7697
run: sleep 30
7798

99+
- name: Publish hm-config
100+
run: |
101+
if curl -sf -A "harmont-release-ci (github-actions)" "https://crates.io/api/v1/crates/hm-config/$VERSION" > /dev/null 2>&1; then
102+
echo "hm-config@$VERSION already published, skipping"
103+
else
104+
cargo publish -p hm-config --token ${{ secrets.CRATES_IO_TOKEN }} --allow-dirty
105+
fi
106+
107+
- name: Wait for crates.io index
108+
run: sleep 30
109+
78110
- name: Publish hm-plugin-protocol
79111
run: |
80112
if curl -sf -A "harmont-release-ci (github-actions)" "https://crates.io/api/v1/crates/hm-plugin-protocol/$VERSION" > /dev/null 2>&1; then
@@ -86,6 +118,39 @@ jobs:
86118
- name: Wait for crates.io index
87119
run: sleep 30
88120

121+
- name: Publish hm-render
122+
run: |
123+
if curl -sf -A "harmont-release-ci (github-actions)" "https://crates.io/api/v1/crates/hm-render/$VERSION" > /dev/null 2>&1; then
124+
echo "hm-render@$VERSION already published, skipping"
125+
else
126+
cargo publish -p hm-render --token ${{ secrets.CRATES_IO_TOKEN }} --allow-dirty
127+
fi
128+
129+
- name: Wait for crates.io index
130+
run: sleep 30
131+
132+
- name: Publish hm-vm
133+
run: |
134+
if curl -sf -A "harmont-release-ci (github-actions)" "https://crates.io/api/v1/crates/hm-vm/$VERSION" > /dev/null 2>&1; then
135+
echo "hm-vm@$VERSION already published, skipping"
136+
else
137+
cargo publish -p hm-vm --token ${{ secrets.CRATES_IO_TOKEN }} --allow-dirty
138+
fi
139+
140+
- name: Wait for crates.io index
141+
run: sleep 30
142+
143+
- name: Publish hm-exec
144+
run: |
145+
if curl -sf -A "harmont-release-ci (github-actions)" "https://crates.io/api/v1/crates/hm-exec/$VERSION" > /dev/null 2>&1; then
146+
echo "hm-exec@$VERSION already published, skipping"
147+
else
148+
cargo publish -p hm-exec --token ${{ secrets.CRATES_IO_TOKEN }} --allow-dirty
149+
fi
150+
151+
- name: Wait for crates.io index
152+
run: sleep 30
153+
89154
- name: Publish hm-plugin-cloud
90155
run: |
91156
if curl -sf -A "harmont-release-ci (github-actions)" "https://crates.io/api/v1/crates/hm-plugin-cloud/$VERSION" > /dev/null 2>&1; then

RELEASING.md

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,30 @@ test changes to the export script.
3636

3737
Versioning is **driven by git tags on the public mirror**. The release
3838
workflow in `.github/workflows/release.yml` triggers on any tag matching
39-
`v*`, seds the version from the tag into all three crates' `Cargo.toml`
40-
files plus the `workspace.dependencies` pins, and publishes
41-
`hm-plugin-protocol`, `hm-plugin-sdk`, and `harmont-cli` to crates.io in
42-
that order. The bundled WASM plugins (`hm-plugin-docker`,
43-
`hm-plugin-output-human`, `hm-plugin-output-json`, `hm-plugin-cloud`)
44-
and `hm-fixtures` are not published — they ship embedded inside the
45-
`hm` binary.
39+
`v*`, seds the version from the tag into every publishable crate's
40+
`Cargo.toml` plus the `workspace.dependencies` pins, runs
41+
`cargo package --workspace` as a fail-fast guard (it resolves sibling
42+
path deps locally, so it catches the `publish = false` /
43+
unpublished-dep class of regression without needing the deps on the
44+
index yet — which `cargo publish --dry-run` would), then publishes the
45+
crates to crates.io in dependency (topological) order:
46+
47+
```
48+
hm-util → hm-pipeline-ir → hm-config → hm-plugin-protocol → hm-render
49+
→ hm-vm → hm-exec → hm-plugin-cloud → hm-dsl-engine → harmont-cli
50+
```
51+
52+
`harmont-cli` (the `hm` binary) depends on every other crate, so they
53+
must all reach crates.io first — including `hm-vm`, which carries the
54+
local Docker backend. `hm-fixtures` is test-only and not published.
4655

4756
### Prerequisites (one-time)
4857

4958
- `CRATES_IO_TOKEN` set as a repository secret on
5059
https://github.com/harmont-dev/harmont-cli/settings/secrets/actions.
51-
Generate it from https://crates.io/me with the `publish-update` scope
52-
on `hm-plugin-protocol`, `hm-plugin-sdk`, and `harmont-cli`.
53-
- The three crates exist on crates.io (first publish only requires
54-
`publish-new` scope). After the initial publish, narrow the token to
55-
`publish-update`.
60+
Generate it from https://crates.io/me. The first release needs the
61+
`publish-new` scope (the crates do not yet exist on crates.io); after
62+
the initial publish, narrow the token to `publish-update`.
5663

5764
### Per-release procedure
5865

@@ -72,9 +79,8 @@ and `hm-fixtures` are not published — they ship embedded inside the
7279
https://github.com/harmont-dev/harmont-cli/actions/workflows/release.yml.
7380
Each crate's publish step skips if the version is already on
7481
crates.io, so re-running after a partial success is safe.
75-
5. After the workflow completes, verify on crates.io:
76-
- https://crates.io/crates/hm-plugin-protocol/1.2.3
77-
- https://crates.io/crates/hm-plugin-sdk/1.2.3
82+
5. After the workflow completes, verify the leaf crate on crates.io
83+
(it depends on all the others, so its presence implies theirs):
7884
- https://crates.io/crates/harmont-cli/1.2.3
7985

8086
### Tagging in the monorepo (optional)

crates/hm-vm/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ name = "hm-vm"
33
version = "0.0.0-dev"
44
edition.workspace = true
55
license.workspace = true
6-
publish = false
6+
repository.workspace = true
7+
description = "Local VM/container backends (Docker) that run hm pipeline steps on the developer's machine."
78

89
[dependencies]
910
anyhow = { workspace = true }

0 commit comments

Comments
 (0)