github.com/goliatone/go-envset@v0.7.0/README.md (about)

     1  # envset
     2  
     3  `envset` run commands in an environment defined using a [ini][ini] configuration file.
     4  
     5  ---
     6  
     7  <!-- vscode-markdown-toc -->
     8  * [Environment level configuration](#environment-level-configuration)
     9  * [Similar Tools](#similar-tools)
    10  * [Examples](#examples)
    11  	* [Executing A Command](#executing-a-command)
    12  		* [Restart Command](#restart-command)
    13  		* [Variable Substitution](#variable-substitution)
    14  		* [Inherit Environment](#inherit-environment)
    15  		* [Overwriting Variables At Runtime](#overwriting-variables-at-runtime)
    16  		* [Load Env File To Current Shell Session](#load-env-file-to-current-shell-session)
    17  		* [Required Environment Variables](#required-environment-variables)
    18  	* [Generating An Example Template](#generating-an-example-template)
    19  	* [Support For .env Files](#support-for-envfiles)
    20  	* [Metadata](#metadata)
    21  	* [Metadata Compare](#metadata-compara)
    22  		* [Ignore Variables](#ignore-variables)
    23  * [Installation](#installation)
    24  	* [macOS](#macos)
    25  	* [Ubuntu/Debian x86_64 - amd64](#ubuntu-debianx86-64-amd64)
    26  	* [CentOS/Redhat x86_64 - amd64](#centos-redhat-x86-64-amd64)
    27  	* [Manual Install x86_64 - amd64](#manual-install-x86-64-amd64)
    28  * [Documentation](#documentation)
    29  	* [Commands](#commands)
    30  	* [Variable Expansion](#variable-expansion)
    31  	* [Commands](#commands-1)
    32  * [.envset File](#envset-file)
    33  * [.envsetrc](#envsetrc)
    34  	* [Configuration](#configuration)
    35  	* [Configuration Syntax](#configuration-syntax)
    36  	* [Ignored And Required Sections](#ignored-and-required-sections)
    37  * [License](#license)
    38  
    39  <!-- vscode-markdown-toc-config
    40  	numbering=false
    41  	autoSave=true
    42  	/vscode-markdown-toc-config -->
    43  <!-- /vscode-markdown-toc -->
    44  
    45  
    46  ---
    47  
    48  ## <a name='environment-level-configuration'></a>Environment level configuration
    49  
    50  Application configuration is (usually) specific to an environment and will change between different build environments- e.g. app secrets for a staging environment are different than your production secrets.
    51  
    52  The [12 factor app][12factor] guidelines suggest you store your application's configuration in the environment.
    53  
    54  Environment variables enable us to manage application configuration outside of our application code.
    55  
    56  Application configuration usually are small and sensitive data such as API keys or tokens, database credentials, etc. However not all environment configuration have to be secrets, there might be build distribution specific values such as the application's base URL to build OAuth callbacks, a dependent service endpoint or anything that changes between development and production environments.
    57  
    58  `envset` helps you manage environment variables for multiple build environments.
    59  
    60  The following command will run a Node.js application with a `development` environment:
    61  
    62  ```console
    63  $ envset development -- node server.js
    64  ```
    65  
    66  `envset` will load the variables defined in the `[development]` section of a local `.envset` file and execute the command after the `--`.
    67  
    68  See the [examples](#examples) section for more details.
    69  
    70  ## <a name='similar-tools'></a>Similar Tools
    71  
    72  Inspired by [daemontools][dtools]' tool [envdir][envdir] and tools such as [dotenv](https://github.com/bkeepers/dotenv).
    73  
    74  * Distributed as a single binary
    75  * No dependencies in your codebase
    76      * e.g. `dotenv-rails` and `dotenv`<sup>[1](#node-dotenv)</sup> for Node.js require you to use a library
    77  * Support multiple environments in a single file
    78  * Generates an example file with your current env vars to keep documentation updated.
    79  * Interpolation of variable using POSIX variable expansion.
    80  * Command expansion
    81  * Define required variables and exit with error if not set
    82  * By default the shell environment is not loaded in the context
    83  
    84  Instead of having an `.env` file per environment you can have one single `.envset` file with one section per environment.
    85  
    86  <a name="node-dotenv">1</a>: You an actually require the library outside of your project with the `node -r` flag.
    87  
    88  ## <a name='examples'></a>Examples
    89  
    90  ### <a name='executing-a-command'></a>Executing A Command
    91  
    92  An **.envset** file could look like this:
    93  
    94  ```ini
    95  [development]
    96  APP_SECRET_TOKEN=4c038a0b-4ed9-44e6-8682-9c82d5b831fd
    97  APP_REMOTE_SERVICE_KEY=07ed716a-078a-4327-8847-b86394f14575
    98  
    99  [production]
   100  APP_SECRET_TOKEN=796bca0f-2692-495b-a994-e8ce82cad55f
   101  APP_REMOTE_SERVICE_KEY=5655969e-af9f-4ac5-b186-184f43468443
   102  ```
   103  
   104  To use it, simply prefix the call to your program with `envset` and the name of the environment section. The node `app.js` will be running with the environment variables specified in the **development** section of the **.envset** file.
   105  
   106  ```console
   107  $ envset development -- node app.js
   108  ```
   109  
   110  #### <a name='restart-command'></a>Restart Command
   111  
   112  `envset` will optionally restart your command if it exits with an error code.
   113  There are three flags you can use to manage the restart behavior:
   114  * `--restart`: Restart command on exit error, default to `true`.
   115  * `--max-restarts [int]`: Max times to restart command, defaults to `3`.
   116  * `--forever`: If present restart the command for as long as `envset` is running.
   117  
   118  All these can be configured using an `.envsetrc` [file](#envsetrc).
   119  
   120  This will restart the node app for a maximum of `--max-restarts`.
   121  
   122  ```console
   123  $ envset development --restart --max-restarts 10 -- node app.js
   124  ```
   125  
   126  #### <a name='variable-substitution'></a>Variable Substitution
   127  
   128  You can execute commands that use environment variables in the command arguments.
   129  
   130  Is important to note that you need to scape the variable so that it is not replaced in the shell as you call `envset`. You can do so by using single quotes `'` or the scape char `\$`.
   131  
   132  ```console
   133  $ envset development -- say '${APP_ENV}'
   134  $ envset development -- say \${APP_ENV}
   135  ```
   136  
   137  #### <a name='inherit-environment'></a>Inherit Environment
   138  
   139  Sometimes the command you want to run will assume that has access to predefined environment variables:
   140  
   141  ```console
   142  $ envset development -- spd-say '${APP_ENV}'
   143  Failed to connect to Speech Dispatcher:
   144  Error: Can't connect to unix socket ~/.cache/speech-dispatcher/speechd.sock: No such file or directory. Autospawn: Autospawn failed. Speech Dispatcher refused to start with error code, stating this as a reason:
   145  exit status 1
   146  ```
   147  
   148  By default the process in which `envset` runs `spd-say` in an isolated mode has no access to your shell.
   149  
   150  You can control environment inheritance using two flags:
   151  
   152  - `--isolated`: Inherit all parent environment variables
   153  - `--inherit`: Inherit specific parent environment variables
   154  
   155  If you need the executed command to inherit the host's environment wholesale use the `--isolated=false` flag.
   156  
   157  ```console
   158  $ envset development --isolated=false -- spd-say '${APP_ENV}'
   159  ```
   160  
   161  Some commands might rely on a known environment variable set on your shell, for instance if you want to `go run`:
   162  
   163  ```console
   164  $ envset development -- go run cmd/app/server.go
   165  missing $GOPATH
   166  ```
   167  
   168  You will get an error saying that `$GOPATH` is not available. The `--inherit` flag lets you specify a list of environment variable keys that will be inherited from the parent environment:
   169  
   170  ```console
   171  $ envset development -I=GOPATH -I=HOME -- go run cmd/app/server.go
   172  ```
   173  
   174  #### <a name='overwriting-variables-at-runtime'></a>Overwriting Variables At Runtime
   175  
   176  You can overwrite environment variables without editing your `.envset` file.
   177  
   178  ```console
   179  APP_NAME="New Name" envset development --isolated=false -- spd-say '${APP_NAME}'
   180  ```
   181  
   182  #### <a name='load-env-file-to-current-shell-session'></a>Load Env File To Current Shell Session
   183  
   184  If you want to make the variables defined in a env file to your running shell session use something like the following snippet.
   185  
   186  
   187  ```sh
   188  $ eval $(envset development)
   189  ```
   190  
   191  #### <a name='required-environment-variables'></a>Required Environment Variables
   192  
   193  You can specify a list of required environment variables for your command using the `--required` flag or its `-R` alias.
   194  
   195  Given the following env file:
   196  
   197  ```ini
   198  [development]
   199  APP_SECRET_TOKEN={{APP_SECRET_TOKEN}}
   200  APP_REMOTE_SERVICE_KEY={{APP_REMOTE_SERVICE_KEY}}
   201  ```
   202  
   203  If you run the following command:
   204  
   205  ```console
   206  $ envset development --required=BOOM -R BOOM2 -- node index.js
   207  ```
   208  
   209  `envset` will exit with an error and a message with the missing variables:
   210  
   211  ```console
   212  missing required keys: BOOM,BOOM2
   213  ```
   214  
   215  ### <a name='generating-an-example-template'></a>Generating An Example Template
   216  
   217  If we run the `envset template` command with the previous **.envset** file we generate a **envset.example** file:
   218  
   219  ```ini
   220  [development]
   221  APP_SECRET_TOKEN={{APP_SECRET_TOKEN}}
   222  APP_REMOTE_SERVICE_KEY={{APP_REMOTE_SERVICE_KEY}}
   223  
   224  [production]
   225  APP_SECRET_TOKEN={{APP_SECRET_TOKEN}}
   226  APP_REMOTE_SERVICE_KEY={{APP_REMOTE_SERVICE_KEY}}
   227  ```
   228  
   229  
   230  ### <a name='support-for-envfiles'></a>Support For .env Files
   231  
   232  You can load other environment files like `.env` files:
   233  
   234  ```console
   235  $ envset --env-file=.env -- node index.js
   236  ```
   237  
   238  ### <a name='metadata'></a>Metadata
   239  
   240  The `metadata` command will generate a JSON file capturing the values of the provided env file.
   241  
   242  ### <a name='metadata-compara'></a>Metadata Compare
   243  
   244  Note that `envset metadata compare` will output to **stderr** in the case that both files do not match.
   245  
   246  ```console
   247  $ envset metadata compare --section=development .meta/data.json .meta/prod.data.json
   248  ```
   249  
   250  You can omit the path to the local source metadata file and only pass the remote file you want to compare against, it will use the configured path:
   251  
   252  ```
   253  $ envset metadata compare --section=development .meta/prod.data.json
   254  ```
   255  
   256  Pretty output
   257  
   258  ```console
   259  •  source: .meta/data.json
   260     STATUS       ENV KEY         HASH
   261  👻 Missing      MY_APP_NAME     6d22b97ab7dd...
   262  
   263  
   264  • target: .meta/env.staging.json
   265  👍 target has no extra environment variables
   266  
   267  •  different values
   268     STATUS       ENV KEY         HASH
   269  ❓ Different    APP_ENV         2e9975854897...
   270  ❓ Different    NEW_THING       8896f09440c1...
   271  
   272  
   273  👻 Missing in source (1) | 🌱 Missing in target (1)
   274  
   275  ❓ Different values (2)  | 🤷 Ignored Keys (0)
   276  ```
   277  
   278  To have JSON output you can pass the `--json` flag:
   279  
   280  ```console
   281  $ envset metadata compare --json -s development .meta/data.json .meta/prod.json
   282  {
   283    "name": "development",
   284    "values": [
   285      {
   286        "key": "MY_APP_SECRET",
   287        "hash": "aca50d5cf2f285a5a5c5469c8fe9df2540b9bea6905a23461b",
   288        "comment": "different hash value"
   289      },
   290      {
   291        "key": "MY_APP_NAME",
   292        "hash": "6d22b97ab7dd929f1b30099dcacd3a8f883373cefbe4a59a05",
   293        "comment": "missing in source"
   294      }
   295    ]
   296  }
   297  ```
   298  
   299  #### <a name='ignore-variables'></a>Ignore Variables
   300  
   301  When comparing metadata files you can optionally ignore some variables that you know will be different or will be missing. You can do pass `--ignore` or `-I` flag with the variable name:
   302  
   303  ```console
   304  $ envset metadata compare --section=development -I IGNORED_VAR .meta/prod.data.json
   305  ```
   306  
   307  ## <a name='installation'></a>Installation
   308  
   309  ### <a name='macos'></a>macOS
   310  <!--
   311  TODO: List how to install in all different platforms
   312  -->
   313  
   314  Add tap to brew:
   315  
   316  ```console
   317  $ brew tap goliatone/homebrew-tap
   318  ```
   319  
   320  Install `envset`:
   321  
   322  ```console
   323  $ brew install envset
   324  ```
   325  
   326  
   327  ### <a name='ubuntu-debianx86-64-amd64'></a>Ubuntu/Debian x86_64 - amd64
   328  
   329  ```console
   330  $ export tag=<version>
   331  $ cd /tmp
   332  $ wget https://github.com/goliatone/go-envset/releases/download/v${tag}/envset_${tag}_linux_x86_64.deb
   333  $ sudo dpkg -i envset_${tag}_linux_x86_64.deb
   334  ```
   335  
   336  ### <a name='centos-redhat-x86-64-amd64'></a>CentOS/Redhat x86_64 - amd64
   337  
   338  ```console
   339  $ yum localinstall https://github.com/goliatone/go-envset/releases/download/v<version>/envset_<version>_linux_x86_64.rpm
   340  ```
   341  
   342  ### <a name='manual-install-x86-64-amd64'></a>Manual Install x86_64 - amd64
   343  
   344  ```console
   345  $ wget https://github.com/goliatone/go-envset/releases/download/v<version>/envset_<version>_linux_x86_64.tar.gz
   346  $ tar -C /usr/bin/ -xzvf envset_<version>_linux_x86_64.tar.gz envset
   347  $ chmod +x /usr/bin/envset
   348  ```
   349  
   350  ## <a name='documentation'></a>Documentation
   351  
   352  `envset` will look for a file defining different environments and make them available as commands.
   353  
   354  ```ini
   355  [development]
   356  APP_BASE_URL=https://localhost:3003
   357  
   358  [production]
   359  APP_BASE_URL=https://envset.sh
   360  ```
   361  
   362  Your `.envset` files can have global variables that you are not part of any section but can be used to do string interpolation in section's variable values.
   363  
   364  The syntax to interpolate is `%(KEY)s`.
   365  
   366  ```ini
   367  VERSION=v0.6.2
   368  
   369  [development]
   370  APP_BASE_URL=https://localhost:3003
   371  DOWNLOAD_URL=%(APP_BASE_URL)s/%(VERSION)s
   372  
   373  [production]
   374  APP_BASE_URL=https://envset.sh
   375  DOWNLOAD_URL=%(APP_BASE_URL)s/%(VERSION)s
   376  ```
   377  
   378  You can have a special section with comments and the content will not generate syntax errors.
   379  
   380  
   381  ### <a name='Commands'></a>Commands
   382  
   383  The following is a list of the available commands:
   384  
   385  * metadata
   386      * compare
   387  * template
   388  
   389  ### <a name='VariableExpansion'></a>Variable Expansion
   390  
   391  `envset` can interpolate variables using POSIX variable expansion in both the loaded environment file and the running command arguments.
   392  
   393  ```ini
   394  [development]
   395  CLIENT_NAME=$(whoami -f)
   396  CLIENT_ID=${CLIENT_NAME}.devices.local
   397  ```
   398  
   399  ```
   400  $ envset development -- node cli.js --user '${USER}'
   401  ```
   402  
   403  ### <a name='Commands-1'></a>Commands
   404  
   405  If you type `envset` without arguments it will display help and a list of supported environment names.
   406  
   407  ## <a name='envset-file'></a>.envset File
   408  
   409  
   410  ## <a name='envsetrc'></a>.envsetrc
   411  You can create an `.envsetrc` file with configuration options for `envset`.
   412  
   413  The default `.envsetrc` looks like this:
   414  
   415  ```ini
   416  # Default configuration
   417  filename=.envset
   418  expand=true
   419  isolated=true
   420  export_environment=APP_ENV
   421  restart=true
   422  max_restarts=3
   423  restart_forever=false
   424  
   425  [metadata]
   426  dir=.meta
   427  file=data.json
   428  print=true
   429  json=false
   430  
   431  [template]
   432  dir=.
   433  file=envset.example
   434  
   435  [environments]
   436  name=test
   437  name=staging
   438  name=production
   439  name=development
   440  
   441  [comments]
   442  key=COMMENTS
   443  key=DOCUMENTATION
   444  ```
   445  
   446  ### <a name='Configuration'></a>Configuration
   447  
   448  Follows `rc` [standards][rcstand].
   449  
   450  
   451  ### <a name='ConfigurationSyntax'></a>Configuration Syntax
   452  
   453  The loaded files need to be valid `ini` syntax.
   454  
   455  ```ini
   456  [development]
   457  APP_BASE_URL=https://localhost:3003
   458  
   459  [production]
   460  APP_BASE_URL=https://envset.sh
   461  ```
   462  
   463  ### <a name='IgnoredAndRequiredSections'></a>Ignored And Required Sections
   464  
   465  You can add a `[required]` or `[ignored]` section in your `.envsetrc`:
   466  
   467  ```ini
   468  [ignored]
   469  development=MY_APP_NAME
   470  development=MY_APP_SECRET
   471  staging=MY_IGNORED_STAGING
   472  
   473  [required]
   474  development=MY_REQUIRED_APP_NAME
   475  staging=MY_REQUIRED_VAR_STAGING
   476  ```
   477  
   478  ## <a name='license'></a>License
   479  Copyright (c) 2015 goliatone
   480  Licensed under the MIT license.
   481  
   482  
   483  
   484  [ini]: https://en.wikipedia.org/wiki/INI_file
   485  [dtools]: http://cr.yp.to/daemontools.html
   486  [envdir]: http://cr.yp.to/daemontools/envdir.html
   487  [rcstand]: https://github.com/dominictarr/rc#standards
   488  [12factor]: http://12factor.net/config
   489  [vcn]: https://github.com/goliatone/vcn
   490  [npm-fix-perm]:https://docs.npmjs.com/getting-started/fixing-npm-permissions
   491  
   492  
   493  
   494  <!--
   495  Add self-update
   496  * [go-update](https://github.com/tj/go-update)
   497  * [go-update](https://github.com/inconshreveable/go-update)
   498  * [s3update](https://github.com/heetch/s3update): Related article [here](https://medium.com/inside-heetch/self-updating-tools-in-go-lang-9c07291d6285)
   499  
   500  documentation extension for urfav/cli/v2
   501  https://github.com/clok/cdocs
   502  -->