Skip to content

Latest commit

 

History

History
157 lines (124 loc) · 5.92 KB

File metadata and controls

157 lines (124 loc) · 5.92 KB

Packaging & Distribution

canton-devkit ships through complementary channels:

  1. DPM component (primary) — installed via dpm install package.
  2. Standalone Go binary (additional) — direct download / install.
  3. Package-manager convenience — a Homebrew tap wraps the same standalone binary for macOS and Linux workflows.

All release artifacts are produced by the same release workflow (.github/workflows/release.yml) from the same Go source. The DPM component and Homebrew formula both wrap the standalone binary for their respective ecosystems.

Standalone binary

Tagged releases (v*) publish per-platform standalone artifacts to GitHub Releases:

File Platform
canton-devkit_<version>_linux_amd64.tar.gz Linux x86_64
canton-devkit_<version>_darwin_arm64.tar.gz macOS Apple Silicon
canton-devkit_<version>_windows_amd64.zip Windows x86_64
SHA256SUMS GNU sha256sum --check-compatible manifest

Each tarball/zip contains the binary, LICENSE, and README.md. Verify before unpacking:

sha256sum --check SHA256SUMS
tar -xzf canton-devkit_v0.7.0_linux_amd64.tar.gz
./canton-devkit localnet --help

For macOS arm64 and Linux amd64, a scripted installer is also available:

curl -fsSL https://raw.githubusercontent.com/bitdynamics-ab/canton-devkit/main/install.sh | sh

Version-string asymmetry: the standalone archive filenames keep the v prefix (canton-devkit_v0.7.0_linux_amd64.tar.gz), matching the git tag, while the DPM/OCI tag strips it (ghcr.io/bitdynamics-ab/canton-devkit:0.7.0) because DPM requires a bare-semver tag. Same release, two conventions — chosen to match each ecosystem's norm.

DPM component

The DPM component is published to GitHub Container Registry on every tagged release at ghcr.io/bitdynamics-ab/canton-devkit:<version>. dpm install package reads the component references from the project's daml.yaml. Remove sdk-version and declare the SDK packages plus the DevKit component, then install:

# daml.yaml
#sdk-version: <your-sdk-version>
components:
  - canton-open-source:<your-sdk-version>
  - codegen:<your-sdk-version>
  - damlc:<your-sdk-version>
  - daml-new:<your-sdk-version>
  - daml-script:<your-sdk-version>
  - upgrade-check:<your-sdk-version>
  - scribe:<your-sdk-version>
  - daml-shell:<your-sdk-version>
  - oci://ghcr.io/bitdynamics-ab/canton-devkit:<version>
dpm install package
dpm localnet --help

Replace <your-sdk-version> with the Canton/Daml release you are targeting. <version> for the DevKit OCI tag follows semver (no v prefix); tag latest points at the most recently published final (non-pre-release) release.

Manifest

The component registers a single top-level command localnet that delegates the rest of the DevKit CLI surface to the binary's own argv parser. See packaging/component.yaml.tmpl.

DPM does NOT pass the registered command name into the binary's argv — only exec-args + user args reach it. exec-args: ["--via-dpm", "localnet"] is therefore required: the localnet arg makes the binary dispatch into its localnet subtree regardless of how DPM invoked the component, and the leading --via-dpm marker tells the binary it was launched by DPM. A contract test (TestRunIsArgvOnly) locks this invariant.

The manifest lives as a template with a @@BINARY_PATH@@ token: the release workflow substitutes bin/canton-devkit on Unix platforms and bin/canton-devkit.exe on Windows. DPM does NOT auto-append .exe on Windows — empirically verified against DPM 1.0.16, which fails manifest validation with stat <path>: no such file or directory when the path doesn't include the extension.

Why a single top-level command?

DPM components register top-level commands into a flat namespace shared with DPM builtins and every other component. DevKit deliberately registers only localnet to:

  • Avoid collisions with DPM builtins (install, publish, versions, bootstrap, …) or with future first-party components.
  • Keep the DPM surface minimal — dpm localnet up, dpm localnet dar upload, dpm localnet contracts ls, etc. nest naturally.

All DevKit subcommands live inside the binary's own Cobra tree, not in the DPM manifest.

Local validation

Before pushing a release-affecting change, validate the manifest end-to-end against a real DPM CLI:

# 1. Build a host-platform binary into the expected layout.
mkdir -p /tmp/cdk-component/bin
go build -o /tmp/cdk-component/bin/canton-devkit ./cmd/canton-devkit

# 2. Render the manifest from the template for this platform.
sed "s|@@BINARY_PATH@@|bin/canton-devkit|" \
    packaging/component.yaml.tmpl > /tmp/cdk-component/component.yaml
cp LICENSE /tmp/cdk-component/LICENSE

# 3. Run dpm publish --dry-run; it validates the manifest schema and
#    reports the OCI layout that would be pushed.
dpm publish component oci://localhost:5000/canton-devkit:0.0.1-dryrun \
    --dry-run \
    --platform darwin/arm64=/tmp/cdk-component

✅ Component manifest is valid confirms the manifest schema. The release workflow runs the same --dry-run validation on every run (tag pushes and manual dispatches); the real publish happens only on v* tags.

Supply-chain integrity

Today's integrity story is SHA-256 checksums (SHA256SUMS, verifiable with sha256sum --check) plus the immutability of the GHCR OCI digest. The CI pipeline also pins every GitHub Action and the DPM CLI tarball by SHA.

Known limitation: the release artifacts are not yet cryptographically signed. There are no cosign/Sigstore signatures on SHA256SUMS or on the OCI artifact, so consumers can verify integrity (the bytes match the checksum) but not provenance (the bytes were produced by the project's release pipeline). Keyless cosign signing plus a published verification step is a planned hardening item.