Skip to main content

Usage

Available commands

Nyx provides the same features in all the available versions but the means to invoke each may change. This table summarizes the available commands and gives the available name for each when using different versions.

NameCommand Line CommandGradle Task Name
CleancleannyxClean
InferinfernyxInfer
MakemakenyxMake
MarkmarknyxMark
PublishpublishnyxPublish

Using the command line

Download the binary

You can find the latest binaries for any platform in the latest release assets.

Make sure you store the binary so that it's available from the PATH and it has execution permissions.

info

This guide assumes you rename the executable as nyx, regardless of the platform (or nyx.exe on Windows).

This is all you need to use Nyx on the command line.

Synopsis

Nyx comes with a whole lot of arguments that you can pass on the command line to let you control every single aspect of its behavior. You can see them all by running nyx --help, from which we have an abbreviated output here:

nyx --help

Nyx version: 3.1.3

Usage:
  nyx [arguments] [command]

Commands are:
  clean               reverts the repository to its initial state and removes files created by other commands, if any
  infer               inspects the commit history and repository status and computes the project version
  make                produces artifacts (i.e. changelog) as per the configuration
  mark                commits, tags and pushes, according to the configuration and the repository status
  publish             publish the new release, if any, to the configured services

Global arguments are:
  [...]

Changelog arguments are:
  [...]

Commit Message Conventions arguments are:
  [...]

Git arguments are:
  [...]

Git arguments are:
  [...]

Release Type arguments are:
  [...]

Services arguments are:
  [...]

As you can see you can give as much arguments as you like and one command at the end. Arguments start with a single (-) or double dash (--) and are detailed in the full output from nyx --help and in the configuration reference.

The command needs to appear at the end of the command line with no dash sign. If you don't specify any command Nyx will run the default one infer. For an introduction on what every command does see How Nyx Works.

Dynamic argument names

One thing that is important to note is that many arguments names are dynamic and this may be confusing at first as it's different than common arguments on other tools. For example, the --services-<NAME>-type=<TYPE> argument has a dynamic <NAME> in the attribute name.

This is to allow users to define the <TYPE> value for arbitrary services whose name is dynamically configured. When passing this as an actual argument on the command line also the <NAME> part needs to be replaced so for example --services-gh-type=GITHUB sets the type GITHUB for a service instance configured under the name gh.

This kind of notation implies that the internal configuration model always creates a service configuration named gh whenever an argument like this is provided. This is somewhat different from configuration files where you need to create a gh section and then define additional options underneath.

info

Since argument names are dynamically defined Nyx will not complain in case of unsupported arguments.

Run the command

All you have to do is run the command according to the synopsis above. Remember to run Nyx from the Git project directory or pass the --directory argument.

Also keep in mind that when no command is given on the command line infer is executed by default. This will generate and display the latest version for the project but will not change anything in the project directory. To run other commands you can specify them explicitly, as shown below.

Configuration

You have different means to configure the tool. Whichever combination you use, see the configuration reference for a detailed description of each option.

In some cases you might prefer using command line arguments while in others configuration files (or even a combination of) might be the way you pick. In order to support some edge cases, all options can also be passed as environment variables.

Different configuration methods can be combined together with well known priorities of each means over the others so you have complete freedom to create configuration baselines and override values as you need. This might be especially useful for large organizations. See the configuration methods for more on this.

Using command line arguments

With the above said, you can start easy with:

nyx --preset=simple infer

This runs the infer command and uses the simple preset.

Keep in mind that while presets are a handy way to avoid repeating streamlined configurations, you don't need to use them and you can define your own from scratch by whatever configuration means.

Using configuration files

If you rather prefer to configure Nyx by means of configuration files you can use one of the default configuration files that are looked up automatically or set the configurationFile global option to look for a file in a custom location.

Nonetheless, you can override configuration options from configuration files with command line arguments.

The Nyx State

You can enable writing the Nyx state file by using the --state-file argument. You can have it in JSON or YAML, depending on the extension you set. Example:

nyx --state-file=nyx-state.json infer

After this command runs you can read the nyx-state.json file to inspect its contents and use them for other purposes. Check out the State Reference to know more about the contents and how powerful this can be.

Exit codes

Nyx always returns 0 as the exit code unless some error occured, in which case 1 or other values other than 0 are returned.

Using the Docker image

Many teams prefer using Docker containers for their CI/CD and local development environments. If that's your case you can use the Docker container that comes out of the box with Nyx.

The Docker images are published onto the two main registries:

Nyx' Docker image has a small footprint (less than 10Mb) and uses Alpine Linux as the base image.

info

