cargo-dist (dist)

repository·main·Indexed 24 days ago

https://github.com/axodotdev/cargo-dist

A tool for automating the building, hosting, and announcing of Rust binary releases, including the creation of installers, tarballs, and CI/CD pipelines. The repository also includes axoproject, a utility for detecting and analyzing Cargo and npm workspace structures, and cargo-dist-schema for parsing dist-manifest.json files.

Tokens
49.5K
Snippets
127
Records
291
Agent score
84%

What's inside cargo-dist

  1. Overview of the dist release workflow

    main

    The dist tool automates the entire lifecycle of releasing and distributing software binaries. The workflow is divided into two primary phases:

    1. Building (Planning & Building):

      • Planning the release.
      • Selecting appropriate build flags for shippable binaries.
      • Building binaries, tarballs, and installers.
      • Generating machine-readable manifests.
    2. Distributing (Hosting, Publishing, & Announcing):

      • Hosting artifacts (e.g., uploading to GitHub Releases).
      • Publishing to package managers.
      • Announcing releases (e.g., creating GitHub Releases with changelogs).

    When fully configured (e.g., using GitHub CI), the process is triggered simply by pushing a git tag.

  2. What is axoproject?

    main
    axoproject is a utility tool designed to detect and analyze the structure of Cargo (Rust) or npm (JavaScript) workspaces and projects within a given directory. It provides a standardized way to make sense of project structures, allowing other tools like dist and oranda to share consistent detection logic.
  3. Overview of dist (formerly cargo-dist)

    main

    dist is a tool designed to automate the distribution of Rust binaries. It covers the entire release lifecycle by splitting functionality into two main parts:

    1. Building: Planning the release, picking optimal build flags, creating tarballs and installers, and generating machine-readable manifests.
    2. Distributing: Hosting artifacts, publishing to package managers, and announcing releases (e.g., creating GitHub Releases with changelogs).

    A key feature is its ability to generate its own CI scripts. For example, running dist init for GitHub CI will generate a release.yml file that automates the full pipeline from detecting a git tag to uploading artifacts and adding release notes.

  4. Overview of Supply-chain security features

    main

    The dist project provides several turnkey features to help comply with software supply-chain security policies and regulations. These features include:

    • Signing: Support for Windows Codesigning (and upcoming support for macOS, Linux, Sigstore, and Windows Trusted Signing).
    • Attestation: Support for GitHub Attestation.
    • SBOMs: Generation of CycloneDX-format Software Bill of Materials via cargo-cyclonedx.
    • Dependency Auditing: Embedding dependency trees into binaries via cargo-auditable.
    • Software Identification: Generating unique OmniBOR artifact IDs via omnibor-cli.
  5. How dist computes the Universe of Apps and Artifacts

    main

    An invocation of dist is driven by four major inputs that define the "Universe" (the total set of possible binaries, platforms, and installers) and the subset of that Universe to be processed:

    1. Project Structure: The Cargo Workspace structure (via cargo-metadata).
    2. Configuration: Settings in Cargo.toml under [workspace.metadata.dist] and [package.metadata.dist].
    3. Announcement Tag: The --tag flag (e.g., --tag=v1.0.0) which determines which Apps are part of the current release.
    4. Artifact Mode: The --artifacts flag (e.g., --artifacts=all) which determines which types of files are produced.

    Understanding this distinction is critical: the configuration defines the full Universe, while the --tag and --artifacts flags select the specific subset to build or manifest in a given run.

  6. Understand the types of artifacts generated by cargo-dist

    main

    In cargo-dist, Artifacts are the various files generated to help you distribute your binaries. There are four primary categories of artifacts:

    • Archives: The baseline artifacts, typically tarballs or zip files, that contain your compiled binaries.
    • Installers: Advanced artifacts designed to simplify the process of fetching and installing archives for end-users.
    • Checksums: Cryptographic hashes used to verify the integrity of other artifacts.
    • Symbols: Debug information, symbols, or sourcemaps associated with your binaries.
  7. Understand the configuration hierarchy in dist

    main

    Configuration for dist is read from multiple sources. When multiple sources provide the same configuration, the one with the highest preference wins. The order of preference (from lowest to highest) is:

    1. Language-specific project manifests: e.g., Cargo.toml (for Rust) or package.json (for JavaScript).
    2. Workspace dist config: dist-workspace.toml or dist.toml.
    3. Package dist config: dist.toml.

    Note for Rust users: During the current configuration migration, references to the [dist] section in dist-workspace.toml or dist.toml may also be configured via [workspace.metadata.dist] or [package.metadata.dist] in your Cargo.toml.

  8. Understand how Artifact URLs are derived

    main

    To enable installers that fetch binaries, cargo-dist must be able to derive download URLs from a base Artifact URL. This derivation is currently based on two components:

    1. Hosting Provider: The service where artifacts are uploaded (e.g., GitHub).
    2. Source Host: The URL of your git repository.

    Both must be well-defined for fetching installers to work. If you use the github CI backend, cargo-dist automatically computes the Artifact URL using the following pattern:

    {repo_url}/releases/download/{tag}

    Where repo_url is your source host repository URL and tag is the git tag of the release.

  9. Manage $PATH modifications

    main

    By default, dist installers ensure applications are available on the system PATH. On Linux/macOS, this involves editing shell dotfiles; on Windows, it involves editing the Environment.Path registry key.

    Controlling PATH behavior

    • Automatic Modification: The installer sources $PATH to check if the installation location is already present and modifies it if necessary.
    • Skip PATH modification: To prevent the installer from touching the user's PATH, set the INSTALLER_NO_MODIFY_PATH environment variable.
    • GitHub Actions: If the installer detects the $GITHUB_PATH environment variable, it will modify it to ensure applications are immediately available in the CI context.
    • Unmanaged Mode: Setting ${app name}_UNMANAGED_INSTALL to a path also disables PATH modifications.
  10. Configure the `[dist]` section

    main

    The [dist] section contains the primary configuration for how dist builds and publishes your applications. This section is a temporary placeholder and will be migrated to a new hierarchy in Config 1.0.

    Key settings within [dist] include:

    • allow-dirty: A list of generate tasks to ignore when checking if configuration is up to date.
    • cargo-dist-version: A mandatory Cargo-style SemVer version used for reproducibility.
    • dist: A boolean to force distribution of a package.
    • packages: An explicit list of packages to distribute.
    • targets: A list of target platforms to build for.
    • version: An optional value to override package versions.
  11. Defining Apps in a Cargo Workspace

    main

    In dist, an App is any Cargo package that contains binary targets (executables) or cdylibs (including WASM bundles).

    App Selection Rules

    • Multiple Binaries: If a package defines multiple binaries, they are treated as a single App. All binaries in that package will be included in the same zips/installers.
    • Excluding Packages: You can prevent a package from being treated as an App by:
      • Using Cargo's publish = false.
      • Using dist = false in the dist configuration (takes priority over publish).
    • Workspace-level Override: You can use the packages setting in [workspace.metadata.dist] to define a specific list of packages to be distributed, overriding individual package settings.
  12. Determine which packages are 'distable'

    main

    When releasing a workspace version, dist identifies "distable" packages. A package is considered distable by default unless it meets any of the following disqualification criteria:

    • It is "empty": By default, dist checks if the package defines any binaries. If you have enabled cdylibs/cstaticlibs, it will check for those as well.
    • It is explicitly disabled: The package has dist=false set in its configuration.
    • Cargo inheritance: For Cargo projects, if dist is not explicitly specified, it inherits the publish field from Cargo.toml (which defaults to true). You can use dist=true in a dist.toml to override a publish=false setting in Cargo.toml and make the package distable.