Versio uses authorization options to connect to both Git remote
repositories, and the GitHub API. You may need to provide credentials to
Versio if you need to use these services with authorization. If you
don't want to bother with authorization (and are will to accept reduced
behavior), you can always force Versio to stick to the local repository
with -l local
; or to not use the GitHub API with -l remote
. See
VCS Levels for more information.
See the CI
sections in Use Cases
for info on how to set up authorization for common CI/CD systems.
Versio will attempt to use an underlying credentials helper agent in order to provide the correct SSH key to GitHub remote servers. Instructions to set this up are outside the scope of this document, but once you set this up, you should be able to see something like this (example output on macOS):
$ git config credential.helper
osxkeychain
On Windows, you may need to install the "Git Credential Manager", available here
You'll need authorization to push to and pull from the remote if you
expect Versio to keep your remote in sync. Make sure that commands like
e.g. git fetch
work from the command-line if Versio is having trouble.
If you don't have an agent set up, or if your agent is unable to
negotiate credentials, you can set the environment variables
GITHUB_USER
and GITHUB_TOKEN
to use more traditional user/password
authorization. GITHUB_TOKEN
can be the github password for this user,
or (suggested) an access token generated for this user and appropriately
scoped for Versio operations.
For GitHub remotes, Versio is capable of scanning through the PRs associated with commits: see PR Scanning. In order to do this, though, it may need an authorization token. You can generate a new personal access token for this purpose via the GitHub web UI in your user's Settings -> Developer settings.
Once you have the new token, you can set the environment variable
GITHUB_TOKEN
(this can be the same GITHUB_TOKEN
used for git
authorization as well), or you can add it to your user preferences in
~/.versio/prefs.toml
. Here's an example of such a file:
[auth]
github_token = "thisisa40charactertokeniamnotevenjokingg"
The environment variable has precedence over the preferences file, but the file approach may be more convenient for some users.
Versio, like many comprehensive command-line applications, has a number of subcommands that dictate what task is actually performed. Most of these subcommands have their own set of flags and options. There are also a couple of global flags and options that apply to all commands.
Run Versio like this:
$ versio <global options> [subcommand] <subcommand options>
vcs-level
(-l
),vcs-level-min
(-m
),vcs-level-max
(-x
): see the VCS Levels page for a description of these global options.no-current
(-c
): when the calculated vcs level is "local", commands that make no changes (check
,get
,show
,diff
,files
,changes
,plan
,info
) will not verify that the repo is current.
The following is a complete list of subcommands available in Versio,
along with their options and flags. You can always use versio help
or
versio help <subcommand>
to get the latest list.
-
check
: Run this command to ensure that your config file and repository is properly configured. -
show
: Show all projects in your monorepo, along with their current versions.--prev
(-p
): Show the previous versions instead, created by the last run ofversio run
. This will differ from the current version if you have added/removed projects, or manually made version number changes since the last time Versio ran.--wide
(-w
): Output a wide format that includes the project ID.
-
get
: Show one or more projects' version numbers.--id
(-i <ID>
): Show only the project that matches the given ID.--version-only
(-v
): Output only the version number(s)--name
(-n <name>
): Show only the project(s) whose name at least partially matches. Mutually exclusive withid
.--exact
(-e <name>
): Likename
, but matches exactly, Mutually exclusive withid
andname
.--prev
(-p
): Show the previous versions instead, created by the last run ofversio run
. This will differ from the current version if you have added/removed projects, or manually made version number changes since the last time Versio ran.--wide
(-w
): Output a wide format that includes the project ID.
If you only have a single project configured, you don't need to provide the
id
orname
option. -
set
: Change one project's version number.--id
(-i <ID>
): Change the project that matches the given ID.--name
(-n <name>
): Change the project that matches the given name.--exact
(-e <name>
): Likename
, but matches exactly, Mutually exclusive withid
andname
.--value
(-v <value>
): The new version value
If you only have a single project configured, you don't need to provide the
id
orname
option. Depending on the VCS level (default: "none"), the changed version may be also committed, pushed, and/or tagged. -
diff
: See differences between the current and previous versions. -
files
: See all files that have changed since the previous version. -
plan
: View the update plan.--id
(-i <ID>
): only show the plan of a single project with the given ID.--template
(-t <url>
): use a changelog template (such asbuiltin:json
), instead of a simple text output, when displaying the plan. Must be used with--id
if the repo contains more than one project. See Changelog Management for more.
-
info
: Outputs a JSON document with information about projects:--id
(-i <ID>
): include a single project with the given ID (you can provide this option more than once).--name
(-n <name>
): include a named project in the document (you can provide this option more than once).--exact
(-e <name>
): Likename
, but matches exactly.--label
(-l <label>
): include all projects with a label (you can provide this option more than once).--all
(-a
): include all projects.--show-root
(-R
): include the projects' root directories in the document.--show-name
(-N
): include the projects' names.--show-full-version
(-F
): include the projects' full version (including the tag prefix).--show-version
(-V
): include the projects' version numbers.--show-tag-prefix
(-T
): include the projects' tag prefixes.--show-id
(-I
): include the projects' ids.--show-all
(-A
): include all fields from the projects.
This command is useful to generate a machine-consumable document of one or more of the project configurations. It's especially helpful to create a matrix of projects that share a label. For example:
echo "::set-output name=matrix::{\"include\":$(versio -l none info -l cargo -R -N)}"
can be used to create a dynamic GitHub Actions matrix that contains all "cargo" projects, which you can then use to run cargo-specific jobs.
-
release
: Apply the update plan: update version numbers, create/update changelogs, and commit/tag/push all changes.--show-all
(-a
): Show the run results for all projects, even those that weren't updated.--pause
(-p <stage>
): Pause the release process before a stage of operation. Currently, only thecommit
stage is supported, which means that Versio will exit after it writes any local files, but before it commits, tags, or pushes to the remote repository. You can use this feature to perform additional changes before committing your version update. This will create a.versio-paused
file at the top level of your local repository that stores the planned resume action: while this file exists, only therelease --resume
orrelease --abort
commands can be used.--resume
will perform the planned commits, tags, pushes, etc. which were paused from a previousrelease --pause
. Any local file changes made after therelease --pause
will also be committed. You may supply a different VCS Level to this command than the originalrelease --pause
command.--abort
will simply delete the.versio-paused
file from a previousrelease --pause
, discarding any planned commits, tags, pushes. This command will not rollback any local changes made as part of the previousrelease --pause
; if needed, you should do that yourself with e.g.git checkout -- .
. You can't use both--resume
and--abort
.--lock-tags
(-l
): Normally, if a project contains changes that all map to a "none" size, then the project version will be unchanged, but Versio will still move the project tag to the latest commit. This flag removes that behavior, ensuring that tags are never moved--only new tags will be created for new versions. This is helpful if you're using deploy tools that expect a tag to always refer to exactly the same commit, but it may mean that a given version tag doesn't contain all the latest changes for that version.--dry-run
(-d
): Don't actually commit, push, tag, or change any files, but otherwise run as if you would.dry-run
is incompatible with--pause
,--resume
, and--abort
.--changelog-only
(-c
): Just like--dry-run
, but allows changelogs to be created/updated to disk, allowing workflows to create "preview" changelogs. See Changelog Management
-
init
:--max-depth
(-d <depth>
): The maximum directory depth that Versio will search for projects. Defaults to5
.
Run this command at the base directory of an uninitialized repository. It will search the repository for projects, and create a new
.versio.yaml
config based on what it finds. It will also append/.versio-paused
to your.gitignore
file, as a safety measure while using therelease --pause
command.init
will skip any hidden directories and files, as well as directories and files listed in.gitignore
files. -
schema
: Output a JSON schema document for the config file. This feature is in-progress, and may be altered/enhanced in future releases. Most JSON schema validators require JSON input, but you can use a yaml-to-json converter (ex: https://crates.io/crates/record-query) to convert your input. Also note that many JSON documents are valid YAML, if you want to keep your.versio.yaml
file in JSON format. -
template
: Output a changelog template.--template
(-t <url>
, required): pick which changelog template (such asbuiltin:json
) to output. See Changelog Management.
versio init
recognizes the following files as indicative of common
projects, and will create projects in the .versio.yaml
file as best it
can. The search technique is quite primitive, though. It may not find
the projects you are interested in, or it may set its configuration
incorrectly. You might want to double check the .versio.yaml
contents
when this command completes.
In some cases, versio init
will emit a warning that it can't find or
construct a legitimate project. You should definitely manually edit the
.versio.yaml
in that case--questionable fields will have the value
"EDIT_ME" when this happens.
Here's a listing of the files that versio init
searches for:
pom.xml
: Maven / Javapackage.json
: NPM/Node JavaScriptgo.mod
: GoCargo.toml
: Cargo / Rustsetup.py
: Pip / Python*.gemspec
: Gem / Ruby*.tf
: TerraformDockerfile
or.dockerfile
: Docker
A config file named .versio.yaml
must be located at the base directory
of your repository. If you use JSON Schema
to validate or help edit your YAML files, you can use the versio schema
command (see above) to generate a schema document for the config
file. Here's an example .versio.yaml
:
options:
prev_tag: "versio-prev"
projects:
- name: proj_1
id: 1
root: "proj_1"
tag_prefix: "proj1"
tag_prefix_separator: "/"
labels: npm
version:
file: "package.json"
json: "version"
also:
- file: "README.md"
pattern: 'This is proj_1 version (\d+\.\d+\.\d+)'
hooks:
post_write: ./bin/my_script.sh --auto
- name: proj_2
id: 2
root: "proj_2"
tag_prefix: ""
labels: go
depends:
1:
size: match
files:
- file: 'go.mod'
pattern: 'myregistry.io/proj_1 v(\d+\.\d+\.\d+)'
version:
tags:
default: "0.0.0"
subs: {}
sizes:
use_angular: true
fail: ["*"]
All paths listed in the configuation are relative paths, and follow the
"forward-slash" format ("path/to/file"
). The "root" property is
relative to the base of the repo; other paths are relative to that root
(except where listed otherwise)
-
options
These are general project options. Currently the only option is
prev_tag
, which specifies the tag used to locate the latest run ofversio release
. It has a default value of"versio-prev"
. -
projects
This is a list of projects: you can leave this out if your repo doesn't have any projects. Each project has the following properties:
name
: (required) The name of the project.id
: (required) The numeric ID of the project. Don't change a project's ID! By maintaining a consistent ID over the life of the project, you can track its continuity over multiple commits, even if the project name or location changes.root
: (optional, default"."
) The location, relative to the base of the repo, where the project is located. Thechangelog
,includes
,excludes
,also
, andversion: file
properties are all listed relative toroot
. Additionally, ifsubs
is given, the major subdirectories (v2
, etc) are searched for in root.includes
,excludes
: (optional, default includes:["**/*"]
, excludes:[]
) A list of file glob patterns which specify which files are included in/excluded from the project."*"
matches a single file, and"**"
matches zero or more nested directories. Only files covered byincludes
and not byexcludes
are included. These patterns are used to determine which commits are applicable to a project.depends
: (optional, default{}
) A list of projects on which the current project depends. Any version number increment in any dependency will result in an increment in the current project. See Version Chains for more info.changelog
: (optional) The file name where the changelog is located. If this property is not provided, no changelog will be created or updated. Alternately, you can provide a map in the following format, which additionally specifies which template to use when creating/updating the changelog. If no template is provided, then "builtin:html" is assumed. See the Changelog docs.changelog: file: "path/to/CHANGELOG.html" template: "file:path/to/CHANGELOG.html.tmpl"
version
: (required) The location of the project version. See "Version config" below.also
: (optional: default[]
) Additional locations where the project version should be written. See "Also" below.tag_prefix
: (optional) (required when using version tags) The prefix to use when reading/writing tags for this project. Not providing this will result in no tags being written. Using the empty string "" will use tags with no prefix. Each project's tag prefix, if any, must be unique.tag_prefix_separator
: (optional, defaults to "-") The separator used between the tag prefix and the version number when generating the full tag for this project. In the above example, the first project's version tags would look likeproj1/v1.2.3
.subs
: If provided, allows a project to be subdivided into "major" versions, each in its own subdirectory. See Major Subdirectories for more info on this feature.labels
: (optional) A string or sequence of strings, you can arbitrary labels to you projects, which is useful when using theinfo
command.hooks
: (optional) A set of hooks that run at certain points of the release process. Currently, only thepost_write
hook is supported: this hook runs after local file changes are made, but before any VCS commits/push/tagging is performed; it's useful to make additional file changes that need to be committed with the release.
-
commit
Identifying information included with all commits and annotated tags that Versio makes. If not present, Versio will use default values instead.
message
: (optional) The text message included with the commit. If not specified, this will be"build(deploy): Versio update versions"
.author
: (optional) The listed author of the commit. If not specified, this will be the name of this application,"Versio"
.email
: (optional) The email of the commitor. If not specified, this will be Versio's github location:"github.com/chaaz/versio"
.
-
sizes
This is a mapping of what conventional commit type applies to what size of increment. Each sub-property is one of the five increment sizes:
major
,minor
,patch
,none
, andfail
; and their values are the types that should trigger that size. Here's an example:use_angular: true major: [ breaking, incompatible ] minor: [ minor, docs ] patch: [ "*" ] none: [ ignore ] fail: [ "-" ]
If you include the
use_angular: true
key in your sizes, then the following angular conventions (from the angular and angular.js specifications) will be added to your sizes:major: [ "!" ]
,minor: [ feat ]
,patch: [ fix ]
, andnone: [ build, chore, ci, docs, perf, refactor, style, test ]
. You can override these by placing those specific types in different properties (asdocs
is done here)."!" is a special type which matches a commit whose type ends with "!" (as in
refactor!: remove NodeJS 6 support
orchore(toil)!: delete deprecated APIs
), or which contains a footer starting with "BREAKING CHANGE:" or "BREAKING-CHANGE:"—the actual type is ignored in this case. "-" is a special type which matches all non-conventional commits (commits for which a type can't be parsed). "*" is a special type which matches all commit types that are not matched elsewhere (including non-conventional commits if "-" is not listed). If you don't provide a "*" type in your sizes config, Versio will exit in error as soon as an unmatched commit message is encountered.The "none" size indicates that a matched commit shouldn't trigger a version increment. The "fail" size indicates that the entire run process should fail if a matching type is encountered.
The "version" property is used both to look up a project's old version, and to decide where to write the new version. Broadly speaking, there are three places a project's version can be found:
- a structured manifest file
- some VCS tagging scheme
- a pair of get/set shell commands.
If the version number is found in a manifest file, you can list that using something like:
version:
file: "Cargo.toml"
toml: "package.version"
The "package.version" above indicates the structured location within the
file where the version number is located. Here, it's listed as the usual
location within a Cargo.toml
file:
[package]
version = "0.1.0"
The structured location can be fairly complex: here you can specify that the version is located in a deeply nested location (which has the value "1.2.3":
{
"version": {
"thing": [
"2.4.6",
{ "version": "1.2.3" }
]
}
}
version:
file: "custom.json"
json: "version.thing.1.version"
Or, you can be extremely specific for weird edge cases:
{
"outer": {
"0": [
{ "not.the.version": "2.4.6" },
{ "the.version": "1.2.3" }
]
}
}
version:
file: "weird.json"
json: ["outer", "0", 1, "the.version"]
Versio understands toml
, json
, yaml
, and xml
formatting, and
pattern
to use the extended regex pattern for searching through a
file. Or, provide just the "file" property, and Versio will assume
version number makes up the file contents in their entirety (See "File
parsing" below).
If you are using VCS tagging to track your project version number (which is common in Go and Terraform projects), then you can use something like this instead:
tag_prefix: "projname"
version:
tags:
default: "0.0.0"
See Version Tags for more info on the benefits and pitfalls of this technique.
If you are using a custom get/set shell commands to get and set the version, you can configure them this way:
version:
get: "find-version"
set: "set-version"
When the current version number needs to be looked up, then Versio will
execute the get
command: its output to stdout will be assumed as the
version number. When Versio needs to set the current version, it will
run the set
command adding a single command-line argument, which is
the new version number itself.
When the release
command runs, it will detect and write the new
version in the location specified by the version
property. You may
want to write the new version in additional locations, for example,
documentation, examples, or other versioned files. You can use the
also
property for this purpose:
also:
- file: "examples/simple/main.tf"
pattern: 'source = .*/g2c-compute-gcp-(\d+\.\d+\.\d+)\.zip'
Files in the also
property are listed relative to the root
of the
project, and should only be used to update additional files in the same
project. If you want to update files in other projects in your repo, you
might want to use the depends
property in those other projects. The
Version Chains doc explains how that works.
When you specify a file as the version location, you also need to tell
Versio where in the file the version number is. You can use xml:
,
json:
, yaml:
, toml:
, or pattern:
types.
-
XML: If your version is located in an XML, use this style. The version will be found in the text area between the tags matched by the value. For example, if your version is stored in a
pom.xml
:<project xmlns="http://maven.apache.org/POM/4.0.0" ...> <version>0.1.0</version> </project>
You can configure your project like this:
version: file: "pom.xml" xml: "project.version"
Currently, the XML parser can't find a version number inside a CDATA block or in XML attributes.
-
TOML: Some projects keep the current version in a TOML file. For example, Rust projects have a
Cargo.toml
file:[package] name = "versio" version = "0.1.1"
version: file: "Cargo.toml" toml: "package.version"
TOML is a straightforward language, so most things there are supported. However, the TOML parser will probably have difficulty with triple-quoted string literals.
-
YAML: If your project has its version number saved in a YAML file such as
project.yaml
, you can access it like this:package: version: "0.1.1"
version: file: "project.yaml" yaml: "package.version"
YAML has a lot of different ways to represent data. If the version number is stored in a
|
or>
string literal, or if the value is accessed through an alias somehow, Versio might have a hard time reading or writing to it. -
JSON: Many project types use JSON to save project metadata. For example, NPM projects have a manifest file named "package.json"
{ "version": "0.1.1" }
version: file: "package.json" json: "version"
-
Regex: If your version number is listed in a file that doesn't match one of the common types, you can instead supply a regex pattern: The first capturing group of the first match found in the file will be used as the version. For example, if you have a file
version.md
that has the version number:What's interesting about this file, is that the version is _not_ 1.4.2. Instead, it's quite clear the version is 50.49.3.
version: file: "version.md" pattern: '[Tt]he version is (\d+\.\d+\.\d+)\.'
If no .versio.yaml
file is found, the default configuration is
assumed, which looks something like this:
options:
prev_tag: "versio-prev"
sizes:
use_angular: true
fail: ["*"]