All the examples in this page assume you're using the latest image pulling it from Docker Hub. They also assume you're making an ephemeral use of the container (you run it and dispose it every time). In case you need advanced use cases other than these please refer to the official Docker Documentation.

Requisites

All you need is a recent version of Docker installed and running.

Pull the image

Let's start by pulling the image from the public registry. Open a shell and run:

$ docker pull mooltiverse/nyx:latest
latest: Pulling from mooltiverse/nyx
ab6db1bc80d0: Pull complete
[...]
Digest: sha256:976f4821d643e02fc55c884cd6c9af5e958011132145150b7dd97e01d71ba055
Status: Downloaded newer image for mooltiverse/latest
mooltiverse/latest

and make sure the new image is there:

$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
mooltiverse/nyx latest a14cbc284e81 2 days ago 7.35MB

Run the container

To run the container you simply run a command like:

$ docker run -it --rm -v /local/path/to/project:/project mooltiverse/nyx:latest

A few things to note here:

  1. there is no explicit command executed within the container because nyx infer is executed by default. This will generate and display the latest version for the project but will not change anything in the project directory. To run other commands you can specify them explicitly, as shown below
  2. a local folder (/local/path/to/project) is mounted from the host into the container at the default location /project. You need to change /local/path/to/project to whatever path is hosting your Git repository, or mount a Docker volume hosting the Git repository in case you already have one (in this case, pass your volume name to the command line like docker run -it --rm -v project-volume:/project mooltiverse/nyx:latest [...], where project-volume has to be changed to your volume name)
  3. Nyx is using the default configuration means (configuration files available in the project directory at standard locations)
info

When running on Linux or Mac hosts you may also want to map the host user ID to the container user in order to avoid issue with file permissions. You can do this by adding this option to the command line: -u $(id -u):$(id -g). See the Docker run reference for more.

Running specific commands

In order to run a specific command you need to pass it on the command line, like:

$ docker run -it --rm -v /local/path/to/project:/project mooltiverse/nyx:latest <COMMAND>

So if you need to run the publish command, run the container as:

$ docker run -it --rm -v /local/path/to/project:/project mooltiverse/nyx:latest publish

Mounting the project volume or folder

You can pass Nyx your project folder as a path on the host or as a Docker volume. What you need to do is:

  • replace /local/path/to/project with an actual host path when the project directory is shared from the Docker host to the container, or
  • replace /local/path/to/project with a Docker volume name when the project directory is already in a Docker volume

For more on volumes and mounts please see the official Docker documentation.

Passing the configuration to Nyx

Generally speaking, configuring Nyx within a container is just like using it from the command line. This means that if configuration files are available in the project directory at their default locations they will be loaded as usual and if additional options are passed on the command line they will be used.

The one caveat abous passing configuration as environment variables in a Docker container is about setting those variables by means of one or more -e flags.

Using the Gradle plugin

When using Gradle, the native Nyx plugin is the easiest and most effective way of using Nyx. The plugin can be used with the Groovy or the Kotlin syntax, although this documentation always refers to Groovy unless otherwise specified.

info

All the examples in this page assume you're using the plain gradle command. If you're using the (recommended) wrapper just change instances of the gradle command with ./gradlew.

info

Some extra information on the Gradle Plugin internals is available here.

Apply the plugin

You can apply the plugin as a project plugin or as a settings plugin. You're suggested to use the settings plugin to make sure you have properties are evaluated early in the build lifecycle as detailed in this post.

When using Groovy you can use the same plugin DSL in both cases:

plugins {
  id "com.mooltiverse.oss.nyx" version "3.1.3"
}

Add the above definition to the settings.gradle file to deploy the plugin as a settings plugin (suggested) or to the build.gradle file to deploy the plugin as a project plugin.

If you're using Kotlin you can use this example for your build.gradle.kts or settings.gradle.kts when applying the project plugin or settings plugin, respectively:

plugins {
  id("com.mooltiverse.oss.nyx") version "3.1.3"
}

Configure the plugin

You have different means to configure the plugin and in these sections we'll introduce you to all of them. Whichever combination of configuration means you use, see the configuration reference for a detailed description of each option.

warning

The version configuration option is not handled like other options because it would overlap Gradle's standard version project property. The plugin reads and writes the standard Gradle option to provide a consistent behavior and reduce impact on existing build scripts. See here for more.

You can also mix different configuration means according to the configuration evaluation order in order to use what better suits your needs. Mixed configurations are often used to reuse some parts or entire configurations across projects and organizations or to override some inherited values on a project basis.

Examples of different configuration files are available here.

Using the extension

The easier way to configure Nyx is via a Gradle extension.

