altenv: Powerful CLI Environment Variable Manager
Tags: go, cli, environmentvariable
Published: 2020-05-04 09:24:14

---
title: altenv: Powerful CLI Environment Variable Manager
published: true
description: 
tags: go,cli,"environment variable"
---

I just created a tool to manage environment variables in CLI: `altenv` 

[https://github.com/m-mizutani/altenv](https://github.com/m-mizutani/altenv)

# Motivation

In my business, I'm developing various tools and system. However we felt that the more projects we had to deal with, the more complicated it became to manage the setting values used for development and deployment. In particular, some tools are open to the public, so if you try to separate the implementation and settings properly (especially in the case of local development settings). So I just want a universal tool to manage these varialbles.

Simply put, `altenv` reads environment variables according to the contents of options and configuration files, and executes the specified commands with the environment variables. A simple example is following.

```sh
$ cat test.env
DBNAME=hoge
$ altenv -e test.env npm run server
# running npm server with environment variable DBNAME=hoge
```

# Use cases

Details of usage is wrote in the repository and let me roughly describe the usage for each use case. You can specify various options on the command line, but the configuration file `$ HOME / .altenv` is read by default. So I'd like to introduce the configuration there.

## Use different environment variable(s) by project directory.

In configuration file, `wordir.xxx` can be used to define environment variables for each working directory. (`xxx` is just a label)

```toml
[workdir.proj1]
dirpath = "/Users/mizutani/.ghq/github.com/xxx/project1"
define = ["DB_NAME=mydb1"]

[workdir.proj2]
dirpath = "/Users/mizutani/.ghq/github.com/yyy/project2"
define = ["DB_NAME=mydb2"]
```

When current working directory (CWD) is under `dirpath`, configurations 
 in the table is enabled. Specifically, it looks like following. (`-r dryrun` option only output a list of imported environment variables)

```shell
$ cd /Users/mizutani/.ghq/github.com/xxx/project1
$ altenv -r dryrun
DB_NAME=mydb1
$ cd ../../yyy/project2
$ altenv -r dryrun
DB_NAME=mydb2
```

## Referencing environment variables from an external repository or file sharing service

If you use only `define` configuration to define environment variables, all environment variables need to be written in `$HOME/.altenv`. It difficult to share common environment variables with your team member. So, by referencing an external file, you can share environment variables using git repository and file sharing services (e.g. Google File Stream, Dropbox, etc.). NOTE: the git repository assumes that you will pull the latest file yourself.

```toml
[workdir.proj1]
dirpath = "/Users/mizutani/.ghq/github.com/xxx/project1"
envfile = ["/Users/mizutani/Google Drive File Stream/Shared drives/MyTeam/config/project1.env"]

[workdir.proj2]
dirpath = "/Users/mizutani/.ghq/github.com/yyy/project2"
envfile = ["/Users/mizutani/.ghq/github.com/yyy/configs/project2.env"]
```

With this setting, files in the Shared Drive of Google Drive will be referenced when in the project1 directory, and files in the config management repository will be referenced when in the project2 directory.

## Switching Staging and Production

For example, when accessing both staging environment and production environment even in the same directory, it is necessary to switch the environment variable to be used. By preparing a table called `profile.xxx`, you can select the settings you want to use each time. The `xxx` in profile is the profile name as it is.

```toml
[profile.proj1-stg]
envfile = ["/path/to/proj1/stg.env"]

[profile.proj1-prd]
envfile = ["/path/to/proj1/prd.env"]
```

With this setting, the environment variables read by the `-p` option can be switched.

```sh
$ altenv -p proj1-stg ./deploy.sh
# The deploy.sh is executed after the environment variables for staging are read.
```

## Use secret value as environment variable (macOS only)

By saving environment variables in the macOS Keychain, you can manage secret values such as API keys more safely than saving plain text in a file. This feature is inspired by [envchain] (https://github.com/sorah/envchain).

With the option `-r update-keychain -w <namespace>`, the read environment variables are written to Keychain. `<namespace>` means just namespace and you can select namespace when both of reading and writing.

For example, if you have already saved the file in plain text, you can export it to Keychain as follows.

```sh
$ altenv -e credential.env -r update-keychain -w mycred
```

Alternatively, if it has already been read in the environment variable, you can write it to Keychain as follows. For example, let me save [Environment Variables for AWS CLI tool](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html) to Keychain.

```sh
$ env | grep -e "^AWS_ " | altenv -i env -r update-keychain -w aws-cli
```

You can also copy and paste them out one at a time.

```sh
$ altenv --prompt AWS_SECRET_ACCESS_KEY -r update-keychain -w aws-cli
Enter AWS_SECRET_ACCESS_KEY Value:
# No-echo because assuming secret value
```

`-k <namespace>` option imports saved environment variable in Keychain.

```sh
$ altenv -k aws-cli -r dryrun
AWS_SECRET_ACCESS_KEY=xxxxxxx
AWS_ACCESS_KEY_ID=xxxx
$ altenv -k aws-cli aws s3 ls
2019-11-21 19:02:20 mybucket-1
2019-11-21 19:02:22 mybucket-2
...
```