#container #docker #cli

app avatar-cli

Magic wrapper to run containerized CLI tools

5 releases

0.18.1 Oct 16, 2020
0.17.2 Sep 4, 2020
0.13.0 Jul 27, 2020

#338 in Emulators

46 downloads per month

GPL-3.0 license

97KB
2.5K SLoC

Avatar CLI

Pipeline Status Latest Version Crates Recent Downloads GL Stars GH Stars License

Table of Contents

  1. Introduction
  2. Why
  3. How to install Avatar-CLI
  4. How to use Avatar-CLI
  5. Using Avatar-CLI in CI/CD pipelines
  6. Using Avatar-CLI inside scripts
  7. Using Avatar-CLI with Jetbrains IDEs
  8. Troubleshooting
  9. How to contribute
  10. Community

Introduction

Avatar-CLI is a command line tool that allows you to run thousands of cli programs for your dev projects without having to install them in your system.

Avatar-CLI can ease the development forkflow in many ways:

  • Making possible version-pinning for any kind of tool used in any kind of project. No need for complex setups or ultra-specific tools like nvm, nodeenv, pyenv, rbenv, goenv, asdf-vm, ... I guess you already have seen the pattern.
  • Making possible for new contributors to be productive from the very first minute, reducing the bootstrap/setup time to almost zero. Only git and docker are required.

Why?

Why Avatar-CLI exists and what problems it tries to solve?

  • Avatar-CLI was created to shorten setup time of development environments to near-zero.
  • Avatar-CLI lets each project define its development environment as code and share it through source control as a configuration file. See the Avatarfile example.

Problems solved by Avatar-CLI and surrounding practices:

  • Works on my machine - With Avatar-CLI, each developer (and/or CI agent) gets a consistent and reproducible environment built with a combination of docker images.
  • Avatar-CLI helps to fight configuration drift. Tools and configurations in the CI/CD environments and developers' environments tend to accumulate differences and mismatches over time. Avatar-CLI allows using exactly the same tools, having a single source of truth for their configuration.

How to install Avatar-CLI

First, install docker, if you haven't already.

Downloading pre-compiled binaries

You can get our pre-compiled binaries in the Releases section. For now we only can provide Linux binaries, but in the future we'll also provide binaries for Macos.

Via Cargo

If you want to use Avatar-CLi in Macos, or you don't mind waiting a little bit more for its compilation, you can use cargo¹ to install it:

cargo install avatar-cli

1: If you don't have cargo in your system, you can obtain it via rustup.

How to use Avatar-CLI

In the command line:

# 1. Enter into your project directory
cd /your/project/path

# 2. Initialize Avatar-CLI for this project, this will create a new config file.
#    You only have to do this one single time per project.
avatar init

# 3. Edit the generated configuration file, without modifying its
#    `internalProjectId` property. You can see an example in the next code
#    block of this README.md file.

# 4. Now you can enter into an Avatar-CLI subshell and use all the configured
#    tools. If, for example, you configured a specific version of NodeJS, then
#    it will be available inside that subshell.
avatar shell

# Now you can use the software you specified in the configuration, even if it
# was not installed in your system.

Configuration example:

---
# This is of no use... for now, but it must be there
avatarVersion: '0.17.0'

# Keep the value generated by `avatar init`, don't share it across projects.
# This value is used (among other things) to keep track of managed volumes and
# containers
projectInternalId: v2ZmtbkGuVdvGwVE

# The field shellConfig is optional, it allows you to define some settings for
# the Avatar-CLI subshell (started via `avatar shell`).
shellConfig:
  # You can define environment variables for the subshell
  env:
    SOME_ENV_VAR: 42
  # In the case of the $PATH environment variable, Avatar-CLI forbids declaring
  # it through the `env` field, but you can extend it adding multiple paths to
  # the `extraPaths` field. This can be useful if you want to access tools
  # provided by some package manager, like `npm` or `composer`, as if they were
  # installed globally.
  extraPaths:
    - ./node_modules/.bin

