Skip to main content
Version: 1.0

Alias tags

A package gets one release tag, written from its tagFormat. In a monorepo that tag usually carries a path prefix, so it says which package released and which version:

services/dispat/v1.4.2

That is the right name for a record. It is the wrong name for a pointer. Some things that consume a release do not want to name a version at all: they want to follow a line and get whatever the newest release on it is. A GitHub Action is the clearest case, because the only ref shape the Marketplace accepts looks like this:

uses: yohimik/dispat@v1

aliasTags gives a package extra names beside its real tag. Each release writes them all.

{
"packages": {
"dispat": {
"aliasTags": [
{ "format": "v{version}" },
{ "format": "v{major}", "moving": true, "channels": ["stable"] }
]
}
}
}

A release of dispat 1.4.2 now writes three refs at the same commit: services/dispat/v1.4.2, v1.4.2 and v1. The first two are written once and never touched again. v1 is re-pointed on every stable 1.x release, which is what makes @v1 mean "the newest 1.x".

Options

KeyDefaultMeaning
formatrequiredThe template. See Placeholders.
movingfalseRe-point the alias on every release it applies to, instead of writing it once.
channelsevery channelOnly write the alias for releases on these channels.
forcecommit.forceWhether this alias may overwrite an existing ref. A moving alias may not set this to false.

aliasTags can be set at the repository level, on a space, in a space folder's config file, and on a package, exactly like tagFormat. A list declared at a nearer level replaces the inherited one rather than adding to it, so a package opts out of its space's aliases with an empty list:

{ "packages": { "internal-tool": { "aliasTags": [] } } }

Placeholders

Everything tagFormat accepts, plus the three parts of the version on their own:

PlaceholderExample
{name}dispat
{version}1.4.2
{major}1
{minor}4
{patch}2
{channel}rc
{counter}1

{major}, {minor} and {patch} are available only here. A release tag has to be readable back into the version that produced it, and v1 names no release in particular, so a tagFormat using one is refused at load.

A format has to name some part of the version, or every release of every package would write the same ref. latest is not a valid alias for that reason.

Channels

channels is what keeps a moving alias honest. Without it, v1 follows whatever released last, release candidates included, so a project publishing 1.5.0-rc.1 would move v1 onto a prerelease and every consumer pinning @v1 would get it.

{ "format": "v{major}", "moving": true, "channels": ["stable"] }

Now v1 only ever follows stable releases. A prerelease still gets its own exact alias if one is configured, so uses: yohimik/dispat@v1.5.0-rc.1 works for anyone testing it, while v1 stays where it was.

channels takes the same values everywhere it appears in the configuration file. Naming nothing selects every release, stable selects the stable line, * selects any prerelease, and a bare name such as beta selects that one channel, matched without regard to case. The other two places it appears are which channels record and which releases a changelog line reaches.

Aliases are never read back

dispat finds a package's history by listing the tags its tagFormat matches. Aliases are written and never read, so they take no part in that.

This is load-bearing rather than incidental, and dispat enforces it. If an alias could be read back as a release tag, the next run would find it while looking for the package's baseline, and a moving alias is always the newest tag by creation date, so it would be found first:

  • a bare v1 does not parse as a version, and an unreadable newest tag makes the whole baseline unreadable, so the package would look as though it had never released;
  • a bare v1.4.2 does parse, and would quietly become some package's released version.

So the configuration is refused, at load, if any package's alias would match any package's tagFormat:

config: package "dispat": alias tag "v1.4.2" would be read back as a release tag of package "cli"
(tagFormat "v{version}"); an alias must never be readable as a release tag, or it becomes that package's history

The same check refuses two packages that would write one alias name, which is what a shared-version group would do if every member declared v{major}.

If your packages tag as {name}@{version} and you want bare aliases, give the aliases a prefix of their own (action-v{major}), or give the packages a path-prefixed tagFormat.

Failures

An alias is a convenience ref, not the record of a release. If one cannot be written, dispat warns (W232) and carries on: the release tag is already there, and the alias is re-pointed by hand or by the next release. That is different from the release tag itself, whose failure is a critical.

Pushing

Aliases are pushed with the release tags, so a ref nobody can fetch is never left behind. A moving alias needs to replace the copy the remote already has, which is what commit.force does and why it defaults to on.