mirror of
https://code.forgejo.org/forgejo/runner.git
synced 2025-09-15 18:57:01 +00:00
GitHub env file support (#426)
* Upgrade to the official golangci-lint action and fix some issues it found * Update deps * Remove a shadow warning * Initialize the splitPattern only once * Initial attempt at supporting $GITHUB_ENV Needs some polishing and tests * Now it's actually working * Replace golang.org/x/crypto/ssh/terminal with golang.org/x/term * Disable the issue-228 test again * The linter is picky * Discovered that the workflow/envs.txt had to exist in certain cases * Fix small linter issue
This commit is contained in:
parent
0fe34092d1
commit
b60851b818
13 changed files with 125 additions and 51 deletions
8
.github/workflows/push.yml
vendored
8
.github/workflows/push.yml
vendored
|
@ -7,11 +7,11 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: docker://golangci/golangci-lint:v1.23.8
|
- uses: golangci/golangci-lint-action@v2
|
||||||
with:
|
|
||||||
args: golangci-lint run
|
|
||||||
env:
|
env:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
|
with:
|
||||||
|
version: v1.32.2
|
||||||
|
|
||||||
test:
|
test:
|
||||||
name: Test
|
name: Test
|
||||||
|
@ -35,7 +35,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: GoReleaser
|
- name: GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v1
|
uses: goreleaser/goreleaser-action@v2
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
args: release --snapshot --rm-dist
|
args: release --snapshot --rm-dist
|
||||||
|
|
1
.github/workflows/test-expressions.yml
vendored
1
.github/workflows/test-expressions.yml
vendored
|
@ -8,6 +8,7 @@ env:
|
||||||
KEY_WITH_UNDERSCORES: value_with_underscores
|
KEY_WITH_UNDERSCORES: value_with_underscores
|
||||||
SOMETHING_TRUE: true
|
SOMETHING_TRUE: true
|
||||||
SOMETHING_FALSE: false
|
SOMETHING_FALSE: false
|
||||||
|
ACT: true
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
|
@ -43,7 +43,6 @@ type styleDef struct {
|
||||||
|
|
||||||
var styleDefs = []styleDef{
|
var styleDefs = []styleDef{
|
||||||
{"\u2554", "\u2557", "\u255a", "\u255d", "\u2550", "\u2551"},
|
{"\u2554", "\u2557", "\u255a", "\u255d", "\u2550", "\u2551"},
|
||||||
//{"\u250c", "\u2510", "\u2514", "\u2518", "\u2500", "\u2502"},
|
|
||||||
{"\u256d", "\u256e", "\u2570", "\u256f", "\u2500", "\u2502"},
|
{"\u256d", "\u256e", "\u2570", "\u256f", "\u2500", "\u2502"},
|
||||||
{"\u250c", "\u2510", "\u2514", "\u2518", "\u254c", "\u254e"},
|
{"\u250c", "\u2510", "\u2514", "\u2518", "\u254c", "\u254e"},
|
||||||
{" ", " ", " ", " ", " ", " "},
|
{" ", " ", " ", " ", " ", " "},
|
||||||
|
|
|
@ -157,7 +157,6 @@ func findGitDirectory(fromFile string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
//log.Debugf("Searching for git directory in %s", absPath)
|
|
||||||
fi, err := os.Stat(absPath)
|
fi, err := os.Stat(absPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
@ -2,6 +2,7 @@ package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -9,6 +10,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-git/go-billy/v5/helper/polyfill"
|
"github.com/go-git/go-billy/v5/helper/polyfill"
|
||||||
|
@ -24,7 +26,7 @@ import (
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewContainerInput the input for the New function
|
// NewContainerInput the input for the New function
|
||||||
|
@ -58,6 +60,7 @@ type Container interface {
|
||||||
Pull(forcePull bool) common.Executor
|
Pull(forcePull bool) common.Executor
|
||||||
Start(attach bool) common.Executor
|
Start(attach bool) common.Executor
|
||||||
Exec(command []string, env map[string]string) common.Executor
|
Exec(command []string, env map[string]string) common.Executor
|
||||||
|
UpdateFromGithubEnv(env *map[string]string) common.Executor
|
||||||
Remove() common.Executor
|
Remove() common.Executor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +119,10 @@ func (cr *containerReference) CopyDir(destPath string, srcPath string) common.Ex
|
||||||
).IfNot(common.Dryrun)
|
).IfNot(common.Dryrun)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cr *containerReference) UpdateFromGithubEnv(env *map[string]string) common.Executor {
|
||||||
|
return cr.extractGithubEnv(env).IfNot(common.Dryrun)
|
||||||
|
}
|
||||||
|
|
||||||
func (cr *containerReference) Exec(command []string, env map[string]string) common.Executor {
|
func (cr *containerReference) Exec(command []string, env map[string]string) common.Executor {
|
||||||
|
|
||||||
return common.NewPipelineExecutor(
|
return common.NewPipelineExecutor(
|
||||||
|
@ -196,10 +203,10 @@ func (cr *containerReference) find() common.Executor {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, container := range containers {
|
for _, c := range containers {
|
||||||
for _, name := range container.Names {
|
for _, name := range c.Names {
|
||||||
if name[1:] == cr.input.Name {
|
if name[1:] == cr.input.Name {
|
||||||
cr.id = container.ID
|
cr.id = c.ID
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +244,7 @@ func (cr *containerReference) create() common.Executor {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
isTerminal := terminal.IsTerminal(int(os.Stdout.Fd()))
|
isTerminal := term.IsTerminal(int(os.Stdout.Fd()))
|
||||||
|
|
||||||
input := cr.input
|
input := cr.input
|
||||||
config := &container.Config{
|
config := &container.Config{
|
||||||
|
@ -275,11 +282,59 @@ func (cr *containerReference) create() common.Executor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var singleLineEnvPattern, mulitiLineEnvPattern *regexp.Regexp
|
||||||
|
|
||||||
|
func (cr *containerReference) extractGithubEnv(env *map[string]string) common.Executor {
|
||||||
|
if singleLineEnvPattern == nil {
|
||||||
|
singleLineEnvPattern = regexp.MustCompile("^([^=]+)=([^=]+)$")
|
||||||
|
mulitiLineEnvPattern = regexp.MustCompile(`^([^<]+)<<(\w+)$`)
|
||||||
|
}
|
||||||
|
|
||||||
|
localEnv := *env
|
||||||
|
return func(ctx context.Context) error {
|
||||||
|
githubEnvTar, _, err := cr.cli.CopyFromContainer(ctx, cr.id, localEnv["GITHUB_ENV"])
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
reader := tar.NewReader(githubEnvTar)
|
||||||
|
_, err = reader.Next()
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
s := bufio.NewScanner(reader)
|
||||||
|
multiLineEnvKey := ""
|
||||||
|
multiLineEnvDelimiter := ""
|
||||||
|
multiLineEnvContent := ""
|
||||||
|
for s.Scan() {
|
||||||
|
line := s.Text()
|
||||||
|
if singleLineEnv := singleLineEnvPattern.FindStringSubmatch(line); singleLineEnv != nil {
|
||||||
|
localEnv[singleLineEnv[1]] = singleLineEnv[2]
|
||||||
|
}
|
||||||
|
if line == multiLineEnvDelimiter {
|
||||||
|
localEnv[multiLineEnvKey] = multiLineEnvContent
|
||||||
|
multiLineEnvKey, multiLineEnvDelimiter, multiLineEnvContent = "", "", ""
|
||||||
|
}
|
||||||
|
if multiLineEnvKey != "" && multiLineEnvDelimiter != "" {
|
||||||
|
if multiLineEnvContent != "" {
|
||||||
|
multiLineEnvContent += "\n"
|
||||||
|
}
|
||||||
|
multiLineEnvContent += line
|
||||||
|
}
|
||||||
|
if mulitiLineEnvStart := mulitiLineEnvPattern.FindStringSubmatch(line); mulitiLineEnvStart != nil {
|
||||||
|
multiLineEnvKey = mulitiLineEnvStart[1]
|
||||||
|
multiLineEnvDelimiter = mulitiLineEnvStart[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env = &localEnv
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (cr *containerReference) exec(cmd []string, env map[string]string) common.Executor {
|
func (cr *containerReference) exec(cmd []string, env map[string]string) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
logger.Debugf("Exec command '%s'", cmd)
|
logger.Debugf("Exec command '%s'", cmd)
|
||||||
isTerminal := terminal.IsTerminal(int(os.Stdout.Fd()))
|
isTerminal := term.IsTerminal(int(os.Stdout.Fd()))
|
||||||
envList := make([]string, 0)
|
envList := make([]string, 0)
|
||||||
for k, v := range env {
|
for k, v := range env {
|
||||||
envList = append(envList, fmt.Sprintf("%s=%s", k, v))
|
envList = append(envList, fmt.Sprintf("%s=%s", k, v))
|
||||||
|
@ -492,7 +547,7 @@ func (cr *containerReference) attach() common.Executor {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
isTerminal := terminal.IsTerminal(int(os.Stdout.Fd()))
|
isTerminal := term.IsTerminal(int(os.Stdout.Fd()))
|
||||||
|
|
||||||
var outWriter io.Writer
|
var outWriter io.Writer
|
||||||
outWriter = cr.input.Stdout
|
outWriter = cr.input.Stdout
|
||||||
|
|
|
@ -283,13 +283,13 @@ const (
|
||||||
// StepTypeRun is all steps that have a `run` attribute
|
// StepTypeRun is all steps that have a `run` attribute
|
||||||
StepTypeRun StepType = iota
|
StepTypeRun StepType = iota
|
||||||
|
|
||||||
//StepTypeUsesDockerURL is all steps that have a `uses` that is of the form `docker://...`
|
// StepTypeUsesDockerURL is all steps that have a `uses` that is of the form `docker://...`
|
||||||
StepTypeUsesDockerURL
|
StepTypeUsesDockerURL
|
||||||
|
|
||||||
//StepTypeUsesActionLocal is all steps that have a `uses` that is a local action in a subdirectory
|
// StepTypeUsesActionLocal is all steps that have a `uses` that is a local action in a subdirectory
|
||||||
StepTypeUsesActionLocal
|
StepTypeUsesActionLocal
|
||||||
|
|
||||||
//StepTypeUsesActionRemote is all steps that have a `uses` that is a reference to a github repo
|
// StepTypeUsesActionRemote is all steps that have a `uses` that is a reference to a github repo
|
||||||
StepTypeUsesActionRemote
|
StepTypeUsesActionRemote
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ var commandPatternADO *regexp.Regexp
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commandPatternGA = regexp.MustCompile("^::([^ ]+)( (.+))?::([^\r\n]*)[\r\n]+$")
|
commandPatternGA = regexp.MustCompile("^::([^ ]+)( (.+))?::([^\r\n]*)[\r\n]+$")
|
||||||
commandPatternADO = regexp.MustCompile("^##\\[([^ ]+)( (.+))?\\]([^\r\n]*)[\r\n]+$")
|
commandPatternADO = regexp.MustCompile("^##\\[([^ ]+)( (.+))?]([^\r\n]*)[\r\n]+$")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RunContext) commandHandler(ctx context.Context) common.LineHandler {
|
func (rc *RunContext) commandHandler(ctx context.Context) common.LineHandler {
|
||||||
|
@ -103,7 +103,7 @@ func unescapeCommandData(arg string) string {
|
||||||
"%0A": "\n",
|
"%0A": "\n",
|
||||||
}
|
}
|
||||||
for k, v := range escapeMap {
|
for k, v := range escapeMap {
|
||||||
arg = strings.Replace(arg, k, v, -1)
|
arg = strings.ReplaceAll(arg, k, v)
|
||||||
}
|
}
|
||||||
return arg
|
return arg
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ func unescapeCommandProperty(arg string) string {
|
||||||
"%2C": ",",
|
"%2C": ",",
|
||||||
}
|
}
|
||||||
for k, v := range escapeMap {
|
for k, v := range escapeMap {
|
||||||
arg = strings.Replace(arg, k, v, -1)
|
arg = strings.ReplaceAll(arg, k, v)
|
||||||
}
|
}
|
||||||
return arg
|
return arg
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetEnv(t *testing.T) {
|
func TestSetEnv(t *testing.T) {
|
||||||
assert := assert.New(t)
|
a := assert.New(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
rc := new(RunContext)
|
rc := new(RunContext)
|
||||||
handler := rc.commandHandler(ctx)
|
handler := rc.commandHandler(ctx)
|
||||||
|
|
||||||
handler("::set-env name=x::valz\n")
|
handler("::set-env name=x::valz\n")
|
||||||
assert.Equal("valz", rc.Env["x"])
|
a.Equal("valz", rc.Env["x"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetOutput(t *testing.T) {
|
func TestSetOutput(t *testing.T) {
|
||||||
assert := assert.New(t)
|
a := assert.New(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
rc := new(RunContext)
|
rc := new(RunContext)
|
||||||
rc.StepResults = make(map[string]*stepResult)
|
rc.StepResults = make(map[string]*stepResult)
|
||||||
|
@ -29,62 +29,62 @@ func TestSetOutput(t *testing.T) {
|
||||||
Outputs: make(map[string]string),
|
Outputs: make(map[string]string),
|
||||||
}
|
}
|
||||||
handler("::set-output name=x::valz\n")
|
handler("::set-output name=x::valz\n")
|
||||||
assert.Equal("valz", rc.StepResults["my-step"].Outputs["x"])
|
a.Equal("valz", rc.StepResults["my-step"].Outputs["x"])
|
||||||
|
|
||||||
handler("::set-output name=x::percent2%25\n")
|
handler("::set-output name=x::percent2%25\n")
|
||||||
assert.Equal("percent2%", rc.StepResults["my-step"].Outputs["x"])
|
a.Equal("percent2%", rc.StepResults["my-step"].Outputs["x"])
|
||||||
|
|
||||||
handler("::set-output name=x::percent2%25%0Atest\n")
|
handler("::set-output name=x::percent2%25%0Atest\n")
|
||||||
assert.Equal("percent2%\ntest", rc.StepResults["my-step"].Outputs["x"])
|
a.Equal("percent2%\ntest", rc.StepResults["my-step"].Outputs["x"])
|
||||||
|
|
||||||
handler("::set-output name=x::percent2%25%0Atest another3%25test\n")
|
handler("::set-output name=x::percent2%25%0Atest another3%25test\n")
|
||||||
assert.Equal("percent2%\ntest another3%test", rc.StepResults["my-step"].Outputs["x"])
|
a.Equal("percent2%\ntest another3%test", rc.StepResults["my-step"].Outputs["x"])
|
||||||
|
|
||||||
handler("::set-output name=x%3A::percent2%25%0Atest\n")
|
handler("::set-output name=x%3A::percent2%25%0Atest\n")
|
||||||
assert.Equal("percent2%\ntest", rc.StepResults["my-step"].Outputs["x:"])
|
a.Equal("percent2%\ntest", rc.StepResults["my-step"].Outputs["x:"])
|
||||||
|
|
||||||
handler("::set-output name=x%3A%2C%0A%25%0D%3A::percent2%25%0Atest\n")
|
handler("::set-output name=x%3A%2C%0A%25%0D%3A::percent2%25%0Atest\n")
|
||||||
assert.Equal("percent2%\ntest", rc.StepResults["my-step"].Outputs["x:,\n%\r:"])
|
a.Equal("percent2%\ntest", rc.StepResults["my-step"].Outputs["x:,\n%\r:"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddpath(t *testing.T) {
|
func TestAddpath(t *testing.T) {
|
||||||
assert := assert.New(t)
|
a := assert.New(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
rc := new(RunContext)
|
rc := new(RunContext)
|
||||||
handler := rc.commandHandler(ctx)
|
handler := rc.commandHandler(ctx)
|
||||||
|
|
||||||
handler("::add-path::/zoo\n")
|
handler("::add-path::/zoo\n")
|
||||||
assert.Equal("/zoo", rc.ExtraPath[0])
|
a.Equal("/zoo", rc.ExtraPath[0])
|
||||||
|
|
||||||
handler("::add-path::/boo\n")
|
handler("::add-path::/boo\n")
|
||||||
assert.Equal("/boo", rc.ExtraPath[1])
|
a.Equal("/boo", rc.ExtraPath[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStopCommands(t *testing.T) {
|
func TestStopCommands(t *testing.T) {
|
||||||
assert := assert.New(t)
|
a := assert.New(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
rc := new(RunContext)
|
rc := new(RunContext)
|
||||||
handler := rc.commandHandler(ctx)
|
handler := rc.commandHandler(ctx)
|
||||||
|
|
||||||
handler("::set-env name=x::valz\n")
|
handler("::set-env name=x::valz\n")
|
||||||
assert.Equal("valz", rc.Env["x"])
|
a.Equal("valz", rc.Env["x"])
|
||||||
handler("::stop-commands::my-end-token\n")
|
handler("::stop-commands::my-end-token\n")
|
||||||
handler("::set-env name=x::abcd\n")
|
handler("::set-env name=x::abcd\n")
|
||||||
assert.Equal("valz", rc.Env["x"])
|
a.Equal("valz", rc.Env["x"])
|
||||||
handler("::my-end-token::\n")
|
handler("::my-end-token::\n")
|
||||||
handler("::set-env name=x::abcd\n")
|
handler("::set-env name=x::abcd\n")
|
||||||
assert.Equal("abcd", rc.Env["x"])
|
a.Equal("abcd", rc.Env["x"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddpathADO(t *testing.T) {
|
func TestAddpathADO(t *testing.T) {
|
||||||
assert := assert.New(t)
|
a := assert.New(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
rc := new(RunContext)
|
rc := new(RunContext)
|
||||||
handler := rc.commandHandler(ctx)
|
handler := rc.commandHandler(ctx)
|
||||||
|
|
||||||
handler("##[add-path]/zoo\n")
|
handler("##[add-path]/zoo\n")
|
||||||
assert.Equal("/zoo", rc.ExtraPath[0])
|
a.Equal("/zoo", rc.ExtraPath[0])
|
||||||
|
|
||||||
handler("##[add-path]/boo\n")
|
handler("##[add-path]/boo\n")
|
||||||
assert.Equal("/boo", rc.ExtraPath[1])
|
a.Equal("/boo", rc.ExtraPath[1])
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,7 +185,6 @@ func TestInterpolate(t *testing.T) {
|
||||||
func updateTestExpressionWorkflow(t *testing.T, tables []struct {
|
func updateTestExpressionWorkflow(t *testing.T, tables []struct {
|
||||||
in string
|
in string
|
||||||
out string
|
out string
|
||||||
//wantErr bool
|
|
||||||
}, rc *RunContext) {
|
}, rc *RunContext) {
|
||||||
|
|
||||||
var envs string
|
var envs string
|
||||||
|
|
|
@ -12,11 +12,11 @@ import (
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
//nocolor = 0
|
// nocolor = 0
|
||||||
red = 31
|
red = 31
|
||||||
green = 32
|
green = 32
|
||||||
yellow = 33
|
yellow = 33
|
||||||
|
@ -126,7 +126,7 @@ func (f *stepLogFormatter) isColored(entry *logrus.Entry) bool {
|
||||||
func checkIfTerminal(w io.Writer) bool {
|
func checkIfTerminal(w io.Writer) bool {
|
||||||
switch v := w.(type) {
|
switch v := w.(type) {
|
||||||
case *os.File:
|
case *os.File:
|
||||||
return terminal.IsTerminal(int(v.Fd()))
|
return term.IsTerminal(int(v.Fd()))
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,10 @@ func (rc *RunContext) startJobContainer() common.Executor {
|
||||||
Name: "workflow/event.json",
|
Name: "workflow/event.json",
|
||||||
Mode: 0644,
|
Mode: 0644,
|
||||||
Body: rc.EventJSON,
|
Body: rc.EventJSON,
|
||||||
|
}, &container.FileEntry{
|
||||||
|
Name: "workflow/envs.txt",
|
||||||
|
Mode: 0644,
|
||||||
|
Body: "",
|
||||||
}, &container.FileEntry{
|
}, &container.FileEntry{
|
||||||
Name: "home/.act",
|
Name: "home/.act",
|
||||||
Mode: 0644,
|
Mode: 0644,
|
||||||
|
@ -199,6 +203,13 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = sc.setupEnv()(ctx)
|
_ = sc.setupEnv()(ctx)
|
||||||
|
|
||||||
|
if sc.Env != nil {
|
||||||
|
err := rc.JobContainer.UpdateFromGithubEnv(&sc.Env)(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
rc.ExprEval = sc.NewExpressionEvaluator()
|
rc.ExprEval = sc.NewExpressionEvaluator()
|
||||||
|
|
||||||
runStep, err := rc.EvalBool(sc.Step.If)
|
runStep, err := rc.EvalBool(sc.Step.If)
|
||||||
|
@ -267,14 +278,17 @@ func (rc *RunContext) isEnabled(ctx context.Context) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var splitPattern *regexp.Regexp
|
||||||
|
|
||||||
// EvalBool evaluates an expression against current run context
|
// EvalBool evaluates an expression against current run context
|
||||||
func (rc *RunContext) EvalBool(expr string) (bool, error) {
|
func (rc *RunContext) EvalBool(expr string) (bool, error) {
|
||||||
|
if splitPattern == nil {
|
||||||
|
splitPattern = regexp.MustCompile(fmt.Sprintf(`%s|%s|\S+`, expressionPattern.String(), operatorPattern.String()))
|
||||||
|
}
|
||||||
if strings.HasPrefix(strings.TrimSpace(expr), "!") {
|
if strings.HasPrefix(strings.TrimSpace(expr), "!") {
|
||||||
return false, errors.New("expressions starting with ! must be wrapped in ${{ }}")
|
return false, errors.New("expressions starting with ! must be wrapped in ${{ }}")
|
||||||
}
|
}
|
||||||
if expr != "" {
|
if expr != "" {
|
||||||
splitPattern := regexp.MustCompile(fmt.Sprintf(`%s|%s|\S+`, expressionPattern.String(), operatorPattern.String()))
|
|
||||||
|
|
||||||
parts := splitPattern.FindAllString(expr, -1)
|
parts := splitPattern.FindAllString(expr, -1)
|
||||||
var evaluatedParts []string
|
var evaluatedParts []string
|
||||||
for i, part := range parts {
|
for i, part := range parts {
|
||||||
|
@ -550,6 +564,8 @@ func (rc *RunContext) withGithubEnv(env map[string]string) map[string]string {
|
||||||
github := rc.getGithubContext()
|
github := rc.getGithubContext()
|
||||||
env["CI"] = "true"
|
env["CI"] = "true"
|
||||||
env["HOME"] = "/github/home"
|
env["HOME"] = "/github/home"
|
||||||
|
env["GITHUB_ENV"] = "/github/workflow/envs.txt"
|
||||||
|
|
||||||
env["GITHUB_WORKFLOW"] = github.Workflow
|
env["GITHUB_WORKFLOW"] = github.Workflow
|
||||||
env["GITHUB_RUN_ID"] = github.RunID
|
env["GITHUB_RUN_ID"] = github.RunID
|
||||||
env["GITHUB_RUN_NUMBER"] = github.RunNumber
|
env["GITHUB_RUN_NUMBER"] = github.RunNumber
|
||||||
|
|
|
@ -92,7 +92,7 @@ func TestRunEvent(t *testing.T) {
|
||||||
{"testdata", "matrix-include-exclude", "push", "", platforms},
|
{"testdata", "matrix-include-exclude", "push", "", platforms},
|
||||||
{"testdata", "commands", "push", "", platforms},
|
{"testdata", "commands", "push", "", platforms},
|
||||||
{"testdata", "workdir", "push", "", platforms},
|
{"testdata", "workdir", "push", "", platforms},
|
||||||
//{"testdata", "issue-228", "push", "", platforms}, // TODO [igni]: Remove this once everything passes
|
// {"testdata", "issue-228", "push", "", platforms}, // TODO [igni]: Remove this once everything passes
|
||||||
{"testdata", "defaults-run", "push", "", platforms},
|
{"testdata", "defaults-run", "push", "", platforms},
|
||||||
}
|
}
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
|
|
17
cmd/root.go
17
cmd/root.go
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common"
|
||||||
|
|
||||||
fswatch "github.com/andreaskoch/go-fswatch"
|
"github.com/andreaskoch/go-fswatch"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"github.com/nektos/act/pkg/model"
|
"github.com/nektos/act/pkg/model"
|
||||||
"github.com/nektos/act/pkg/runner"
|
"github.com/nektos/act/pkg/runner"
|
||||||
|
@ -79,7 +79,12 @@ func readArgsFile(file string) []string {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer func() {
|
||||||
|
err := f.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to close args file: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
scanner := bufio.NewScanner(f)
|
scanner := bufio.NewScanner(f)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
arg := scanner.Text()
|
arg := scanner.Text()
|
||||||
|
@ -91,7 +96,7 @@ func readArgsFile(file string) []string {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupLogging(cmd *cobra.Command, args []string) {
|
func setupLogging(cmd *cobra.Command, _ []string) {
|
||||||
verbose, _ := cmd.Flags().GetBool("verbose")
|
verbose, _ := cmd.Flags().GetBool("verbose")
|
||||||
if verbose {
|
if verbose {
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
|
@ -189,7 +194,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
||||||
Platforms: input.newPlatforms(),
|
Platforms: input.newPlatforms(),
|
||||||
Privileged: input.privileged,
|
Privileged: input.privileged,
|
||||||
}
|
}
|
||||||
runner, err := runner.New(config)
|
r, err := runner.New(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -198,10 +203,10 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
||||||
if watch, err := cmd.Flags().GetBool("watch"); err != nil {
|
if watch, err := cmd.Flags().GetBool("watch"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if watch {
|
} else if watch {
|
||||||
return watchAndRun(ctx, runner.NewPlanExecutor(plan))
|
return watchAndRun(ctx, r.NewPlanExecutor(plan))
|
||||||
}
|
}
|
||||||
|
|
||||||
return runner.NewPlanExecutor(plan)(ctx)
|
return r.NewPlanExecutor(plan)(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue