aqua - Declarative CLI Version Manager
Published: 2021-09-08 09:48:37

* https://github.com/suzuki-shunsuke/aqua
* https://github.com/suzuki-shunsuke/aqua-registry

In this post, I introduce [aqua](https://github.com/suzuki-shunsuke/aqua), which is a declarative CLI Version Manager. 
You can install CLI tools and manage their versions with YAML declaratively.
Mainly the following use cases are assumed.

* Install tools in CI/CD
* Install tools for repository's local development
* Install tools in your laptop

aqua supports the `Lazy Install` and Sharable Configuration mechanism named `Registry`.
Compared to other package manager like `Homebrew`, aqua supports switching tool versions per `aqua.yaml`.
Of course, you can use aqua with other package managers too.

You can install aqua with [aqua-installer](https://github.com/suzuki-shunsuke/aqua-installer).

```console
$ curl -sSfL \
  https://raw.githubusercontent.com/suzuki-shunsuke/aqua-installer/v0.2.0/aqua-installer |
  bash -s -- -i ~/bin/aqua -v v0.7.16
```

You can install aqua with Homebrew too.

```console
$ brew install suzuki-shunsuke/aqua/aqua
```

For example, let's install jq with aqua. Write the following `aqua.yaml`.

```yaml
registries:
- type: standard
  ref: v0.9.0

packages:
- name: stedolan/jq
  version: jq-1.5
```

And run `aqua i -l`.

```console
$ aqua i -l
```

The option `-l` is important. By this option, the symbolic links are created in `~/.aqua/bin` but the downloading tools is skipped.
This is the feature named `Lazy Install`.

Tools are installed in `~/.aqua`. Let's add `~/.aqua/bin` to the environment variable `PATH`.

```console
$ export PATH=$HOME/.aqua/bin:$PATH
```

Let's check if jq installed correctly.

```console
$ jq --version
INFO[0000] download and unarchive the package            package_name=jq package_version=jq-1.5 program=aqua registry=standard
jq-1.5
```

The output `INFO[0000] download and unarchive the package            package_name=jq package_version=jq-1.5 program=aqua registry=standard` indicates that jq is installed automatically before jq is executed.

aqua searches the configuration file `[.]aqua.y[a]ml` from the current directory to the root directory.

```console
$ cd foo
$ jq --version
jq-1.5

$ cd ../..
$ jq --version
FATA[0000] aqua failed                                   error="command is not found" exe_name=jq program=aqua
```

Let's update jq from 1.5 to 1.6.

```yaml
packages:
- name: stedolan/jq
  version: jq-1.6
```

And run `jq --version`.
Before jq is executed, jq is installed automatically.

```console
$ jq --version
INFO[0000] download and unarchive the package            package_name=jq package_version=jq-1.6 program=aqua registry=standard
jq-1.6
```

Let's downgrade jq from 1.6 to 1.5.

```yaml
packages:
- name: stedolan/jq
  version: jq-1.5
```

```console
$ jq --version
jq-1.5
```

The version of tool is changed seamlessly.
You don't have to execute `aqua`.

By adding `aqua.yaml` in each Git repositories, you can manage tools for each repositories.
Developers can use the same version, which prevents the problem due to the difference of tool versions.
aqua supports both MacOS and Linux, so even if you are working on MacOS and CI is run on Linux, you can manage tools with the same aqua.yaml.

aqua installs tools in `~/.aqua` and shares tools across multiple `aqua.yaml`, so the same version of the same tool is installed only at once.
It saves time and disk usage.

aqua supports the Global configuration `~/.aqua/global/[.]aqua.y[a]ml`.
This is useful to install tools in your laptop regardless the specific project.
Like `dotfiles`, it is good to manage the Global Configuration with Git and share it with your multiple laptops.

## Registry

aqua supports the Sharable Configuration mechanism named `Registry`.

You can install jq with the simple configuration.

```yaml
registries:
- type: standard
  ref: v0.9.0

packages:
- name: stedolan/jq
  version: jq-1.5
```

In the above configuration, the [Standard Registry](https://github.com/suzuki-shunsuke/aqua-registry) is being used.
The Standard Registry is the Registry which the aqua's maintainers maintain.

Please see the configuration.

https://github.com/suzuki-shunsuke/aqua-registry/blob/v0.9.0/registry.yaml#L1295-L1305

```yaml
- type: github_release
  repo_owner: stedolan
  repo_name: jq
  asset: 'jq-{{.OS}}'
  format: raw
  link: http://stedolan.github.io/jq/
  description: Command-line JSON processor
  replacements:
    darwin: osx-amd64
    linux: linux64
    windows: win64.exe
```

This is the configuration to download jq from GitHub Releases.
If you don't use the Registry, you have to write the configuration in `aqua.yaml`'s `inline_registry`.

```yaml
inline_registry:
  packages:
  - type: github_release
    repo_owner: stedolan
    repo_name: jq
    asset: 'jq-{{.OS}}'
    format: raw
    link: http://stedolan.github.io/jq/
    description: Command-line JSON processor
    replacements:
      darwin: osx-amd64
      linux: linux64
      windows: win64.exe

packages:
- name: stedolan/jq
  version: jq-1.5
```

It's not desirable to write such a configuration in every `aqua.yaml`.
Thanks to the Registry, you can install tools very easily without complicated configuration.

You can search the tool from the Registries with `aqua g` command.
Please add the Registries to your aqua.yaml's registries, and run `aqua g`.

```yaml
registries:
- type: standard
  ref: v0.9.0
```

```console
$ aqua g
```

`aqua g` launches the interactive UI and you can search the package by fuzzy search.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hasvwb3qbc590fpc6tjx.png)

If the tool you need isn't found, please create the issue or send the pull request to the [Standard Registry](https://github.com/suzuki-shunsuke/aqua-registry)!
By adding various packages to the Standard Registry, aqua becomes more useful and attractive.
Your contribution is needed!

It is also easy to create your own Registries.
Just create GitHub Repositories and add Registry Configuration like [the Standard Registry](https://github.com/suzuki-shunsuke/aqua-registry/blob/main/registry.yaml) and add it to `aqua.yaml`'s registries.
The private repository is also supported.

e.g.

```yaml
registries:
- name: suzuki-shunsuke/aqua-registry
  type: github_content
  repo_owner: suzuki-shunsuke
  repo_name: aqua-registry
  ref: v0.9.0
  path: registry.yaml
```

## Cotinuous update by Renovate

aqua manages package and registry versions,
so it is important to update them continuously.
aqua doesn't provide sub commands like `aqua update` or options like `aqua install --update`.
It is recommended to manage `aqua.yaml` with Git and update versions by [Renovate](https://docs.renovatebot.com/).

Using Renovate's [Regex Manager](https://docs.renovatebot.com/modules/manager/regex/), you can update versions.

The Renovate Preset Configuration https://github.com/suzuki-shunsuke/aqua-renovate-config is useful.
For the detail, please see the [README](https://github.com/suzuki-shunsuke/aqua-renovate-config).

## Summary

In this post, I introduced [aqua](https://github.com/suzuki-shunsuke/aqua), which is a declarative CLI Version Manager. 
You can install CLI tools and manage their versions with YAML declaratively.
aqua supports the `Lazy Install` and Sharable Configuration mechanism named `Registry`.

You can search tools from Registries by `aqua g` command.
If the tool you need isn't found, please create the issue or send the pull request to the [Standard Registry](https://github.com/suzuki-shunsuke/aqua-registry)!
By adding various packages to the Standard Registry, aqua becomes more useful and attractive.
Your contribution is needed!