# In this section we declare the OCI images that we'll use in our project
images:
  # Image name
  node:
    tags:
      14-buster:
        # The runConfig block allows us to tweak our containers, to improve
        # their integration with our development environment.
        runConfig:
          # You can specify hardcoded environment variables for your containers,
          # in this example we use this to configure NPM's cache
          env:
            npm_config_cache: /caches/.npm

          # You can pass host environment variables to your containers
          envFromHost:
            - NPM_TOKEN

          # You can specify which container paths have to be mounted as volumes,
          # this is specially useful for package managers' caches
          volumes:
            /caches/.npm: {} # In most cases, we won't need to configure volumes
            /another/example:
              # Volume names are usually autogenerated, use this configuration
              # option only in case you want to share volumes accross projects
              name: exotic_volume

              # By default, the scope of a volume is "Project", allowed values
              # are "Project", "OCIImage" and "Binary".
              # This setting defines how volumes are shared between containers,
              # and has no effect if a custom volume name has been set.
              scope: Project

          # In most cases, bindings won't be necessary, and it's advisable to
          # avoid them as they difficult to share development environments with
          # other people. But, if you really need to map a container path to
          # your host filesystem, they will allow you to do so.
          bindings:
            /container/path: /host/path

      # For each image, we can declare which binaries we want to expose to our
      # project.
      binaries:
        node:
          path: node # The path can also be an absolute path

          # Although we don't do it in this example, each binary can have its
          # own `runConfig` block, and its values will override the ones defined
          # at the image tag level

        # Usually we can skip configuring the binary, we just have to list it
        npm: {}
        npx: {}
        yarn: {}

  # Image name
  rust:
    tags:
      1.45-stretch:
        binaries:
          cargo:
            path: cargo

Using Avatar-CLI in CI/CD pipelines

If you want to use Avatar-CLI in your own CI/CD pipelines, you can rely on the generated OCI images. We provide the Avatar-CLI images through three different registries:

  • Gitlab CI Registry: registry.gitlab.com/avatar-cli/avatar-cli:[ major[.minor[.patch]] | latest ]
  • Github Registry: docker.pkg.github.com/avatar-cli/avatar-cli/avatar-cli:[ major[.minor[.patch]] | latest ]
  • Docker Hub: avatarcli/avatar-cli:[ major[.minor[.patch]] | latest ]

Using Avatar-CLI inside scripts

Given that creating subshells inside scripts may be too cumbersome, you can also "source" the output of the avatar export-env command.

In Bash scripts, you could do something like this:

#!/bin/bash

source <(avatar export-env)

If you want full compatibility with POSIX shell, then you have to first create a file and then source it:

#!/bin/sh

avatar export-env > /your/temporary/file
. /your/temporary/file

Using Avatar-CLI with Jetbrains IDEs

When using your preferred IDE, sometimes you have to specify the path of certain interpreters like Python or PHP.

For that, Avatar-CLI generates wrapper scripts in the directory .avatar-cli/volatile/wrappers of your project, and you can tell your IDE to find the interpreters there.

As a side note, notice that there is a similar directory (.avatar-cli/volatile/bin), this is where the symbolic links used by avatar shell are, and they won't work with your IDE.

Troubleshooting

Interactive Git Hooks using tools managed by Avatar-CLI

Git hooks are non-interactive by default, if you want to transform them into interactive programs, the program must connect its standard input to a pseud-tty device (usually /dev/tty) by itself.

If such git hooks use tools managed by Avatar, you must ensure that the TTY attachment is performed before any managed container is spawned, because once the container has been already connected and started, there's no sensible way to attach a terminal to it for Avatar-CLI.

One example for the mentioned problem is the combination of tools such as NodeJS, Husky and Commitizen. Husky will start a shell script for each git hook, and pass the control of execution to npm after some checks.

In the specific case of Avatar-CLI, we solved this problem by creating a patch for Husky (PR #747), and forking the project while the Husky project mantainers decide whether to accept this PR or not.

Customized $PATH environment variable

In case you have a customized $PATH environment variable via configuration scripts like ~/.bashrc, you should wrap that redefinition with a conditional statement to avoid breaking how Avatar-CLI works.

For example, something like this:

export PATH="/custom/extra/bin/path:${PATH}";

Should be converted into this:

if [ -z "${AVATAR_CLI_SESSION_TOKEN}" ]; then
  export PATH="/custom/extra/bin/path:${PATH}";
fi

Don't worry, the paths you declared are still available, but Avatar-CLI must be sure that its own managed paths are the first ones to be evaluated.

How to contribute

Read the contributing guidelines.

Community

License

Avatar-CLI is licensed under the GPL 3.0 license.

Dependencies

~13–24MB
~469K SLoC