|
| 1 | +# GoDotEnv  |
| 2 | + |
| 3 | +A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file) |
| 4 | + |
| 5 | +From the original Library: |
| 6 | + |
| 7 | +> Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables. |
| 8 | +> |
| 9 | +> But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped. |
| 10 | +
|
| 11 | +It can be used as a library (for loading in env for your own daemons etc) or as a bin command. |
| 12 | + |
| 13 | +There is test coverage and CI for both linuxish and windows environments, but I make no guarantees about the bin version working on windows. |
| 14 | + |
| 15 | +## Installation |
| 16 | + |
| 17 | +As a library |
| 18 | + |
| 19 | +```shell |
| 20 | +go get github.com/OpsHelmInc/godotenv |
| 21 | +``` |
| 22 | + |
| 23 | +or if you want to use it as a bin command |
| 24 | +```shell |
| 25 | +go get github.com/OpsHelmInc/godotenv/cmd/godotenv |
| 26 | +``` |
| 27 | + |
| 28 | +## Usage |
| 29 | + |
| 30 | +Add your application configuration to your `.env` file in the root of your project: |
| 31 | + |
| 32 | +```shell |
| 33 | +S3_BUCKET=YOURS3BUCKET |
| 34 | +SECRET_KEY=YOURSECRETKEYGOESHERE |
| 35 | +``` |
| 36 | + |
| 37 | +Then in your Go app you can do something like |
| 38 | + |
| 39 | +```go |
| 40 | +package main |
| 41 | + |
| 42 | +import ( |
| 43 | + "github.com/OpsHelmInc/godotenv" |
| 44 | + "log" |
| 45 | + "os" |
| 46 | +) |
| 47 | + |
| 48 | +func main() { |
| 49 | + err := godotenv.Load() |
| 50 | + if err != nil { |
| 51 | + log.Fatal("Error loading .env file") |
| 52 | + } |
| 53 | + |
| 54 | + s3Bucket := os.Getenv("S3_BUCKET") |
| 55 | + secretKey := os.Getenv("SECRET_KEY") |
| 56 | + |
| 57 | + // now do something with s3 or whatever |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +If you're even lazier than that, you can just take advantage of the autoload package which will read in `.env` on import |
| 62 | + |
| 63 | +```go |
| 64 | +import _ "github.com/OpsHelmInc/godotenv/autoload" |
| 65 | +``` |
| 66 | + |
| 67 | +While `.env` in the project root is the default, you don't have to be constrained, both examples below are 100% legit |
| 68 | + |
| 69 | +```go |
| 70 | +_ = godotenv.Load("somerandomfile") |
| 71 | +_ = godotenv.Load("filenumberone.env", "filenumbertwo.env") |
| 72 | +``` |
| 73 | + |
| 74 | +If you want to be really fancy with your env file you can do comments and exports (below is a valid env file) |
| 75 | + |
| 76 | +```shell |
| 77 | +# I am a comment and that is OK |
| 78 | +SOME_VAR=someval |
| 79 | +FOO=BAR # comments at line end are OK too |
| 80 | +export BAR=BAZ |
| 81 | +``` |
| 82 | + |
| 83 | +Or finally you can do YAML(ish) style |
| 84 | + |
| 85 | +```yaml |
| 86 | +FOO: bar |
| 87 | +BAR: baz |
| 88 | +``` |
| 89 | +
|
| 90 | +as a final aside, if you don't want godotenv munging your env you can just get a map back instead |
| 91 | +
|
| 92 | +```go |
| 93 | +var myEnv map[string]string |
| 94 | +myEnv, err := godotenv.Read() |
| 95 | + |
| 96 | +s3Bucket := myEnv["S3_BUCKET"] |
| 97 | +``` |
| 98 | + |
| 99 | +... or from an `io.Reader` instead of a local file |
| 100 | + |
| 101 | +```go |
| 102 | +reader := getRemoteFile() |
| 103 | +myEnv, err := godotenv.Parse(reader) |
| 104 | +``` |
| 105 | + |
| 106 | +... or from a `string` if you so desire |
| 107 | + |
| 108 | +```go |
| 109 | +content := getRemoteFileContent() |
| 110 | +myEnv, err := godotenv.Unmarshal(content) |
| 111 | +``` |
| 112 | + |
| 113 | +### Precedence & Conventions |
| 114 | + |
| 115 | +Existing envs take precedence of envs that are loaded later. |
| 116 | + |
| 117 | +The [convention](https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use) |
| 118 | +for managing multiple environments (i.e. development, test, production) |
| 119 | +is to create an env named `{YOURAPP}_ENV` and load envs in this order: |
| 120 | + |
| 121 | +```go |
| 122 | +env := os.Getenv("FOO_ENV") |
| 123 | +if "" == env { |
| 124 | + env = "development" |
| 125 | +} |
| 126 | + |
| 127 | +godotenv.Load(".env." + env + ".local") |
| 128 | +if "test" != env { |
| 129 | + godotenv.Load(".env.local") |
| 130 | +} |
| 131 | +godotenv.Load(".env." + env) |
| 132 | +godotenv.Load() // The Original .env |
| 133 | +``` |
| 134 | + |
| 135 | +If you need to, you can also use `godotenv.Overload()` to defy this convention |
| 136 | +and overwrite existing envs instead of only supplanting them. Use with caution. |
| 137 | + |
| 138 | +### Command Mode |
| 139 | + |
| 140 | +Assuming you've installed the command as above and you've got `$GOPATH/bin` in your `$PATH` |
| 141 | + |
| 142 | +``` |
| 143 | +godotenv -f /some/path/to/.env some_command with some args |
| 144 | +``` |
| 145 | + |
| 146 | +If you don't specify `-f` it will fall back on the default of loading `.env` in `PWD` |
| 147 | + |
| 148 | +### Writing Env Files |
| 149 | + |
| 150 | +Godotenv can also write a map representing the environment to a correctly-formatted and escaped file |
| 151 | + |
| 152 | +```go |
| 153 | +env, err := godotenv.Unmarshal("KEY=value") |
| 154 | +err := godotenv.Write(env, "./.env") |
| 155 | +``` |
| 156 | + |
| 157 | +... or to a string |
| 158 | + |
| 159 | +```go |
| 160 | +env, err := godotenv.Unmarshal("KEY=value") |
| 161 | +content, err := godotenv.Marshal(env) |
| 162 | +``` |
| 163 | + |
| 164 | +## Contributing |
| 165 | + |
| 166 | +Contributions are most welcome! The parser itself is pretty stupidly naive and I wouldn't be surprised if it breaks with edge cases. |
| 167 | + |
| 168 | +*code changes without tests will not be accepted* |
| 169 | + |
| 170 | +1. Fork it |
| 171 | +2. Create your feature branch (`git checkout -b my-new-feature`) |
| 172 | +3. Commit your changes (`git commit -am 'Added some feature'`) |
| 173 | +4. Push to the branch (`git push origin my-new-feature`) |
| 174 | +5. Create new Pull Request |
| 175 | + |
| 176 | +## Releases |
| 177 | + |
| 178 | +Releases should follow [Semver](http://semver.org/) though the first couple of releases are `v1` and `v1.1`. |
| 179 | + |
| 180 | +Use [annotated tags for all releases](https://github.com/OpsHelmInc/godotenv/issues/30). Example `git tag -a v1.2.1` |
| 181 | + |
| 182 | + |
| 183 | +## Who? |
| 184 | + |
| 185 | +The original library [dotenv](https://github.com/bkeepers/dotenv) was written by [Brandon Keepers](http://opensoul.org/), and this port was done by [John Barton](https://johnbarton.co/) based off the tests/fixtures in the original library. |
0 commit comments