When using Groovy the extension is a configuration block named nyx you add inside your settings.gradle or build.gradle script (depending on where and how you applied the plugin, as a settings plugin or project plugin, respectively), like this:

plugins {
  id "com.mooltiverse.oss.nyx" version "3.1.3"
}

nyx {
  // a few examples
  dryRun = false
  resume = false
  stateFile = '.nyx-state.yml'
  verbosity = "INFO"
}

The configuration block shown above is where you can place configuration options defined in the configuration reference using the Gradle syntax.

When using Kotlin you still have a configuration block very similar to the one above but with some differences.

Configuring the project plugin using Kotlin you add something like this to your build.gradle.kts:

plugins {
  id("com.mooltiverse.oss.nyx") version "3.1.3"
}

nyx {
  // a few examples
  dryRun.set(false)
  resume.set(false)
  stateFile.set(".nyx-state.yml")
  verbosity.set("DEBUG")
}

As you can see Kotlin uses a different way to set values. If, instead, you're configuring the settings plugin in Kotlin your settings.gradle.kts file looks like:

plugins {
  id("com.mooltiverse.oss.nyx") version "3.1.3"
}

configure<com.mooltiverse.oss.nyx.gradle.NyxExtension> {
  // a few examples
  dryRun.set(false)
  resume.set(false)
  stateFile.set(".nyx-state.yml")
  verbosity.set("DEBUG")
}

So, when using Kotlin, the difference between configuring the project plugin or settings plugin is in the way the configuration block starts.

Using configuration files

If you rather prefer to configure Nyx by means of configuration files you can use one of the default configuration files that are looked up automatically or set the configurationFile global option to look for a file in a custom location.

Multi-project builds

If you have a multi-project build and apply the plugin in the settings.gradle file you can only apply it to the root project as that's how Gradle restricts the settings.gradle. On the other hand, if you use the settings.gradle, the Nyx plugin should be applied to the root project only as it's supposed to be where the Git repository is located.

warning

Nyx makes no hard checks whether it's applied to the root project or a subproject so if you know what you're doing you can apply the plugin to one of the subprojects as well.

To use the project version from subprojects you should use the rootProject.version property instead of the simple version or project.version or you may get the undesired unspecified value in place of the expected version.

If using the project plugin, in order to be sure the version has been set before you use it, add a dependency from the task you read the rootProject.version to the nyxInfer task in the root project, like:

tasks.register('myTask')  {
dependsOn ':nyxInfer'
doLast {
println rootProject.version
}
}

or

tasks.myTask.dependsOn rootProject.tasks.nyxInfer

This dependency is not needed when using the settings plugin.

You may also propagate the root project version to all sub projects if that's what you need, and to do so you can add the following block in the root project build script:

subprojects {
version = rootProject.version
}

Core tasks

Once the plugin is applied the following tasks and dependencies are available. All tasks belong to the Release group.

nyxClean

Runs the clean command.

This task has no efferent dependecies but if the clean lifecycle task is defined (like when using the Base plugin) it is attached with a dependency on this task.

nyxInfer

Runs the infer command.

This task has no efferent dependecies while nyxMake depends on on this task.

When the plugin is applied as a settings plugin you don't need to run this task explicitly as it's implicitly executed in the initialization phase.

