Skip to content

Commit 4fde7d8

Browse files
authored
fix #121 and #123 - add support for reading env variables from .env (#133)
1 parent af97076 commit 4fde7d8

File tree

14 files changed

+629
-0
lines changed

14 files changed

+629
-0
lines changed

β€ŽREADME.mdβ€Ž

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ You can provide default configuration flags to `act` by either creating a `./.ac
9393
-P ubuntu-latest=nektos/act-environments-ubuntu:18.04
9494
```
9595

96+
Additionally, act support loading environment variables from a `.env` file. The default is to look in the working directory for the file, but can be overriden by:
97+
98+
```
99+
act --env-file my.env
100+
```
101+
96102
# Support
97103

98104
Need help? Ask on [Gitter](https://gitter.im/nektos/act)!

β€Žcmd/input.goβ€Ž

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type Input struct {
1717
dryrun bool
1818
forcePull bool
1919
noOutput bool
20+
envfile string
2021
}
2122

2223
func (i *Input) resolve(path string) string {
@@ -33,6 +34,11 @@ func (i *Input) resolve(path string) string {
3334
return path
3435
}
3536

37+
// Envfile returns path to .env
38+
func (i *Input) Envfile() string {
39+
return i.resolve(i.envfile)
40+
}
41+
3642
// Workdir returns path to workdir
3743
func (i *Input) Workdir() string {
3844
return i.resolve(".")

β€Žcmd/root.goβ€Ž

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/nektos/act/pkg/common"
1313

1414
fswatch "github.com/andreaskoch/go-fswatch"
15+
"github.com/joho/godotenv"
1516
"github.com/nektos/act/pkg/model"
1617
"github.com/nektos/act/pkg/runner"
1718
gitignore "github.com/sabhiram/go-gitignore"
@@ -45,7 +46,9 @@ func Execute(ctx context.Context, version string) {
4546
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "verbose output")
4647
rootCmd.PersistentFlags().BoolVarP(&input.noOutput, "quiet", "q", false, "disable logging of output from steps")
4748
rootCmd.PersistentFlags().BoolVarP(&input.dryrun, "dryrun", "n", false, "dryrun mode")
49+
rootCmd.PersistentFlags().StringVarP(&input.envfile, "env-file", "", ".env", "environment file to read")
4850
rootCmd.SetArgs(args())
51+
4952
if err := rootCmd.Execute(); err != nil {
5053
os.Exit(1)
5154
}
@@ -91,6 +94,15 @@ func setupLogging(cmd *cobra.Command, args []string) {
9194

9295
func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []string) error {
9396
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+
}
105+
94106
planner, err := model.NewWorkflowPlanner(input.WorkflowsPath())
95107
if err != nil {
96108
return err

β€Žgo.modβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/gorilla/mux v1.7.0 // indirect
1919
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c
2020
github.com/inconshreveable/mousetrap v1.0.0 // indirect
21+
github.com/joho/godotenv v1.3.0
2122
github.com/jtolds/gls v4.2.1+incompatible // indirect
2223
github.com/mgutz/str v1.2.0 // indirect
2324
github.com/mitchellh/go-homedir v1.1.0 // indirect

β€Žgo.sumβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
5858
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
5959
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
6060
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
61+
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
62+
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
6163
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
6264
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
6365
github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp/Cjunrr1WlsXSZpqXn+uREuHvUVcK82CV8=

β€Žpkg/runner/runner_test.goβ€Ž

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package runner
33
import (
44
"context"
55
"fmt"
6+
"os"
67
"path/filepath"
78
"testing"
89

10+
"github.com/joho/godotenv"
911
"github.com/nektos/act/pkg/model"
1012

1113
log "github.com/sirupsen/logrus"
@@ -88,3 +90,53 @@ func TestRunEvent(t *testing.T) {
8890
})
8991
}
9092
}
93+
94+
func TestRunEventSecrets(t *testing.T) {
95+
if testing.Short() {
96+
t.Skip("skipping integration test")
97+
}
98+
99+
log.SetLevel(log.DebugLevel)
100+
ctx := context.Background()
101+
102+
platforms := map[string]string{
103+
"ubuntu-latest": "node:12.6-buster-slim",
104+
}
105+
106+
workflowPath := "secrets"
107+
eventName := "push"
108+
109+
workdir, err := filepath.Abs("testdata")
110+
assert.NilError(t, err, workflowPath)
111+
112+
_ = godotenv.Load(filepath.Join(workdir, workflowPath, ".env"))
113+
114+
secrets := make(map[string]string)
115+
for _, secret := range []string{
116+
"MY_SECRET",
117+
"MULTILINE_SECRET",
118+
"JSON_SECRET",
119+
} {
120+
if env, ok := os.LookupEnv(secret); ok && env != "" {
121+
secrets[secret] = env
122+
}
123+
}
124+
125+
runnerConfig := &Config{
126+
Workdir: workdir,
127+
EventName: eventName,
128+
Platforms: platforms,
129+
ReuseContainers: false,
130+
Secrets: secrets,
131+
}
132+
runner, err := New(runnerConfig)
133+
assert.NilError(t, err, workflowPath)
134+
135+
planner, err := model.NewWorkflowPlanner(fmt.Sprintf("testdata/%s", workflowPath))
136+
assert.NilError(t, err, workflowPath)
137+
138+
plan := planner.PlanEvent(eventName)
139+
140+
err = runner.NewPlanExecutor(plan)(ctx)
141+
assert.NilError(t, err, workflowPath)
142+
}
Lines changed: 3 additions & 0 deletions
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β€Ž

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ jobs:
77
steps:
88
- run: |
99
echo '${{secrets.MY_SECRET}}' | grep 'top-secret'
10+
- run: |
11+
echo "${{secrets.MULTILINE_SECRET}}" | wc -l | grep 3
12+
- run: |
13+
echo '${{secrets.JSON_SECRET}}' | grep "{\"foo\": \"bar\"}"

β€Žvendor/github.com/joho/godotenv/.gitignoreβ€Ž

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

β€Žvendor/github.com/joho/godotenv/.travis.ymlβ€Ž

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
Β (0)