RustiQ uses dist to build and publish binary archives to GitHub Releases. crates.io publication runs in a separate workflow, so a registry outage does not block a binary release. Neither workflow creates a release from a GitHub Release event; both are triggered directly by a version tag, and crates.io publication can also be started manually for an existing tag.
The repository-root dist-workspace.toml pins dist 0.33.0, selects only the
rustiq-chem CLI package, and lists the six supported targets. Pull requests
run dist plan; this checks the release plan without building or publishing
artifacts. The generated workflow also runs on non-main pull requests because
dist 0.33.0 does not expose a pull-request base-branch filter. A pull request
cannot enter the publishing jobs.
All six target builds use native GitHub-hosted runners: Linux x64 on
ubuntu-22.04, Linux ARM64 on ubuntu-24.04-arm, macOS Intel on
macos-15-intel, Apple Silicon on macos-14, Windows x64 on windows-2025,
and Windows ARM64 on windows-11-arm. The configuration explicitly selects
the ARM runners and preserves the native Windows runners.
The
rustiq-chem-core library remains a build dependency and is not packaged as an
application. The generated workflow is .github/workflows/release.yml. It pins
actions/upload-artifact to an exact version. Because cargo-dist emits a major
version reference for that action, dist-workspace.toml sets
allow-dirty = ["ci"] so dist plan does not reject the exact pin as an
out-of-date generated workflow. Keep the pin synchronized with the intended
upload-artifact release when updating the workflow or cargo-dist.
Run Actions → Release artifact smoke test → Run workflow and select the
commit, branch, or tag to rehearse. The manually triggered workflow builds the
configured target archive with the pinned dist version on each target's native
GitHub-hosted runner. It extracts that archive, verifies its dist-generated
SHA-256 checksum, starts the packaged rustiq executable, checks --help,
and runs the checked-in H2/STO-3G regression with a copied local basis fixture
and JSON output. Per-target results appear in the job summary; archives, dist
manifests, and command logs are uploaded as workflow artifacts.
This checks archive integrity and basic executable operation for the six
configured targets. The H2 energy comparison reuses the regression reference
and is a packaging smoke test, not broad scientific validation, independent
platform validation, or proof of compatibility with every supported operating
system. The runs use GitHub-hosted runners, which are not pristine operating
system installations. A sha256.sum release manifest may only be created in
the tagged release's combined build; when unavailable, the rehearsal verifies
the per-archive checksum emitted by dist and fails if neither checksum is
available. A checksum made during a rehearsal does not independently validate
a published release.
The rehearsal has read-only repository permissions and only a
workflow_dispatch trigger. It does not run dist's host command, upload
release assets, create a GitHub Release, create tags, or publish crates. It
complements .github/workflows/release.yml, whose tagged-release path builds
and publishes the release assets; ordinary pull requests continue to use the
generated plan-only check.
Each executable archive includes rustiq (named rustiq.exe on Windows),
the README, LICENSE-MIT, LICENSE-APACHE, COPYING, DISTRIBUTION.md, and
THIRD-PARTY-NOTICES.txt. RustiQ-authored source retains MIT OR Apache-2.0;
Malachite and ansi_colours retain their LGPL terms. COPYING supplies the GPLv3
text referenced by LGPLv3, rather than imposing GPLv3 on all RustiQ code. Unix archives use .tar.gz
and Windows archives use .zip. Dist adds a .sha256 file for each archive
and a sha256.sum manifest. Installers are disabled. Archives do not include
calculation samples or basis data.
Each release also includes rustiq-corresponding-source.tar.gz, generated by
the dist extra-artifact command python3 tools/distribution.py source before
publication. This supplies the committed repository tree and all locked
dependency sources. The generated Cargo configuration allows registry-free
rebuilding. Dist's repository-only source tarball is disabled because it would
omit the dependency sources.
Dist treats this file as an extra artifact; it does not emit a separate
checksum for it in the release plan. Before publishing, verify that the source
archive is actually present in the release assets and corresponds to the tagged
commit. Its checksum can be calculated separately when verifying distribution
integrity.
See licenses and redistribution for rebuild instructions and
the requirements for package maintainers. The Nix package installs the same
notice documents into share/doc/rustiq; its metadata describes RustiQ's
MIT/Apache terms and the bundled LGPL/MPL components.
To verify the assets listed in sha256.sum on Linux, download it and all listed
assets into one directory, then run:
sha256sum --check sha256.sumOn macOS, use the built-in shasum command:
shasum -a 256 --check sha256.sumOn Windows PowerShell, use the explicit manifest comparison in the installation guide, replacing its example archive filename with the archive for your target.
The archive target identifies the operating system and CPU architecture; it does not guarantee compatibility with every Linux distribution or older system library. The Linux GNU archives require a compatible glibc runtime.
From the repository root, update the version in both package manifests and
update the CLI's rustiq-chem-core dependency requirement to that same
version:
Cargo.toml(rustiq-chem)crates/rustiq-core/Cargo.toml(rustiq-chem-core)Cargo.toml'srustiq-coredependency
After editing the manifests, regenerate Cargo.lock and the corresponding
notices. The distribution script needs Python with tarfile extraction filters:
Python 3.12 or later, or the backported filters in Python 3.10.12+/3.11.4+.
This is independent of the optional PySCF environment. Enter the Nix rust or
full shell for the pinned notice generator, or install cargo-about 0.9.2
outside Nix, then run:
cargo check --workspace
cargo install cargo-about --version 0.9.2 --locked
python3 tools/distribution.py notices
python3 tools/distribution.py check
cargo deny --locked --workspace --all-features check
git add Cargo.toml crates/rustiq-core/Cargo.toml Cargo.lock THIRD-PARTY-NOTICES.txt THIRD-PARTY-NOTICES.sha256
git commit -m "Prepare release X.Y.Z"The publishing workflow checks both package versions and the CLI dependency requirement against the tag using Cargo metadata. After committing the version change, build the workspace:
cargo check --workspace --lockedA binary release does not require registry publication readiness.
There is currently no local Nickel patch or corresponding crates.io
publication block. Before publishing crates, review the acknowledged
upstream advisories described in crates.io publication
and run cargo publish --dry-run --workspace --locked.
Regenerate and commit notices after changing dependencies, license configuration, the notice template or generator. Review supplemental upstream notices when updating crates whose published packages omit their licenses. CI checks their package inventory, input hashes and generated-file integrity. This catches stale or accidentally edited output; it does not independently verify every license clause or certify legal compliance. Review generated notices and supplemental attribution when changing dependencies. To rehearse the complete source delivery from a clean committed checkout:
python3 tools/distribution.py sourceThe command rejects source changes and untracked files, except the dist workflow's generated JSON manifests. It verifies offline Cargo resolution from the archive staging tree. Before a release, also extract the source artifact and run the reconstruction command documented in licensing.
Review the dist release plan and regenerate the workflow after changing the
dist configuration or updating dist. The allow-dirty = ["ci"] setting means
the generator does not check whether the checked-in release workflow matches
its current template. Preserve the exact upload-artifact pin if you regenerate
the workflow:
dist plan
dist generate --mode ci
dist generate --mode ci --checkThe Rust development shell includes the Nixpkgs cargo-dist package. The
generated workflow installs the exact dist version recorded in
dist-workspace.toml. Before regenerating locally, install that same version
if the Nixpkgs package differs:
cargo install cargo-dist --version 0.33.0 --lockedCommit and push the version changes, then create and push the matching tag:
git tag vX.Y.Z
git push origin HEAD
git push origin vX.Y.ZRelease tags must match vX.Y.Z or vX.Y.Z-prerelease, such as v1.2.3 or
v0.1.0-beta.1. For a prerelease, include the same suffix in both package
versions and the tag. Dist recognizes the suffix and marks the GitHub Release
as a prerelease. Do not reuse an existing tag or a crates.io package version.
The tag starts dist's generated workflow, which builds the configured
platform archives, creates their checksums, and publishes the assets to
GitHub Releases. A dist plan-jobs reusable workflow validates the tag format
and requires its commit to be an ancestor of main before artifact builds can
proceed. This accepts prerelease suffixes such as -alpha.1. A failed
validation blocks the build and therefore the publishing jobs.
Nickel 0.19's published dependency graph currently includes
imbl-sized-chunks 0.1.3, affected by the unfixed security advisory
RUSTSEC-2026-0292, and the unmaintained bitmaps 3.2.1
(RUSTSEC-2026-0247). RustiQ intentionally uses Nickel's published releases:
it does not fork Nickel or backport its transitive dependencies.
deny.toml records explicit exceptions for these advisories. Passing
cargo deny check does not indicate that the vulnerability is fixed.
Review these exceptions and upstream fixes before each release; see
dependency review.
The crates.io workflow is not blocked by these exceptions. A version tag can trigger publication of both crates while the upstream vulnerability remains present. Decide whether to publish that version with the documented risk or hold the tag until Nickel publishes a compatible fix.
.github/workflows/publish-crates.yml publishes both workspace crates when a
v* tag on main is pushed. Cargo publishes workspace members in dependency
order, so
rustiq-chem-core is available before rustiq-chem. Before publishing, the
workflow uses the crates.io API to exclude package versions that already
exist. If a run publishes the core crate and then fails while publishing the
CLI, rerunning the same tag skips the existing core version and retries the
CLI. For a retry, open Actions → Publish crates.io packages → Run
workflow, enter the existing v… tag, and start the workflow.
This workflow remains separate from the dist binary release workflow and can
also be run manually for an existing tag.
The workflow currently authenticates with the Actions secret
CARGO_REGISTRY_TOKEN. Create it from a crates.io API token with only package
publishing permissions, then add it under the repository's Actions secrets
before the first release. Keep the token out of repository files and do not
grant permissions to yank crates.
Crates.io Trusted Publishing uses GitHub OIDC and avoids a long-lived token,
but crates.io requires each crate to have an initial token-authenticated
publication before a Trusted Publisher can be configured. For RustiQ's first
publication, use CARGO_REGISTRY_TOKEN to publish both packages through the
tag workflow or its manual execution for an existing tag. After both crates
exist, configure a Trusted Publisher for each crate in crates.io to trust this
repository and the publishing workflow. A follow-up change can then replace
the token authentication with OIDC; the binary release workflow does not use
or depend on the crates.io token.
Cargo may time out while waiting for a published version to appear in the registry index even when the upload succeeded. Check the version on crates.io before retrying; the workflow's existence check will skip a version already published.