Otherwise, when the plugin is applied as a project plugin, since this is the task that actually makes available all the information required for a new release (including the Gradle's version property), you should make all tasks that need that information dependent on this, directly or indirectly.

For example:

tasks.myTask.dependsOn rootProject.tasks.nyxInfer

or

tasks.register('myTask')  {
dependsOn ':nyxInfer'
doLast {
...
}
}
info

See this post for more on the early inference of the version and other properties.

nyxMake

Runs the make command.

This task depends on the nyxInfer task while nyxMark depends on on this task. Moreover, if an assemble lifecycle tasks is defined (like when using the Base plugin) it is attached with a dependency on this task.

nyxMark

Runs the mark command.

This task depends on the nyxMake task while nyxPublish depends on on this task.

nyxPublish

Runs the publish command.

This task depends on the nyxMark task while the release task is attached to depend on this task.

Lifecycle tasks

The following additional lifecycle tasks are added for convenience.

release

The release lifecycle task is created if there is no task with the same name already defined. This task provides no actions by itself but is just meant to let you run gradle release to run the entire release process.

The newly created or existing release task is attached to depend on the nyxPublish task.

Accessing the Nyx State extra project property from build scripts

Another nifty feature that may save you a bunch of coding is accessing the Nyx State from within a Gradle script.

The entire State is bound to the project extra properties with the nyxState property name so, starting from that, you can read any property exported by Nyx.

info

The nyxState property is only available after at least one core task has executed. When using the settings plugin this is not an issue as the tasks run automatically in the early phases. Not all State properties are available at the same type (after the same task execution), please check out the reference for each property to know when it's available.

This way you can have all the Nyx properties handy without even storing the State file on disk. For example, to only run a task if the release scope contains significant changes you can check the project.nyxState.releaseScope.significantCommits list property while to reuse the same timestamp used by Nyx you can read the project.nyxState.significant.

Example:

task dumpSomeDiagnostics() {
dependsOn nyxInfer
doLast {
println project.nyxState.bump
println project.nyxState.directory.getAbsolutePath()
println project.nyxState.scheme.toString()
println Long.valueOf(project.nyxState.timestamp).toString()
println project.nyxState.version
}
}

In this example dumpSomeDiagnostics represents some arbitrary task that depends on nyxInfer just to make sure the nyxState is available and is used to print a few attributes from the state.

Using the GitHub Action

tip

Check out this section for a quick introduction on the GitHub Action.

To use the GitHub Ation just configure it as a job in your workflow, like:

jobs:
infer-version:
name: Infer the repository version with Nyx
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Nyx infer
id: nyx
uses: mooltiverse/nyx@main
- name: Print version # This step uses the version inferred by Nyx
run: echo the inferred version is ${{ steps.nyx.outputs.version }}

Nyx supports a variety of configuration means, including configuration files, command line arguments and environment variables. All configurable options are accessible via any of the supported configuration methods. The configuration reference gives you full details on each option.

Using the GitHub Action you can use:

info

When using the GitHub Action, action inputs replace command line options, which are not available with Actions. Action inputs are a subset of all the available command line arguments and this is due to Actions not supporting options with dynamic names. Nonetheless they give you a handy way to set the most common settings. For all those arguments not available as inputs you can still use configuration files or environment variables. Action inputs will be passed to Nyx as command line arguments under the hood so they have priority over all other configuration means.

See below for a full reference.

Inputs

NameNotes
commandSelects which Nyx command to run. Allowed values are: clean, infer (default), make, mark, publish. When selecting infer Nyx will only read the repository and give you back the inferred version. make will build the changelog, mark will apply tags, make commits and push changes to the remote repository. publish will publish the release to the configured services
bumpInstructs Nyx on which identifier to bump on the past version in order to build the new version. This option prevents Nyx to infer the identifier to bump from the commit history.
changelogPathThe absolute or relative path to a local file where the changelog is saved when generated. If a file already exists at the given location it is overwritten. Setting this value also enables the changelog creation, which is to say, when this option is not defined no changelog is generated. A common value used for this option is CHANGELOG.md
changelogTemplateThe absolute or relative path to a local file to use as a template instead of the Nyx built-in. The file must contain a valid Handlebars template (Mustache templates are also supported). Template functions can be used in custom templates
commitMessageConventionsEnabledThe comma separated list of commit message convention names that are enabled for the project. Here you can enable or disable the various conventions, either custom or default. The list of available conventions is defined by the configured preset or a configuration file
configurationFileThis option allows you to load a configuration file from a location other than default ones. This can be a relative (to the Action's working directory) path to a local file or an URL to load a remote file. This configuration file can override other options, as per the evaluation order, and can be authored as .yaml (or .yml) or .json (the format is inferred by the file extension or JSON is used by default) just like the default configuration files
directorySets the working directory for Nyx. The directory is where Nyx searches for the Git repository and is also used as the base path when relative paths to local files or directories. By default Nyx uses the Action's working directory for this. Paths defined here must be relative to the Action's working directory
dryRunWhen this flag is set to true no action altering the repository state, either local or remote, is taken. Instead the actions that would be taken if this flag was not set are printed to the log
initialVersionThe default version to use when no previous version can be inferred from the commit history (i.e. when the repository has no tagged releases yet)
presetThis option allows you to import one preset configuration into your configuration to save configuration time and effort
releaseLenientWhen this option is enabled (it is by default), Nyx will attempt to tolerate prefixes and other unnecessary characters (like leading zeroes) when reading Git tags from the commit history. When true, tags like vx.y.x, relx.y.x etc will be detected as release tags (for version x.y.x), regardless of the prefix Nyx uses to generate release names
releasePrefixIt’s a common practice to add a leading string to version numbers to give releases a name. Common prefixes are v or rel but you might use anything, or no prefix at all
releaseTypesEnabledThe comma separated list of release types that are enabled for the project. Here you can enable or disable the various release types, either custom or default. The list of available release types is defined by the configured preset or a configuration file
releaseTypesPublicationServicesThe comma separated list of service configuration names to be used to publish releases when the matched release type has the publish flag enabled. The list of available services is defined by the configured preset or a configuration file
releaseTypesRemoteRepositoriesThe comma separated list of remote repository names to be used to push changes to when the matched release type has the gitPush flag enabled. The list of available remote repositories is defined by the configured preset or a configuration file
resumeWhen this flag is set to true Nyx tries to load an existing state file and resume operations from where it left when the state file was saved
schemeSelects the version scheme to use. Defaults to SEMVER
sharedConfigurationFileThis option allows you to load a shared configuration file from a location other than default ones
stateFileEnables the creation of the state file where Nyx stores its findings and generated values
summaryFileEnables the creation of the summary file where Nyx saves a subset of relevant information from the internal state as name value pairs, easy to parse
verbosityControls the amount of output emitted by Nyx, where values are: FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
versionOverrides the version and prevents Nyx to infer. When overriding this value you take over the tool and go the manual versioning way so Nyx won’t try to read past versions from the commit history nor determine which identifiers to bump

Outputs

NameNotes
branchThis string contains the current Git branch name
bumpThis string contains the name of the identifier that has been bumped to create the new version. Version identifiers depend on the selected version scheme
coreVersionThis value is true when the version only uses core identifiers (i.e. is not a pre-release) according to the scheme
latestVersionThis value is true when the version is the latest in the repository, meaning that, according to the scheme, there are no other tags in the Git repository representing any version greater than version
newReleaseThis value is true when the newVersion is true and a new release with the current version has to be issued
newVersionThis value is true when the version is new and is basically a shorthand to testing if version is different than the previousVersion
schemeThe configured version scheme
timestampThe timestamp in the Unix format (seconds since Jan 01 1970. (UTC). Example: 1591802533
previousVersionThe version that was released before the one being created
primeVersionThe version that is used as the baseline when bumping version numbers when the release type uses collapsed versioning (the pre-release versioning)
versionThe version that was inferred, unless the version configuration option was passed to override inference. When the version is not overridden or inferred the initialVersion is used

All the above outputs are also contained in the state file (if enabled using the stateFile option) or the summary file (if enabled using the summaryFile option).

Limitations

This is a Docker Action so it's only available for Linux runners.

Versioning

Although you can use a specific version for this action you are recommended to always use the latest version from the main branch (uses: mooltiverse/nyx@main).

This action always uses the latest Nyx version.

Caveats

Git repository checkout action

Your pipelines on GitHub Actions probably start with the checkout action, which, by default, only checks out the latest commit as the fetch-depth parameter defaults to 1.

This prevents Nyx from inferring information from the commit history and you likely end up with the inferred version to always be the initial version (i.e. 0.1.0) as further illustrated here.

To work around this you just have to configure the checkout action to always fetch the entire commit history by setting the fetch-depth parameter to 0 as in this example:

- uses: actions/checkout@v4
with:
fetch-depth: 0

Combined release process

Just like for other means of using Nyx, in order to separate Nyx actions and run other jobs or steps in between, you can run this action multiple times passing different commands (see the command parameter). Just make sure you enable the state file (using the stateFile parameter) and the resume flag (using the resume parameter).

jobs:
job1:
name: My job
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run nyx Infer
uses: mooltiverse/nyx@main
with:
command: infer
resume: true
stateFile: .nyx-state.json
# Run other tasks here....
- name: Run nyx Publish
uses: mooltiverse/nyx@main
with:
command: publish
resume: true
stateFile: .nyx-state.json

In case you run Nyx in separate jobs (instead of just separate steps within the same job), you may also wish to bring the state file ahead along with the pipeline progress so you can use the cache action, like in this example:

jobs:
job1:
name: My job 1
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up the cache to store and retrieve the Nyx state
uses: actions/cache@v4
with:
path: |
.nyx-state.json
key: ${{ github.run_id }}-nyx-state
restore-keys: ${{ github.run_id }}-nyx-state
- name: Run nyx Infer
uses: mooltiverse/nyx@main
with:
command: infer
resume: true
stateFile: .nyx-state.json

job2:
name: My job 2
needs: job1
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up the cache to store and retrieve the Nyx state
uses: actions/cache@v4
with:
path: |
.nyx-state.json
key: ${{ github.run_id }}-nyx-state
restore-keys: ${{ github.run_id }}-nyx-state
- name: Run nyx Publish
uses: mooltiverse/nyx@main
with:
command: publish
resume: true
stateFile: .nyx-state.json

Using separate jobs may also come very useful when using matrix builds.