Skip to content

Commit 2f39547

Browse files
jonyhy96cplee
andauthored
feat: load every environment from --env-file to workflow (#184)
* feat: load every environment from --env-file to workflow * fix: pass dotenv's environments through by context * updates to support --secret-file Co-authored-by: Casey Lee <[email protected]>
1 parent f6e37a8 commit 2f39547

File tree

10 files changed

+47
-30
lines changed

10 files changed

+47
-30
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ dist/
1515
.todo
1616

1717
*.nupkg
18+
.vscode/

cmd/input.go

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type Input struct {
1818
forcePull bool
1919
noOutput bool
2020
envfile string
21+
secretfile string
2122
}
2223

2324
func (i *Input) resolve(path string) string {
@@ -39,6 +40,11 @@ func (i *Input) Envfile() string {
3940
return i.resolve(i.envfile)
4041
}
4142

43+
// Secretfile returns path to secrets
44+
func (i *Input) Secretfile() string {
45+
return i.resolve(i.secretfile)
46+
}
47+
4248
// Workdir returns path to workdir
4349
func (i *Input) Workdir() string {
4450
return i.resolve(".")

cmd/root.go

+25-10
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ func Execute(ctx context.Context, version string) {
4646
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "verbose output")
4747
rootCmd.PersistentFlags().BoolVarP(&input.noOutput, "quiet", "q", false, "disable logging of output from steps")
4848
rootCmd.PersistentFlags().BoolVarP(&input.dryrun, "dryrun", "n", false, "dryrun mode")
49-
rootCmd.PersistentFlags().StringVarP(&input.envfile, "env-file", "", ".env", "environment file to read")
49+
rootCmd.PersistentFlags().StringVarP(&input.secretfile, "secret-file", "", "", "file with list of secrets to read from")
50+
rootCmd.PersistentFlags().StringVarP(&input.envfile, "env-file", "", ".env", "environment file to read and use as env in the containers")
5051
rootCmd.SetArgs(args())
5152

5253
if err := rootCmd.Execute(); err != nil {
@@ -92,16 +93,29 @@ func setupLogging(cmd *cobra.Command, args []string) {
9293
}
9394
}
9495

96+
func readEnvs(path string, envs map[string]string) bool {
97+
if _, err := os.Stat(path); err == nil {
98+
env, err := godotenv.Read(path)
99+
if err != nil {
100+
log.Fatalf("Error loading from %s: %v", path, err)
101+
}
102+
for k, v := range env {
103+
envs[k] = v
104+
}
105+
return true
106+
}
107+
return false
108+
}
109+
95110
func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []string) error {
96111
return func(cmd *cobra.Command, args []string) error {
97-
envfile := input.Envfile()
98-
if _, err := os.Stat(envfile); err == nil {
99-
log.Debugf("Loading environment from %s", envfile)
100-
err := godotenv.Load(envfile)
101-
if err != nil {
102-
log.Fatalf("Error loading environment from %s: %v", envfile, err)
103-
}
104-
}
112+
log.Debugf("Loading environment from %s", input.Envfile())
113+
envs := make(map[string]string)
114+
_ = readEnvs(input.Envfile(), envs)
115+
116+
log.Debugf("Loading secrets from %s", input.Secretfile())
117+
secrets := newSecrets(input.secrets)
118+
_ = readEnvs(input.Secretfile(), secrets)
105119

106120
planner, err := model.NewWorkflowPlanner(input.WorkflowsPath())
107121
if err != nil {
@@ -149,7 +163,8 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
149163
Workdir: input.Workdir(),
150164
BindWorkdir: input.bindWorkdir,
151165
LogOutput: !input.noOutput,
152-
Secrets: newSecrets(input.secrets),
166+
Env: envs,
167+
Secrets: secrets,
153168
Platforms: input.newPlatforms(),
154169
}
155170
runner, err := runner.New(config)

pkg/runner/run_context.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ type stepResult struct {
4545
// GetEnv returns the env for the context
4646
func (rc *RunContext) GetEnv() map[string]string {
4747
if rc.Env == nil {
48-
rc.Env = mergeMaps(rc.Run.Workflow.Env, rc.Run.Job().Env)
48+
rc.Env = mergeMaps(rc.Config.Env, rc.Run.Workflow.Env, rc.Run.Job().Env)
4949
}
5050
return rc.Env
5151
}

pkg/runner/runner.go

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type Config struct {
2424
ReuseContainers bool // reuse containers to maintain state
2525
ForcePull bool // force pulling of the image, if already present
2626
LogOutput bool // log the output from docker run
27+
Env map[string]string // env for containers
2728
Secrets map[string]string // list of secrets
2829
Platforms map[string]string // list of platforms
2930
}

pkg/runner/runner_test.go

+3-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package runner
33
import (
44
"context"
55
"fmt"
6-
"os"
76
"path/filepath"
87
"testing"
98

@@ -110,25 +109,16 @@ func TestRunEventSecrets(t *testing.T) {
110109
workdir, err := filepath.Abs("testdata")
111110
assert.NilError(t, err, workflowPath)
112111

113-
_ = godotenv.Load(filepath.Join(workdir, workflowPath, ".env"))
114-
115-
secrets := make(map[string]string)
116-
for _, secret := range []string{
117-
"MY_SECRET",
118-
"MULTILINE_SECRET",
119-
"JSON_SECRET",
120-
} {
121-
if env, ok := os.LookupEnv(secret); ok && env != "" {
122-
secrets[secret] = env
123-
}
124-
}
112+
env, _ := godotenv.Read(filepath.Join(workdir, workflowPath, ".env"))
113+
secrets, _ := godotenv.Read(filepath.Join(workdir, workflowPath, ".secrets"))
125114

126115
runnerConfig := &Config{
127116
Workdir: workdir,
128117
EventName: eventName,
129118
Platforms: platforms,
130119
ReuseContainers: false,
131120
Secrets: secrets,
121+
Env: env,
132122
}
133123
runner, err := New(runnerConfig)
134124
assert.NilError(t, err, workflowPath)

pkg/runner/testdata/secrets/.actrc

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
-W .
2-
-s MY_SECRET
3-
-s MULTILINE_SECRET
4-
-s JSON_SECRET
2+
--secret-file .secrets

pkg/runner/testdata/secrets/.env

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
MY_SECRET=top-secret
2-
MULTILINE_SECRET="foo\nbar\nbaz"
3-
JSON_SECRET={"foo": "bar"}
1+
HELLO=WORLD
2+
MULTILINE_ENV="foo\nbar\nbaz"

pkg/runner/testdata/secrets/.secrets

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
MY_SECRET=top-secret
2+
MULTILINE_SECRET="foo\nbar\nbaz"
3+
JSON_SECRET={"foo": "bar"}

pkg/runner/testdata/secrets/push.yml

+4
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ jobs:
1111
echo "${{secrets.MULTILINE_SECRET}}" | wc -l | grep 3
1212
- run: |
1313
echo '${{secrets.JSON_SECRET}}' | grep "{\"foo\": \"bar\"}"
14+
- run: |
15+
echo '${{env.HELLO}}' | grep "WORLD"
16+
- run: |
17+
echo "${{env.MULTILINE_ENV}}" | wc -l | grep 3

0 commit comments

Comments
 (0)