Skip to content

ci: release didc via cargo-dist; split candid_ui into its own workflow#745

Merged
lwshang merged 2 commits into
masterfrom
migrate-didc-to-cargo-dist
Jun 25, 2026
Merged

ci: release didc via cargo-dist; split candid_ui into its own workflow#745
lwshang merged 2 commits into
masterfrom
migrate-didc-to-cargo-dist

Conversation

@lwshang

@lwshang lwshang commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

What

Replaces the hand-written release.yml with a two-track release setup, mirroring the ic-wasm cargo-dist migration.

didc binaries → cargo-dist

  • Built and published by cargo-dist 0.31.0 (same version as ic-wasm) on didc-vX.Y.Z SemVer tags.
  • Targets: x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl (static), aarch64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin.
  • Config lives in dist-workspace.toml; the workflow didc-release.yml is generated via dist generate (don't hand-edit — regenerate after config changes).
  • Third-party actions are SHA-pinned via [dist.github-action-commits].

candid_ui.wasm → its own workflow

  • cargo-dist can't build a wasm canister, and candid_ui.wasm is pinned downstream by icp-cli at a date-tag URL. So it keeps the repo's date-based tag (YYYY-MM-DD) trigger, now in the new candid-ui.yml, producing the same asset name.
  • tag-namespace = "didc" scopes the cargo-dist workflow to didc-v* tags, so the two triggers never collide.

⚠️ Behavior changes for reviewers

  1. Release process changes. didc now releases on a SemVer tag (didc-v0.6.1) instead of the date tag; date tags now release only candid_ui.wasm. README updated.
  2. didc artifact naming changes. cargo-dist ships didc-<target-triple>.tar.xz archives + didc-installer.sh + sha256.sum instead of raw binaries named didc-linux64 / didc-macos / didc-arm32. Confirmed nothing in sdk/icp-cli hardcodes the old names and the README only links to the releases page generically.
  3. arm32 droppedarm-unknown-linux-gnueabihf is not a cargo-dist-supported target. Can be re-added later as a separate cross-build side-job if needed.

Validation

  • dist plan is clean: only didc 0.6.1, the 5 targets above.
  • cargo metadata parses; both workflows are valid YAML.
  • The old release.yml binary smoke-test is already covered by tools.yml's build-didc job.

Out of scope

npm packaging of didc (ic-wasm has release-npm.yml + npm/; candid has no equivalent today).

🤖 Generated with Claude Code

Replace the hand-written release.yml with a two-track release setup:

- didc binaries are now built and published by cargo-dist (dist 0.31.0,
  matching ic-wasm) on `didc-vX.Y.Z` SemVer tags. Targets: linux x86_64,
  linux x86_64-musl, linux arm64, macOS x86_64, macOS arm64. arm32 is
  dropped as it is not a cargo-dist-supported target. Config lives in
  dist-workspace.toml; the workflow (didc-release.yml) is generated via
  `dist generate`. Third-party actions are SHA-pinned.

- candid_ui.wasm keeps the repo's date-based tag (YYYY-MM-DD) trigger in
  the new candid-ui.yml, preserving the asset name that icp-cli pins.

Add the package metadata cargo-dist needs to tools/didc/Cargo.toml and a
[profile.dist] to the workspace, and document the new release process.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI 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.

Pull request overview

This PR modernizes the repository’s release automation by migrating didc binary releases to cargo-dist while splitting the candid_ui.wasm release into its own dedicated workflow, keeping the existing date-tag release behavior for the wasm artifact.

Changes:

  • Replace the monolithic tag-triggered release.yml with a cargo-dist generated didc-release.yml driven by didc-vX.Y.Z tags and dist-workspace.toml.
  • Add a standalone candid-ui.yml workflow that continues releasing candid_ui.wasm on date-based tags (YYYY-MM-DD).
  • Update crate metadata and documentation to reflect the new two-track release process.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/didc/Cargo.toml Adds missing crate metadata (description/license/repository) needed for distribution tooling.
README.md Documents the new two-track release process and tag conventions.
dist-workspace.toml Introduces cargo-dist configuration (targets, tag namespace, SHA-pinned actions).
Cargo.toml Adds a profile.dist used by cargo-dist builds.
.github/workflows/release.yml Removes the old combined release workflow.
.github/workflows/didc-release.yml Adds the cargo-dist generated didc release workflow.
.github/workflows/candid-ui.yml Adds a dedicated workflow to publish candid_ui.wasm on date tags.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/didc-release.yml
Comment thread .github/workflows/candid-ui.yml Outdated
Comment thread .github/workflows/didc-release.yml
@github-actions

Copy link
Copy Markdown
Name Max Mem (Kb) Encode Decode
blob 4_224 4_207_449 2_121_397
btreemap 75_456 529_878_266 10_166_634_693
double_option 128 1_322_452 ($\textcolor{red}{0.01\%}$) 27_197_905
large_variant 320 1_038_185 20_327_052
multi_arg 64 551_522 ($\textcolor{red}{0.02\%}$) 6_282_711
nns 192 1_992_456 5_507_178 ($\textcolor{green}{-0.02\%}$)
nns_list_neurons 1_152 6_591_925 ($\textcolor{green}{-0.03\%}$) 210_714_588 ($\textcolor{red}{0.00\%}$)
nns_list_proposal 1_216 6_907_923 ($\textcolor{red}{0.03\%}$) 55_061_919 ($\textcolor{green}{-0.03\%}$)
option_list 128 727_821 16_423_653
result_variant 192 1_378_318 16_140_430
subtype_decode 512 2_664_845 ($\textcolor{red}{0.02\%}$) 49_364_518 ($\textcolor{red}{0.00\%}$)
text 6_336 4_204_305 7_877_258
variant_list 128 722_331 15_625_423
vec_int16 12_480 8_404_571 249_585_709
vec_nat 11_008 66_046_846 276_028_297
vec_nat32 24_768 16_793_179 243_294_534
vec_nat64 49_344 33_570_379 251_683_396
vec_service 64 687_601 94_832_635
wide_record 1_152 3_267_512 ($\textcolor{red}{0.09\%}$) 44_558_104
  • Parser cost: 15_594_000 ($\textcolor{green}{-0.00\%}$)
  • Extra args: 2_861_924
Click to see raw report
---------------------------------------------------

Benchmark: blob
  total:
    instructions: 6.33 M (no change)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 4.21 M (no change)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 2.12 M (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: btreemap
  total:
    instructions: 10.70 B (no change)
    heap_increase: 1179 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 529.88 M (no change)
    heap_increase: 159 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 10.17 B (no change)
    heap_increase: 1020 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: double_option
  total:
    instructions: 28.52 M (0.00%) (change within noise threshold)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 1.32 M (0.01%) (change within noise threshold)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 27.20 M (no change)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: extra_args
  total:
    instructions: 2.86 M (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: large_variant
  total:
    instructions: 21.37 M (no change)
    heap_increase: 5 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 1.04 M (no change)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 20.33 M (no change)
    heap_increase: 3 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: multi_arg
  total:
    instructions: 6.84 M (0.00%) (change within noise threshold)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 551.52 K (0.02%) (change within noise threshold)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 6.28 M (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: nns
  total:
    instructions: 23.93 M (-0.01%) (change within noise threshold)
    heap_increase: 3 pages (no change)
    stable_memory_increase: 0 pages (no change)

  0. Parsing (scope):
    calls: 1 (no change)
    instructions: 15.59 M (-0.00%) (change within noise threshold)
    heap_increase: 3 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 1.99 M (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 5.51 M (-0.02%) (change within noise threshold)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: nns_list_neurons
  total:
    instructions: 217.31 M (-0.00%) (change within noise threshold)
    heap_increase: 18 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 6.59 M (-0.03%) (change within noise threshold)
    heap_increase: 18 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 210.71 M (0.00%) (change within noise threshold)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: nns_list_proposal
  total:
    instructions: 61.97 M (-0.02%) (change within noise threshold)
    heap_increase: 19 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 6.91 M (0.03%) (change within noise threshold)
    heap_increase: 5 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 55.06 M (-0.03%) (change within noise threshold)
    heap_increase: 14 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: option_list
  total:
    instructions: 17.15 M (no change)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 727.82 K (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 16.42 M (no change)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: result_variant
  total:
    instructions: 17.52 M (no change)
    heap_increase: 3 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 1.38 M (no change)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 16.14 M (no change)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: subtype_decode
  total:
    instructions: 52.03 M (0.00%) (change within noise threshold)
    heap_increase: 8 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 2.66 M (0.02%) (change within noise threshold)
    heap_increase: 8 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 49.36 M (0.00%) (change within noise threshold)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: text
  total:
    instructions: 12.08 M (no change)
    heap_increase: 99 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 4.20 M (no change)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 7.88 M (no change)
    heap_increase: 33 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: variant_list
  total:
    instructions: 16.35 M (no change)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 722.33 K (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 15.63 M (no change)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: vec_int16
  total:
    instructions: 257.99 M (no change)
    heap_increase: 195 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 8.40 M (no change)
    heap_increase: 130 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 249.59 M (no change)
    heap_increase: 65 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: vec_nat
  total:
    instructions: 342.08 M (no change)
    heap_increase: 172 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 66.05 M (no change)
    heap_increase: 33 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 276.03 M (no change)
    heap_increase: 139 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: vec_nat32
  total:
    instructions: 260.09 M (no change)
    heap_increase: 387 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 16.79 M (no change)
    heap_increase: 258 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 243.29 M (no change)
    heap_increase: 129 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: vec_nat64
  total:
    instructions: 285.26 M (no change)
    heap_increase: 771 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 33.57 M (no change)
    heap_increase: 514 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 251.68 M (no change)
    heap_increase: 257 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: vec_service
  total:
    instructions: 95.52 M (no change)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 687.60 K (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 94.83 M (no change)
    heap_increase: 1 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: wide_record
  total:
    instructions: 47.83 M (0.01%) (change within noise threshold)
    heap_increase: 18 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 3.27 M (0.09%) (change within noise threshold)
    heap_increase: 18 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 44.56 M (no change)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Summary:
  instructions:
    status:   No significant changes 👍
    counts:   [total 20 | regressed 0 | improved 0 | new 0 | unchanged 20]
    change:   [max +2.95K | p75 0 | median 0 | p25 0 | min -13.24K]
    change %: [max 0.01% | p75 0.00% | median 0.00% | p25 0.00% | min -0.02%]

  heap_increase:
    status:   No significant changes 👍
    counts:   [total 20 | regressed 0 | improved 0 | new 0 | unchanged 20]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  stable_memory_increase:
    status:   No significant changes 👍
    counts:   [total 20 | regressed 0 | improved 0 | new 0 | unchanged 20]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------
Successfully persisted results to canbench_results.yml

Addresses Copilot review: the lockfiles are committed, so honor them in
the release build (npm ci instead of npm install, cargo --locked).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lwshang lwshang marked this pull request as ready for review June 25, 2026 13:21
@lwshang lwshang requested a review from a team as a code owner June 25, 2026 13:21
@lwshang lwshang merged commit f3c020b into master Jun 25, 2026
16 checks passed
@lwshang lwshang deleted the migrate-didc-to-cargo-dist branch June 25, 2026 13:21
@zeropath-ai

zeropath-ai Bot commented Jun 25, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to c0ce7fa.

Security Overview
Detected Code Changes

| Change Type | Relevant files

... (code changes summary truncated to fit VCS comment limits.)

lwshang added a commit that referenced this pull request Jun 25, 2026
## Summary

`Nat`/`Int` encode and decode processed values one LEB128/SLEB128 group
at a time, shifting or OR-ing the whole bignum on every byte — O(n²) in
the encoded length once a value exceeds the `u64`/`i64` fast path. This
rebuilds the value in a single pass instead, making all four paths O(n).

- **decode**: collect the 7-bit groups and construct the bignum once via
`BigUint::from_radix_le(_, 128)` (radix 128 is a power of two, so this
bit-packs in O(n)); `Int` additionally reinterprets the two's-complement
sign.
- **encode**: emit groups via `BigUint::to_radix_le(128)` for `Nat`, and
repack the minimal two's-complement bytes into SLEB128 groups for `Int`.

The `u64`/`i64` fast paths are unchanged.

## Impact

All four paths were O(n²) before this PR. Measured with `canbench` on a
1 MiB encoded value, after the fix:

| path | instructions |
|------|-------------:|
| `Nat` encode | 66.5 M |
| `Nat` decode | 189 M |
| `Int` encode | 285 M |
| `Int` decode | 191 M |

For reference, before the fix the encode side alone measured **1.93 T**
(`Nat`) and **3.85 T** (`Int`) for the same input — a ~29,000× /
~13,500× reduction; decode had the same O(n²) shape.

## Tests

- New boundary, large-value, all-`0x7f`, large-negative, and a
randomized roundtrip (1000 values, both signs) covering the bignum
encode/decode paths.
- Existing exact-byte and random fast-path tests still pass (`cargo test
-p candid --all-features`).

## Bench

- Adds `nat_bignum` / `int_bignum` to the `canbench` suite
(`rust/bench`).

## Release

This PR carries the version bumps and CHANGELOG entries for two releases
to be cut **once it merges**:

- **`candid` / `candid_derive` → 0.10.31** (the perf change above), plus
the workspace and bench lockfile refreshes.
- **`didc` → 0.6.2** — picks up `candid_parser` 0.4.0.

### Release steps after merge

1. **candid 0.10.31** — run the existing `publish.yml` workflow
(`workflow_dispatch`) with the **candid** input checked. It publishes
`candid_derive` then `candid` to crates.io.
2. **didc 0.6.2** — push a `didc-v0.6.2` tag. This triggers the new
`didc-release.yml` (cargo-dist) workflow added in #745 —
building/publishing the `didc` binaries for the 5 supported targets and
creating the GitHub Release. This will be the **first real exercise of
that workflow** (so far it has only run in `pull_request` dry-run mode).
`dist plan` against this branch confirms it resolves `didc 0.6.2` with
the expected artifacts.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

3 participants