Skip to content

A tool for managing cargo workspaces and their crates, inspired by lerna

License

Notifications You must be signed in to change notification settings

miraclx/cargo-workspaces

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cargo-workspaces

Fork of pksunkara/cargo-workspaces, maintained by miraclx.

Differences from the upstream repo:

  • Allows definition of package versions in the workspace manifest to avoid prompting.
  • Properly supports workspace inheritance.
  • Introduces package groups which allows for versioning and publishing of only a subset of crates in a workspace.
  • Auto-injection of missing inter-dependency versions.
  • Works on non-git workspaces.
  • Properly discriminates between local and public crates when updating the manifest. (pksunkara/cargo-workspaces#94)
  • Allows for the exclusion of crates from being versioned and published.
  • When versioning and publishing, tags are only applied after crates have been successful published.
  • Reduces the likelihood of surprising git errors when validating, committing or tagging.

For an example what using this utility for versioning looks like, see these examples:


Inspired by Lerna.

A tool that optimizes the workflow around cargo workspaces with git and cargo by providing utilities to version, publish, execute commands and more.

I made this to work on clap and other projects that rely on workspaces. But this will also work on single crates because by default every individual crate is a workspace.

  1. Installation
  2. Usage
    1. Init
    2. Create
    3. List
    4. Changed
    5. Exec
    6. Version
      1. Fixed or Independent
      2. Exclusion
      3. Groups and Grouping
    7. Publish
    8. Rename
  3. Config
    1. Package Configuration
    2. Workspace Configuration
  4. Changelog

Installation

cargo install --git https://github.com/miraclx/cargo-workspaces cargo-workspaces

Usage

The installed tool can be called by cargo workspaces or cargo ws. Both of them point to the same.

You can use cargo ws help or cargo ws help <subcmd> anytime to understand allowed options.

The basic commands available for this tool are given below. Assuming you run them inside a cargo workspace.

Init

Initializes a new cargo workspace in the given directory. Creates Cargo.toml if it does not exist and fills the members with the all the crates that can be found in that directory.

USAGE:
    cargo workspaces init [PATH]

ARGS:
    <PATH>    Path to the workspace root [default: .]

OPTIONS:
    -h, --help    Print help information

Create

Interactively creates a new crate in the workspace. We recommend using this instead of cargo new. All the crates start with 0.0.0 version because the version is responsible for determining the version.

USAGE:
    cargo workspaces create [OPTIONS] <PATH>

ARGS:
    <PATH>    Path for the crate relative to the workspace manifest

OPTIONS:
        --bin                  Whether this is a binary crate
        --edition <EDITION>    The crate edition [possible values: 2015, 2018, 2021]
    -h, --help                 Print help information
        --lib                  Whether this is a library crate
        --name <NAME>          The name of the crate

List

Lists crates in the workspace.

USAGE:
    cargo workspaces list [OPTIONS]

OPTIONS:
    -a, --all                Show private crates that are normally hidden
        --groups <GROUPS>    Comma separated list of crate groups to deal with
    -h, --help               Print help information
        --json               Show information as a JSON array
    -l, --long               Show extended information

Several aliases are available.

  • cargo ws ls implies cargo ws list
  • cargo ws ll implies cargo ws list --long
  • cargo ws la implies cargo ws list --all

Changed

List crates that have changed since the last git tag. This is useful to see the list of crates that would be the subjects of the next version or publish command.

USAGE:
    cargo workspaces changed [OPTIONS]

OPTIONS:
    -a, --all                         Show private crates that are normally hidden
        --force <pattern>             Always include targeted crates matched by glob even when there are no changes
        --groups <GROUPS>             Comma separated list of crate groups to deal with
    -h, --help                        Print help information
        --ignore-changes <pattern>    Ignore changes in files matched by glob
        --include-merged-tags         Include tags from merged branches
        --json                        Show information as a JSON array
    -l, --long                        Show extended information
        --since <SINCE>               Use this git reference instead of the last tag

Exec

Executes an arbitrary command in each crate of the workspace.

USAGE:
    cargo workspaces exec [OPTIONS] <ARGS>...

ARGS:
    <ARGS>...

OPTIONS:
    -h, --help       Print help information
        --no-bail    Continue executing command despite non-zero exit in a given crate

For example, if you want to run ls -l in each crate, you can simply do cargo ws exec ls -l.

Version

Bump versions of the crates in the workspace. This command does the following:

  1. Identifies crates that have been updated since the previous tagged release
  2. Prompts for a new version according to the crate
  3. Modifies crate manifest to reflect new release
  4. Update intra-workspace dependency version constraints if needed
  5. Commits those changes
  6. Tags the commit
  7. Pushes to the git remote

You can influence the above steps with the flags and options for this command.

USAGE:
    cargo workspaces version [OPTIONS] [--] [ARGS]

OPTIONS:
    -h, --help    Print help information

VERSION ARGS:
    <BUMP>      Increment all versions by the given explicit semver keyword while skipping the prompts for them
                [possible values: major, minor, patch, premajor, preminor, prepatch, prerelease, custom]
    <CUSTOM>    Specify custom version value when 'bump' is set to 'custom'

VERSION OPTIONS:
    -a, --all                         Also do versioning for private crates (will not be published)
        --exact                       Specify inter dependency version numbers exactly with `=`
        --force <pattern>             Always include targeted crates matched by glob even when there are no changes
        --groups <GROUPS>             Comma separated list of crate groups to version
        --ignore-changes <pattern>    Ignore changes in files matched by glob
        --include-merged-tags         Include tags from merged branches
        --no-pager                    Do not use a pager for previewing package groups in interactive mode
        --pre-id <identifier>         Specify prerelease identifier
    -y, --yes                         Skip confirmation prompt

GIT OPTIONS:
        --allow-branch <pattern>            Specify which branches to allow from [default: master]
        --amend                             Amend the existing commit, instead of generating a new one
        --git-remote <remote>               Push git changes to the specified remote [default: origin]
        --individual-tag-msg <msg>          Customize tag msg for individual tags, defaults to individual tag name (can contain `%n` and `%v`)
        --individual-tag-prefix <prefix>    Customize prefix for individual tags (should contain `%n`) [default: %n@]
    -m, --message <MESSAGE>                 Use a custom commit message when creating the version commit [default: Release %v]
        --no-git                            Do not perform any git operations (implies --no-git-commit and --no-git-tag)
        --no-git-commit                     Do not commit version changes, omitting this will tag the current commit
        --no-git-push                       Do not push generated commit and tags to git remote
        --no-git-tag                        Do not tag generated commit (implies --no-individual-tags and --no-global-tag)
        --no-global-tag                     Do not create a global tag for a workspace
        --no-individual-tags                Do not tag individual versions for crates
        --tag-msg <msg>                     Customize tag msg, defaults to tag name (can contain `%v`)
        --tag-prefix <prefix>               Customize tag prefix for global tags (can be empty) [default: v]
        --tag-private                       Also tag individual versions of private packages

Fixed or Independent

By default, all the crates in the workspace will share a single version. But if you want the crate to have it's version be independent of the other crates, you can add the following to that crate:

[package.metadata.workspaces]
independent = true

If you want groups of crates to share a single version, independent of the rest of the workspace, see Groups and Grouping.

For more details, check Config section below.

Exclusion

To have crates opt-out from being versioned, you can add the following to the workspace:

[workspace.metadata.workspaces]
exclude = [
    "./crates/*",
    "path/to/some/specific/crate",
]

For more details, check Config section below.

Groups and Grouping

Use this to group certain crates together and have them share a single version that is independent from the rest of workspace.

This also lets you choose to version and publish only a specific subset of crates in the workspace1 instead of all at once. As well as visualizing changes by group or listing crates on a per-group basis.

1 If a crate from outside a group depends on crates within the group that is versioned, their versions are bumped too.

To create groups, add the following to the workspace:

[[workspace.metadata.workspaces.group]]
name = "foobar"
members = [
    "./foo",
    "./bar/*",
]

[[workspace.metadata.workspaces.group]]
name = "another-group"
members = [ "crates/*" ]

Note that group membership is exclusive, a crate isn't allowed to be a part of multiple groups. Also, the default group name is reserved for crates that don't belong to any group. And, the excluded group name is reserved for crates that are marked to be excluded from being versioned.

For more details, check Config section below.

Publish

Publish all the crates from the workspace in the correct order according to the dependencies. By default, this command runs version first. If you do not want that to happen, you can supply the --from-git option.

Note: dev-dependencies are not taken into account when building the dependency graph used to determine the proper publishing order. This is because dev-dependencies are ignored by cargo publish - as such, a dev-dependency on a local crate (with a path attribute), should not have a version field.

USAGE:
    cargo workspaces publish [OPTIONS] [--] [ARGS]

OPTIONS:
    -h, --help    Print help information

VERSION ARGS:
    <BUMP>      Increment all versions by the given explicit semver keyword while skipping the prompts for them
                [possible values: major, minor, patch, premajor, preminor, prepatch, prerelease, custom]
    <CUSTOM>    Specify custom version value when 'bump' is set to 'custom'

VERSION OPTIONS:
    -a, --all                         Also do versioning for private crates (will not be published)
        --exact                       Specify inter dependency version numbers exactly with `=`
        --force <pattern>             Always include targeted crates matched by glob even when there are no changes
        --groups <GROUPS>             Comma separated list of crate groups to version
        --ignore-changes <pattern>    Ignore changes in files matched by glob
        --include-merged-tags         Include tags from merged branches
        --no-pager                    Do not use a pager for previewing package groups in interactive mode
        --pre-id <identifier>         Specify prerelease identifier
    -y, --yes                         Skip confirmation prompt

GIT OPTIONS:
        --allow-branch <pattern>            Specify which branches to allow from [default: master]
        --amend                             Amend the existing commit, instead of generating a new one
        --git-remote <remote>               Push git changes to the specified remote [default: origin]
        --individual-tag-msg <msg>          Customize tag msg for individual tags, defaults to individual tag name (can contain `%n` and `%v`)
        --individual-tag-prefix <prefix>    Customize prefix for individual tags (should contain `%n`) [default: %n@]
    -m, --message <MESSAGE>                 Use a custom commit message when creating the version commit [default: Release %v]
        --no-git                            Do not perform any git operations (implies --no-git-commit and --no-git-tag)
        --no-git-commit                     Do not commit version changes, omitting this will tag the current commit
        --no-git-push                       Do not push generated commit and tags to git remote
        --no-git-tag                        Do not tag generated commit (implies --no-individual-tags and --no-global-tag)
        --no-global-tag                     Do not create a global tag for a workspace
        --no-individual-tags                Do not tag individual versions for crates
        --tag-msg <msg>                     Customize tag msg, defaults to tag name (can contain `%v`)
        --tag-prefix <prefix>               Customize tag prefix for global tags (can be empty) [default: v]
        --tag-private                       Also tag individual versions of private packages

PUBLISH OPTIONS:
        --allow-dirty            Allow dirty working directories to be published
        --from-git               Publish crates from the current commit without versioning
        --no-verify              Skip crate verification (not recommended)
        --registry <REGISTRY>    The Cargo registry to use for publishing
        --token <TOKEN>          The token to use for publishing

Rename

Rename crates in the project. You can run this command when you might want to publish the crates with a standard prefix.

USAGE:
    cargo workspaces rename [OPTIONS] <TO>

ARGS:
    <TO>    The value that should be used as new name (should contain `%n`)

OPTIONS:
    -a, --all                 Rename private crates too
    -f, --from <crate>        Rename only a specific crate
        --groups <GROUPS>     Comma separated list of crate groups to rename
    -h, --help                Print help information
        --ignore <pattern>    Ignore the crates matched by glob

Config

There are two kinds of configuration options.

  • Workspace: Options that are specified in the workspace with [workspace.metadata.workspaces]
  • Package: Options that are specified in the package with [package.metadata.workspaces]

Package Configuration

[package.metadata.workspaces]
independent = false  # This package should be versioned independently from the rest

Workspace Configuration

[workspace.metadata.workspaces]
version = "0.1.0"                       # Version for this workspace, to avoid prompting
allow_branch = "master"                 # Specify which branches to allow from [default: master]
no_individual_tags = false              # Do not tag individual versions for crates
exclude = [ "./foo", "./bar/*" ]        # List of crates to exclude from actions

[[workspace.metadata.workspaces.group]]
name = "utils"                          # Name for this group
version = "0.1.0"                       # Version for this group, to avoid prompting
members = [ "./utils/a", "./utils/b" ]  # Member crates belonging to this group

Contributors

Here is a list of Contributors

TODO

Changelog

Please see CHANGELOG.md.

License

MIT/X11

Bug Reports

Report here.

Credit

Originally built by Pavan Kumar Sunkara (pavan.sss1991@gmail.com, GitHub, Twitter)

Now maintained by Miraculous Owonubi (omiraculous@gmail.com, GitHub, Twitter)

About

A tool for managing cargo workspaces and their crates, inspired by lerna

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages