mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-03-25 16:25:02 +01:00
Compare commits
8 Commits
9fd95d203f
...
09d18916bf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09d18916bf | ||
|
|
bffc600775 | ||
|
|
a27473e6a8 | ||
|
|
a77f10683d | ||
|
|
d187ac2fc1 | ||
|
|
949a40c7a5 | ||
|
|
3413919161 | ||
|
|
40ee0f3ef6 |
@@ -3,8 +3,8 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func drawGraph(plan *model.Plan) error {
|
func drawGraph(plan *model.Plan) error {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func printList(plan *model.Plan) error {
|
func printList(plan *model.Plan) error {
|
||||||
|
|||||||
50
cmd/root.go
50
cmd/root.go
@@ -5,12 +5,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
@@ -25,14 +27,14 @@ import (
|
|||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/artifactcache"
|
"gitea.com/gitea/act_runner/pkg/artifactcache"
|
||||||
"github.com/actions-oss/act-cli/pkg/artifacts"
|
"gitea.com/gitea/act_runner/pkg/artifacts"
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/container"
|
"gitea.com/gitea/act_runner/pkg/container"
|
||||||
"github.com/actions-oss/act-cli/pkg/gh"
|
"gitea.com/gitea/act_runner/pkg/gh"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/actions-oss/act-cli/pkg/runner"
|
"gitea.com/gitea/act_runner/pkg/runner"
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Flag struct {
|
type Flag struct {
|
||||||
@@ -176,7 +178,7 @@ func bugReport(ctx context.Context, version string) error {
|
|||||||
report += sprintf("Variant:", "https://gitea.com/actions-oss/act-cli / https://github.com/actions-oss/act-cli")
|
report += sprintf("Variant:", "https://gitea.com/actions-oss/act-cli / https://github.com/actions-oss/act-cli")
|
||||||
report += sprintf("GOOS:", runtime.GOOS)
|
report += sprintf("GOOS:", runtime.GOOS)
|
||||||
report += sprintf("GOARCH:", runtime.GOARCH)
|
report += sprintf("GOARCH:", runtime.GOARCH)
|
||||||
report += sprintf("NumCPU:", fmt.Sprint(runtime.NumCPU()))
|
report += sprintf("NumCPU:", strconv.Itoa(runtime.NumCPU()))
|
||||||
|
|
||||||
var dockerHost string
|
var dockerHost string
|
||||||
var exists bool
|
var exists bool
|
||||||
@@ -199,15 +201,21 @@ func bugReport(ctx context.Context, version string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
report += sprintf("Config files:", "")
|
report += sprintf("Config files:", "")
|
||||||
|
var reportSb202 strings.Builder
|
||||||
|
var reportSb205 strings.Builder
|
||||||
for _, c := range configLocations() {
|
for _, c := range configLocations() {
|
||||||
args := readArgsFile(c, false)
|
args := readArgsFile(c, false)
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
report += fmt.Sprintf("\t%s:\n", c)
|
fmt.Fprintf(&reportSb202, "\t%s:\n", c)
|
||||||
|
var reportSb206 strings.Builder
|
||||||
for _, l := range args {
|
for _, l := range args {
|
||||||
report += fmt.Sprintf("\t\t%s\n", l)
|
fmt.Fprintf(&reportSb206, "\t\t%s\n", l)
|
||||||
}
|
}
|
||||||
|
reportSb205.WriteString(reportSb206.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
report += reportSb205.String()
|
||||||
|
report += reportSb202.String()
|
||||||
|
|
||||||
vcs, ok := debug.ReadBuildInfo()
|
vcs, ok := debug.ReadBuildInfo()
|
||||||
if ok && vcs != nil {
|
if ok && vcs != nil {
|
||||||
@@ -220,9 +228,11 @@ func bugReport(ctx context.Context, version string) error {
|
|||||||
report += sprintf("\tMain checksum:", vcs.Main.Sum)
|
report += sprintf("\tMain checksum:", vcs.Main.Sum)
|
||||||
|
|
||||||
report += fmt.Sprintln("\tBuild settings:")
|
report += fmt.Sprintln("\tBuild settings:")
|
||||||
|
var reportSb223 strings.Builder
|
||||||
for _, set := range vcs.Settings {
|
for _, set := range vcs.Settings {
|
||||||
report += sprintf(fmt.Sprintf("\t\t%s:", set.Key), set.Value)
|
reportSb223.WriteString(sprintf(fmt.Sprintf("\t\t%s:", set.Key), set.Value))
|
||||||
}
|
}
|
||||||
|
report += reportSb223.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := container.GetHostInfo(ctx)
|
info, err := container.GetHostInfo(ctx)
|
||||||
@@ -245,13 +255,15 @@ func bugReport(ctx context.Context, version string) error {
|
|||||||
report += sprintf("\tOS version:", info.OSVersion)
|
report += sprintf("\tOS version:", info.OSVersion)
|
||||||
report += sprintf("\tOS arch:", info.Architecture)
|
report += sprintf("\tOS arch:", info.Architecture)
|
||||||
report += sprintf("\tOS kernel:", info.KernelVersion)
|
report += sprintf("\tOS kernel:", info.KernelVersion)
|
||||||
report += sprintf("\tOS CPU:", fmt.Sprint(info.NCPU))
|
report += sprintf("\tOS CPU:", strconv.Itoa(info.NCPU))
|
||||||
report += sprintf("\tOS memory:", fmt.Sprintf("%d MB", info.MemTotal/1024/1024))
|
report += sprintf("\tOS memory:", fmt.Sprintf("%d MB", info.MemTotal/1024/1024))
|
||||||
|
|
||||||
report += fmt.Sprintln("\tSecurity options:")
|
report += fmt.Sprintln("\tSecurity options:")
|
||||||
|
var reportSb252 strings.Builder
|
||||||
for _, secopt := range info.SecurityOptions {
|
for _, secopt := range info.SecurityOptions {
|
||||||
report += fmt.Sprintf("\t\t%s\n", secopt)
|
fmt.Fprintf(&reportSb252, "\t\t%s\n", secopt)
|
||||||
}
|
}
|
||||||
|
report += reportSb252.String()
|
||||||
|
|
||||||
fmt.Println(report)
|
fmt.Println(report)
|
||||||
return nil
|
return nil
|
||||||
@@ -261,7 +273,7 @@ func generateManPage(cmd *cobra.Command) error {
|
|||||||
header := &doc.GenManHeader{
|
header := &doc.GenManHeader{
|
||||||
Title: "act",
|
Title: "act",
|
||||||
Section: "1",
|
Section: "1",
|
||||||
Source: fmt.Sprintf("act %s", cmd.Version),
|
Source: "act " + cmd.Version,
|
||||||
}
|
}
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
cobra.CheckErr(doc.GenMan(cmd, header, buf))
|
cobra.CheckErr(doc.GenMan(cmd, header, buf))
|
||||||
@@ -575,7 +587,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
|||||||
}
|
}
|
||||||
if plan != nil {
|
if plan != nil {
|
||||||
if len(plan.Stages) == 0 {
|
if len(plan.Stages) == 0 {
|
||||||
plannerErr = fmt.Errorf("could not find any stages to run. View the valid jobs with `act --list`. Use `act --help` to find how to filter by Job ID/Workflow/Event Name")
|
plannerErr = errors.New("could not find any stages to run. View the valid jobs with `act --list`. Use `act --help` to find how to filter by Job ID/Workflow/Event Name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if plan == nil && plannerErr != nil {
|
if plan == nil && plannerErr != nil {
|
||||||
@@ -611,7 +623,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
|||||||
log.Warnf(deprecationWarning, "privileged", "--privileged")
|
log.Warnf(deprecationWarning, "privileged", "--privileged")
|
||||||
}
|
}
|
||||||
if len(input.usernsMode) > 0 {
|
if len(input.usernsMode) > 0 {
|
||||||
log.Warnf(deprecationWarning, "userns", fmt.Sprintf("--userns=%s", input.usernsMode))
|
log.Warnf(deprecationWarning, "userns", "--userns="+input.usernsMode)
|
||||||
}
|
}
|
||||||
if len(input.containerCapAdd) > 0 {
|
if len(input.containerCapAdd) > 0 {
|
||||||
log.Warnf(deprecationWarning, "container-cap-add", fmt.Sprintf("--cap-add=%s", input.containerCapAdd))
|
log.Warnf(deprecationWarning, "container-cap-add", fmt.Sprintf("--cap-add=%s", input.containerCapAdd))
|
||||||
@@ -699,9 +711,9 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
|||||||
var r runner.Runner
|
var r runner.Runner
|
||||||
if eventName == "workflow_call" {
|
if eventName == "workflow_call" {
|
||||||
// Do not use the totally broken code and instead craft a fake caller
|
// Do not use the totally broken code and instead craft a fake caller
|
||||||
convertedInputs := make(map[string]interface{})
|
convertedInputs := make(map[string]any)
|
||||||
for k, v := range inputs {
|
for k, v := range inputs {
|
||||||
var raw interface{}
|
var raw any
|
||||||
if err := yaml.Unmarshal([]byte(v), &raw); err != nil {
|
if err := yaml.Unmarshal([]byte(v), &raw); err != nil {
|
||||||
return fmt.Errorf("failed to unmarshal input %s: %w", k, err)
|
return fmt.Errorf("failed to unmarshal input %s: %w", k, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadSecrets(t *testing.T) {
|
func TestReadSecrets(t *testing.T) {
|
||||||
@@ -34,7 +35,7 @@ func TestListOptions(t *testing.T) {
|
|||||||
err := newRunCommand(context.Background(), &Input{
|
err := newRunCommand(context.Background(), &Input{
|
||||||
listOptions: true,
|
listOptions: true,
|
||||||
})(rootCmd, []string{})
|
})(rootCmd, []string{})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRun(t *testing.T) {
|
func TestRun(t *testing.T) {
|
||||||
@@ -44,7 +45,7 @@ func TestRun(t *testing.T) {
|
|||||||
workdir: "../pkg/runner/testdata/",
|
workdir: "../pkg/runner/testdata/",
|
||||||
workflowsPath: "./basic/push.yml",
|
workflowsPath: "./basic/push.yml",
|
||||||
})(rootCmd, []string{})
|
})(rootCmd, []string{})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunPush(t *testing.T) {
|
func TestRunPush(t *testing.T) {
|
||||||
@@ -54,7 +55,7 @@ func TestRunPush(t *testing.T) {
|
|||||||
workdir: "../pkg/runner/testdata/",
|
workdir: "../pkg/runner/testdata/",
|
||||||
workflowsPath: "./basic/push.yml",
|
workflowsPath: "./basic/push.yml",
|
||||||
})(rootCmd, []string{"push"})
|
})(rootCmd, []string{"push"})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunPushJsonLogger(t *testing.T) {
|
func TestRunPushJsonLogger(t *testing.T) {
|
||||||
@@ -65,7 +66,7 @@ func TestRunPushJsonLogger(t *testing.T) {
|
|||||||
workflowsPath: "./basic/push.yml",
|
workflowsPath: "./basic/push.yml",
|
||||||
jsonLogger: true,
|
jsonLogger: true,
|
||||||
})(rootCmd, []string{"push"})
|
})(rootCmd, []string{"push"})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFlags(t *testing.T) {
|
func TestFlags(t *testing.T) {
|
||||||
@@ -73,13 +74,13 @@ func TestFlags(t *testing.T) {
|
|||||||
t.Run("TestFlag-"+f, func(t *testing.T) {
|
t.Run("TestFlag-"+f, func(t *testing.T) {
|
||||||
rootCmd := createRootCommand(context.Background(), &Input{}, "")
|
rootCmd := createRootCommand(context.Background(), &Input{}, "")
|
||||||
err := rootCmd.Flags().Set(f, "true")
|
err := rootCmd.Flags().Set(f, "true")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = newRunCommand(context.Background(), &Input{
|
err = newRunCommand(context.Background(), &Input{
|
||||||
platforms: []string{"ubuntu-latest=node:16-buster-slim"},
|
platforms: []string{"ubuntu-latest=node:16-buster-slim"},
|
||||||
workdir: "../pkg/runner/testdata/",
|
workdir: "../pkg/runner/testdata/",
|
||||||
workflowsPath: "./basic/push.yml",
|
workflowsPath: "./basic/push.yml",
|
||||||
})(rootCmd, []string{})
|
})(rootCmd, []string{})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +93,7 @@ func TestWorkflowCall(t *testing.T) {
|
|||||||
workflowsPath: "./workflow_call_inputs/workflow_call_inputs.yml",
|
workflowsPath: "./workflow_call_inputs/workflow_call_inputs.yml",
|
||||||
inputs: []string{"required=required input", "boolean=true"},
|
inputs: []string{"required=required input", "boolean=true"},
|
||||||
})(rootCmd, []string{"workflow_call"})
|
})(rootCmd, []string{"workflow_call"})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocalRepositories(t *testing.T) {
|
func TestLocalRepositories(t *testing.T) {
|
||||||
@@ -105,5 +106,5 @@ func TestLocalRepositories(t *testing.T) {
|
|||||||
workflowsPath: "./remote-action-composite-action-ref-partial-override/push.yml",
|
workflowsPath: "./remote-action-composite-action-ref-partial-override/push.yml",
|
||||||
localRepository: []string{"needs/override@main=" + wd + "/actions-environment-and-context-tests"},
|
localRepository: []string{"needs/override@main=" + wd + "/actions-environment-and-context-tests"},
|
||||||
})(rootCmd, []string{"push"})
|
})(rootCmd, []string{"push"})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
60
go.mod
60
go.mod
@@ -21,71 +21,83 @@ require (
|
|||||||
gotest.tools/v3 v3.5.2
|
gotest.tools/v3 v3.5.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require go.yaml.in/yaml/v4 v4.0.0-rc.3
|
require (
|
||||||
|
dario.cat/mergo v1.0.2
|
||||||
|
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||||
|
github.com/Masterminds/semver v1.5.0
|
||||||
|
github.com/adrg/xdg v0.5.3
|
||||||
|
github.com/andreaskoch/go-fswatch v1.0.0
|
||||||
|
github.com/avast/retry-go v3.0.0+incompatible
|
||||||
|
github.com/containerd/errdefs v1.0.0
|
||||||
|
github.com/creack/pty v1.1.24
|
||||||
|
github.com/distribution/reference v0.6.0
|
||||||
|
github.com/docker/cli v28.5.1+incompatible
|
||||||
|
github.com/docker/go-connections v0.6.0
|
||||||
|
github.com/go-git/go-billy/v5 v5.7.0
|
||||||
|
github.com/go-git/go-git/v5 v5.16.5
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||||
|
github.com/julienschmidt/httprouter v1.3.0
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||||
|
github.com/moby/go-archive v0.1.0
|
||||||
|
github.com/moby/patternmatcher v0.6.0
|
||||||
|
github.com/opencontainers/image-spec v1.1.1
|
||||||
|
github.com/opencontainers/selinux v1.13.1
|
||||||
|
github.com/pkg/errors v0.9.1
|
||||||
|
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
|
||||||
|
github.com/spf13/pflag v1.0.10
|
||||||
|
github.com/timshannon/bolthold v0.0.0-20240314194003-30aac6950928
|
||||||
|
go.etcd.io/bbolt v1.4.3
|
||||||
|
go.yaml.in/yaml/v4 v4.0.0-rc.3
|
||||||
|
golang.org/x/crypto v0.48.0
|
||||||
|
golang.org/x/sync v0.19.0
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cyphar.com/go-pathrs v0.2.3 // indirect
|
cyphar.com/go-pathrs v0.2.3 // indirect
|
||||||
dario.cat/mergo v1.0.2 // indirect
|
|
||||||
github.com/Masterminds/semver v1.5.0 // indirect
|
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||||
github.com/avast/retry-go v3.0.0+incompatible // indirect
|
|
||||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/cloudflare/circl v1.6.3 // indirect
|
github.com/cloudflare/circl v1.6.3 // indirect
|
||||||
github.com/containerd/errdefs v1.0.0 // indirect
|
|
||||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/creack/pty v1.1.24 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/distribution/reference v0.6.0 // indirect
|
|
||||||
github.com/docker/cli v28.5.1+incompatible // indirect
|
|
||||||
github.com/docker/docker-credential-helpers v0.9.5 // indirect
|
github.com/docker/docker-credential-helpers v0.9.5 // indirect
|
||||||
github.com/docker/go-connections v0.6.0 // indirect
|
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.7.0 // indirect
|
|
||||||
github.com/go-git/go-git/v5 v5.16.5 // indirect
|
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/google/go-cmp v0.7.0 // indirect
|
github.com/google/go-cmp v0.7.0 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
|
||||||
github.com/kevinburke/ssh_config v1.6.0 // indirect
|
github.com/kevinburke/ssh_config v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.4 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
github.com/moby/go-archive v0.1.0 // indirect
|
|
||||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
|
||||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||||
github.com/moby/sys/user v0.4.0 // indirect
|
github.com/moby/sys/user v0.4.0 // indirect
|
||||||
github.com/moby/sys/userns v0.1.0 // indirect
|
github.com/moby/sys/userns v0.1.0 // indirect
|
||||||
github.com/moby/term v0.5.2 // indirect
|
github.com/moby/term v0.5.2 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
|
||||||
github.com/opencontainers/selinux v1.13.1 // indirect
|
|
||||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sergi/go-diff v1.4.0 // indirect
|
github.com/sergi/go-diff v1.4.0 // indirect
|
||||||
github.com/skeema/knownhosts v1.3.2 // indirect
|
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||||
github.com/spf13/pflag v1.0.10 // indirect
|
|
||||||
github.com/stretchr/objx v0.5.3 // indirect
|
github.com/stretchr/objx v0.5.3 // indirect
|
||||||
github.com/timshannon/bolthold v0.0.0-20240314194003-30aac6950928 // indirect
|
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||||
go.etcd.io/bbolt v1.4.3 // indirect
|
|
||||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.40.0 // indirect
|
go.opentelemetry.io/otel v1.40.0 // indirect
|
||||||
@@ -93,10 +105,10 @@ require (
|
|||||||
go.opentelemetry.io/otel/metric v1.40.0 // indirect
|
go.opentelemetry.io/otel/metric v1.40.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.40.0 // indirect
|
go.opentelemetry.io/otel/trace v1.40.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||||
golang.org/x/crypto v0.48.0 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/net v0.50.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
|
||||||
golang.org/x/sys v0.41.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
|
golang.org/x/text v0.34.0 // indirect
|
||||||
golang.org/x/tools v0.42.0 // indirect
|
golang.org/x/tools v0.42.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
37
go.sum
37
go.sum
@@ -12,6 +12,8 @@ gitea.com/actions-oss/act-cli v0.4.2-0.20260220200604-40ee0f3ef6fc h1:KXg17X1FZh
|
|||||||
gitea.com/actions-oss/act-cli v0.4.2-0.20260220200604-40ee0f3ef6fc/go.mod h1:tl2dPJQRui7za899nfJIhPqP3a8ii+ySEvzL18mjC0U=
|
gitea.com/actions-oss/act-cli v0.4.2-0.20260220200604-40ee0f3ef6fc/go.mod h1:tl2dPJQRui7za899nfJIhPqP3a8ii+ySEvzL18mjC0U=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||||
|
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
||||||
|
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||||
@@ -19,8 +21,13 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0
|
|||||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
|
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||||
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
||||||
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||||
|
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
|
||||||
|
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
|
||||||
|
github.com/andreaskoch/go-fswatch v1.0.0 h1:la8nP/HiaFCxP2IM6NZNUCoxgLWuyNFgH0RligBbnJU=
|
||||||
|
github.com/andreaskoch/go-fswatch v1.0.0/go.mod h1:r5/iV+4jfwoY2sYqBkg8vpF04ehOvEl4qPptVGdxmqo=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
@@ -41,7 +48,9 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
|
|||||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
|
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
|
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
|
||||||
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||||
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
||||||
@@ -96,6 +105,7 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
||||||
|
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
@@ -119,8 +129,15 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
||||||
@@ -155,7 +172,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
|
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
|
||||||
|
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
|
||||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||||
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
@@ -176,6 +197,7 @@ github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+Q
|
|||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
@@ -193,6 +215,7 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
|
|||||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||||
@@ -217,47 +240,60 @@ go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZY
|
|||||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
||||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
|
go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
|
||||||
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
|
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
|
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
|
||||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
|
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||||
@@ -265,6 +301,7 @@ golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
|||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
1
internal/app/act-cli/VERSION
Normal file
1
internal/app/act-cli/VERSION
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0.4.0
|
||||||
19
internal/app/act-cli/main.go
Normal file
19
internal/app/act-cli/main.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/cmd"
|
||||||
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed VERSION
|
||||||
|
var version string
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx, cancel := common.CreateGracefulJobCancellationContext()
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
cmd.Execute(ctx, version)
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"gitea.com/gitea/act_runner/internal/pkg/config"
|
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/artifactcache"
|
"gitea.com/gitea/act_runner/pkg/artifactcache"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gitea.com/gitea/act_runner/internal/app/run"
|
"gitea.com/gitea/act_runner/internal/app/run"
|
||||||
"github.com/actions-oss/act-cli/pkg/artifactcache"
|
"gitea.com/gitea/act_runner/pkg/artifactcache"
|
||||||
"github.com/actions-oss/act-cli/pkg/artifacts"
|
"gitea.com/gitea/act_runner/pkg/artifacts"
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/actions-oss/act-cli/pkg/runner"
|
"gitea.com/gitea/act_runner/pkg/runner"
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@@ -312,7 +312,7 @@ func runExecList(planner model.WorkflowPlanner, execArgs *executeArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command, args []string) error {
|
func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command, args []string) error {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(_ *cobra.Command, args []string) error {
|
||||||
planner, err := model.NewWorkflowPlanner(execArgs.WorkflowsPath(), model.PlannerConfig{
|
planner, err := model.NewWorkflowPlanner(execArgs.WorkflowsPath(), model.PlannerConfig{
|
||||||
Recursive: !execArgs.noWorkflowRecurse,
|
Recursive: !execArgs.noWorkflowRecurse,
|
||||||
Workflow: model.WorkflowConfig{
|
Workflow: model.WorkflowConfig{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gotest.tools/v3/assert"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRegisterNonInteractiveReturnsLabelValidationError(t *testing.T) {
|
func TestRegisterNonInteractiveReturnsLabelValidationError(t *testing.T) {
|
||||||
@@ -15,5 +15,5 @@ func TestRegisterNonInteractiveReturnsLabelValidationError(t *testing.T) {
|
|||||||
Token: "token",
|
Token: "token",
|
||||||
InstanceAddr: "http://localhost:3000",
|
InstanceAddr: "http://localhost:3000",
|
||||||
})
|
})
|
||||||
assert.Error(t, err, "unsupported schema: invalid")
|
require.Error(t, err, "unsupported schema: invalid")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,16 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||||
"connectrpc.com/connect"
|
"connectrpc.com/connect"
|
||||||
"github.com/actions-oss/act-cli/pkg/artifactcache"
|
"gitea.com/gitea/act_runner/pkg/artifactcache"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/actions-oss/act-cli/pkg/runner"
|
"gitea.com/gitea/act_runner/pkg/runner"
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@@ -145,7 +146,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||||||
var stepIds []string
|
var stepIds []string
|
||||||
for i, v := range job.Steps {
|
for i, v := range job.Steps {
|
||||||
if v.ID == "" {
|
if v.ID == "" {
|
||||||
v.ID = fmt.Sprint(i)
|
v.ID = strconv.Itoa(i)
|
||||||
}
|
}
|
||||||
stepIds = append(stepIds, v.ID)
|
stepIds = append(stepIds, v.ID)
|
||||||
}
|
}
|
||||||
@@ -204,7 +205,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||||||
// maxLifetime = time.Until(deadline)
|
// maxLifetime = time.Until(deadline)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
actCtx := map[string]interface{}{}
|
actCtx := map[string]any{}
|
||||||
forgeCtx := task.Context.AsMap()
|
forgeCtx := task.Context.AsMap()
|
||||||
actCtx["github"] = forgeCtx
|
actCtx["github"] = forgeCtx
|
||||||
actCtx["gitea"] = forgeCtx
|
actCtx["gitea"] = forgeCtx
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.yaml.in/yaml/v4"
|
"go.yaml.in/yaml/v4"
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// It behaves like the C# implementation in the repository –
|
// It behaves like the C# implementation in the repository –
|
||||||
// it supports escaped braces and numeric argument indices.
|
// it supports escaped braces and numeric argument indices.
|
||||||
// Format specifiers (e.g. :D) are recognised but currently ignored.
|
// Format specifiers (e.g. :D) are recognised but currently ignored.
|
||||||
func Format(formatStr string, args ...interface{}) (string, error) {
|
func Format(formatStr string, args ...any) (string, error) {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(formatStr) {
|
for i < len(formatStr) {
|
||||||
@@ -47,7 +47,7 @@ func Format(formatStr string, args ...interface{}) (string, error) {
|
|||||||
}
|
}
|
||||||
// append argument (format specifier is ignored here)
|
// append argument (format specifier is ignored here)
|
||||||
arg := args[idx]
|
arg := args[idx]
|
||||||
sb.WriteString(fmt.Sprintf("%v", arg))
|
fmt.Fprintf(&sb, "%v", arg)
|
||||||
if spec != "" {
|
if spec != "" {
|
||||||
// placeholder for future specifier handling
|
// placeholder for future specifier handling
|
||||||
_ = spec
|
_ = spec
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package functions
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFormat(t *testing.T) {
|
func TestFormat(t *testing.T) {
|
||||||
s, err := Format("Hello {0}, you have {1} new messages", "Alice", 5)
|
_, err := Format("Hello {0}, you have {1} new messages", "Alice", 5)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fmt.Println(s) // Hello Alice, you have 5 new messages
|
// fmt.Println(s) // Hello Alice, you have 5 new messages
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,14 +93,14 @@ func (o CaseSensitiveObject[T]) GetEnumerator() map[string]T {
|
|||||||
type EvaluationResult struct {
|
type EvaluationResult struct {
|
||||||
context *EvaluationContext
|
context *EvaluationContext
|
||||||
level int
|
level int
|
||||||
value interface{}
|
value any
|
||||||
kind ValueKind
|
kind ValueKind
|
||||||
raw interface{}
|
raw any
|
||||||
omitTracing bool
|
omitTracing bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEvaluationResult creates a new EvaluationResult.
|
// NewEvaluationResult creates a new EvaluationResult.
|
||||||
func NewEvaluationResult(context *EvaluationContext, level int, val interface{}, kind ValueKind, raw interface{}, omitTracing bool) *EvaluationResult {
|
func NewEvaluationResult(context *EvaluationContext, level int, val any, kind ValueKind, raw any, omitTracing bool) *EvaluationResult {
|
||||||
er := &EvaluationResult{context: context, level: level, value: val, kind: kind, raw: raw, omitTracing: omitTracing}
|
er := &EvaluationResult{context: context, level: level, value: val, kind: kind, raw: raw, omitTracing: omitTracing}
|
||||||
if !omitTracing {
|
if !omitTracing {
|
||||||
er.traceValue()
|
er.traceValue()
|
||||||
@@ -112,10 +112,10 @@ func NewEvaluationResult(context *EvaluationContext, level int, val interface{},
|
|||||||
func (er *EvaluationResult) Kind() ValueKind { return er.kind }
|
func (er *EvaluationResult) Kind() ValueKind { return er.kind }
|
||||||
|
|
||||||
// Raw returns the raw value that was passed to the constructor.
|
// Raw returns the raw value that was passed to the constructor.
|
||||||
func (er *EvaluationResult) Raw() interface{} { return er.raw }
|
func (er *EvaluationResult) Raw() any { return er.raw }
|
||||||
|
|
||||||
// Value returns the canonical value.
|
// Value returns the canonical value.
|
||||||
func (er *EvaluationResult) Value() interface{} { return er.value }
|
func (er *EvaluationResult) Value() any { return er.value }
|
||||||
|
|
||||||
// IsFalsy implements the logic from the C# class.
|
// IsFalsy implements the logic from the C# class.
|
||||||
func (er *EvaluationResult) IsFalsy() bool {
|
func (er *EvaluationResult) IsFalsy() bool {
|
||||||
@@ -195,7 +195,7 @@ func (er *EvaluationResult) ConvertToString() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TryGetCollectionInterface returns the underlying collection if the value is an array or object.
|
// TryGetCollectionInterface returns the underlying collection if the value is an array or object.
|
||||||
func (er *EvaluationResult) TryGetCollectionInterface() (interface{}, bool) {
|
func (er *EvaluationResult) TryGetCollectionInterface() (any, bool) {
|
||||||
switch v := er.value.(type) {
|
switch v := er.value.(type) {
|
||||||
case ReadOnlyArray[any]:
|
case ReadOnlyArray[any]:
|
||||||
return v, true
|
return v, true
|
||||||
@@ -207,7 +207,7 @@ func (er *EvaluationResult) TryGetCollectionInterface() (interface{}, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateIntermediateResult creates an EvaluationResult from an arbitrary object.
|
// CreateIntermediateResult creates an EvaluationResult from an arbitrary object.
|
||||||
func CreateIntermediateResult(context *EvaluationContext, obj interface{}) *EvaluationResult {
|
func CreateIntermediateResult(context *EvaluationContext, obj any) *EvaluationResult {
|
||||||
val, kind, raw := convertToCanonicalValue(obj)
|
val, kind, raw := convertToCanonicalValue(obj)
|
||||||
return NewEvaluationResult(context, 0, val, kind, raw, true)
|
return NewEvaluationResult(context, 0, val, kind, raw, true)
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ var ExpressionConstants = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertToCanonicalValue converts an arbitrary Go value to a canonical form.
|
// convertToCanonicalValue converts an arbitrary Go value to a canonical form.
|
||||||
func convertToCanonicalValue(obj interface{}) (interface{}, ValueKind, interface{}) {
|
func convertToCanonicalValue(obj any) (any, ValueKind, any) {
|
||||||
switch v := obj.(type) {
|
switch v := obj.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
return nil, ValueKindNull, nil
|
return nil, ValueKindNull, nil
|
||||||
@@ -243,11 +243,11 @@ func convertToCanonicalValue(obj interface{}) (interface{}, ValueKind, interface
|
|||||||
return f, ValueKindNumber, f
|
return f, ValueKindNumber, f
|
||||||
case string:
|
case string:
|
||||||
return v, ValueKindString, v
|
return v, ValueKindString, v
|
||||||
case []interface{}:
|
case []any:
|
||||||
return BasicArray[any](v), ValueKindArray, v
|
return BasicArray[any](v), ValueKindArray, v
|
||||||
case ReadOnlyArray[any]:
|
case ReadOnlyArray[any]:
|
||||||
return v, ValueKindArray, v
|
return v, ValueKindArray, v
|
||||||
case map[string]interface{}:
|
case map[string]any:
|
||||||
return CaseInsensitiveObject[any](v), ValueKindObject, v
|
return CaseInsensitiveObject[any](v), ValueKindObject, v
|
||||||
case ReadOnlyObject[any]:
|
case ReadOnlyObject[any]:
|
||||||
return v, ValueKindObject, v
|
return v, ValueKindObject, v
|
||||||
@@ -257,7 +257,7 @@ func convertToCanonicalValue(obj interface{}) (interface{}, ValueKind, interface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toInt64(v interface{}) int64 {
|
func toInt64(v any) int64 {
|
||||||
switch i := v.(type) {
|
switch i := v.(type) {
|
||||||
case int:
|
case int:
|
||||||
return int64(i)
|
return int64(i)
|
||||||
@@ -274,7 +274,7 @@ func toInt64(v interface{}) int64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toUint64(v interface{}) uint64 {
|
func toUint64(v any) uint64 {
|
||||||
switch i := v.(type) {
|
switch i := v.(type) {
|
||||||
case uint:
|
case uint:
|
||||||
return uint64(i)
|
return uint64(i)
|
||||||
@@ -291,7 +291,7 @@ func toUint64(v interface{}) uint64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toFloat64(v interface{}) float64 {
|
func toFloat64(v any) float64 {
|
||||||
switch f := v.(type) {
|
switch f := v.(type) {
|
||||||
case float32:
|
case float32:
|
||||||
return float64(f)
|
return float64(f)
|
||||||
@@ -304,7 +304,7 @@ func toFloat64(v interface{}) float64 {
|
|||||||
|
|
||||||
// coerceTypes implements the C# CoerceTypes logic.
|
// coerceTypes implements the C# CoerceTypes logic.
|
||||||
// It converts values to compatible types before comparison.
|
// It converts values to compatible types before comparison.
|
||||||
func coerceTypes(left, right interface{}) (interface{}, interface{}, ValueKind, ValueKind) {
|
func coerceTypes(left, right any) (any, any, ValueKind, ValueKind) {
|
||||||
leftKind := getKind(left)
|
leftKind := getKind(left)
|
||||||
rightKind := getKind(right)
|
rightKind := getKind(right)
|
||||||
|
|
||||||
@@ -340,7 +340,7 @@ func coerceTypes(left, right interface{}) (interface{}, interface{}, ValueKind,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// abstractEqual uses coerceTypes before comparing.
|
// abstractEqual uses coerceTypes before comparing.
|
||||||
func abstractEqual(left, right interface{}) bool {
|
func abstractEqual(left, right any) bool {
|
||||||
left, right, leftKind, rightKind := coerceTypes(left, right)
|
left, right, leftKind, rightKind := coerceTypes(left, right)
|
||||||
if leftKind != rightKind {
|
if leftKind != rightKind {
|
||||||
return false
|
return false
|
||||||
@@ -367,7 +367,7 @@ func abstractEqual(left, right interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// abstractGreaterThan uses coerceTypes before comparing.
|
// abstractGreaterThan uses coerceTypes before comparing.
|
||||||
func abstractGreaterThan(left, right interface{}) bool {
|
func abstractGreaterThan(left, right any) bool {
|
||||||
left, right, leftKind, rightKind := coerceTypes(left, right)
|
left, right, leftKind, rightKind := coerceTypes(left, right)
|
||||||
if leftKind != rightKind {
|
if leftKind != rightKind {
|
||||||
return false
|
return false
|
||||||
@@ -389,7 +389,7 @@ func abstractGreaterThan(left, right interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// abstractLessThan uses coerceTypes before comparing.
|
// abstractLessThan uses coerceTypes before comparing.
|
||||||
func abstractLessThan(left, right interface{}) bool {
|
func abstractLessThan(left, right any) bool {
|
||||||
left, right, leftKind, rightKind := coerceTypes(left, right)
|
left, right, leftKind, rightKind := coerceTypes(left, right)
|
||||||
if leftKind != rightKind {
|
if leftKind != rightKind {
|
||||||
return false
|
return false
|
||||||
@@ -411,7 +411,7 @@ func abstractLessThan(left, right interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertToNumber converts a value to a float64 following JavaScript rules.
|
// convertToNumber converts a value to a float64 following JavaScript rules.
|
||||||
func convertToNumber(v interface{}) float64 {
|
func convertToNumber(v any) float64 {
|
||||||
switch val := v.(type) {
|
switch val := v.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
return 0
|
return 0
|
||||||
@@ -447,7 +447,7 @@ func convertToNumber(v interface{}) float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getKind returns the ValueKind for a Go value.
|
// getKind returns the ValueKind for a Go value.
|
||||||
func getKind(v interface{}) ValueKind {
|
func getKind(v any) ValueKind {
|
||||||
switch v.(type) {
|
switch v.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
return ValueKindNull
|
return ValueKindNull
|
||||||
@@ -457,9 +457,9 @@ func getKind(v interface{}) ValueKind {
|
|||||||
return ValueKindNumber
|
return ValueKindNumber
|
||||||
case string:
|
case string:
|
||||||
return ValueKindString
|
return ValueKindString
|
||||||
case []interface{}:
|
case []any:
|
||||||
return ValueKindArray
|
return ValueKindArray
|
||||||
case map[string]interface{}:
|
case map[string]any:
|
||||||
return ValueKindObject
|
return ValueKindObject
|
||||||
default:
|
default:
|
||||||
return ValueKindObject
|
return ValueKindObject
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
exprparser "github.com/actions-oss/act-cli/internal/expr"
|
exprparser "gitea.com/gitea/act_runner/internal/expr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EvaluationContext holds variables that can be referenced in expressions.
|
// EvaluationContext holds variables that can be referenced in expressions.
|
||||||
@@ -56,11 +56,11 @@ func (e *Evaluator) EvaluateBoolean(expr string) (bool, error) {
|
|||||||
return result.IsTruthy(), nil
|
return result.IsTruthy(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Evaluator) ToRaw(result *EvaluationResult) (interface{}, error) {
|
func (e *Evaluator) ToRaw(result *EvaluationResult) (any, error) {
|
||||||
if col, ok := result.TryGetCollectionInterface(); ok {
|
if col, ok := result.TryGetCollectionInterface(); ok {
|
||||||
switch node := col.(type) {
|
switch node := col.(type) {
|
||||||
case ReadOnlyObject[any]:
|
case ReadOnlyObject[any]:
|
||||||
rawMap := map[string]interface{}{}
|
rawMap := map[string]any{}
|
||||||
for k, v := range node.GetEnumerator() {
|
for k, v := range node.GetEnumerator() {
|
||||||
rawRes, err := e.ToRaw(CreateIntermediateResult(e.Context(), v))
|
rawRes, err := e.ToRaw(CreateIntermediateResult(e.Context(), v))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -70,7 +70,7 @@ func (e *Evaluator) ToRaw(result *EvaluationResult) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
return rawMap, nil
|
return rawMap, nil
|
||||||
case ReadOnlyArray[any]:
|
case ReadOnlyArray[any]:
|
||||||
rawArray := []interface{}{}
|
rawArray := []any{}
|
||||||
for _, v := range node.GetEnumerator() {
|
for _, v := range node.GetEnumerator() {
|
||||||
rawRes, err := e.ToRaw(CreateIntermediateResult(e.Context(), v))
|
rawRes, err := e.ToRaw(CreateIntermediateResult(e.Context(), v))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -85,7 +85,7 @@ func (e *Evaluator) ToRaw(result *EvaluationResult) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate parses and evaluates the expression, returning a boolean result.
|
// Evaluate parses and evaluates the expression, returning a boolean result.
|
||||||
func (e *Evaluator) EvaluateRaw(expr string) (interface{}, error) {
|
func (e *Evaluator) EvaluateRaw(expr string) (any, error) {
|
||||||
root, err := exprparser.Parse(expr)
|
root, err := exprparser.Parse(expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("parse error: %w", err)
|
return false, fmt.Errorf("parse error: %w", err)
|
||||||
@@ -97,16 +97,16 @@ func (e *Evaluator) EvaluateRaw(expr string) (interface{}, error) {
|
|||||||
return e.ToRaw(result)
|
return e.ToRaw(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
type FilteredArray []interface{}
|
type FilteredArray []any
|
||||||
|
|
||||||
func (a FilteredArray) GetAt(i int64) interface{} {
|
func (a FilteredArray) GetAt(i int64) any {
|
||||||
if int(i) > len(a) {
|
if int(i) > len(a) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return a[i]
|
return a[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a FilteredArray) GetEnumerator() []interface{} {
|
func (a FilteredArray) GetEnumerator() []any {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ func (e *Evaluator) evalBinaryNodeLeft(node *exprparser.BinaryNode, left *Evalua
|
|||||||
return CreateIntermediateResult(e.Context(), ret), nil
|
return CreateIntermediateResult(e.Context(), ret), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, errors.ErrUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Evaluator) evalBinaryNodeRight(node *exprparser.BinaryNode, left *EvaluationResult, right *EvaluationResult) (*EvaluationResult, error) {
|
func (e *Evaluator) evalBinaryNodeRight(node *exprparser.BinaryNode, left *EvaluationResult, right *EvaluationResult) (*EvaluationResult, error) {
|
||||||
@@ -244,7 +244,7 @@ func (e *Evaluator) evalUnaryNode(node *exprparser.UnaryNode) (*EvaluationResult
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func processIndex(col interface{}, right *EvaluationResult) interface{} {
|
func processIndex(col any, right *EvaluationResult) any {
|
||||||
if mapVal, ok := col.(ReadOnlyObject[any]); ok {
|
if mapVal, ok := col.(ReadOnlyObject[any]); ok {
|
||||||
key, ok := right.Value().(string)
|
key, ok := right.Value().(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -264,7 +264,7 @@ func processIndex(col interface{}, right *EvaluationResult) interface{} {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processStar(subcol interface{}, ret FilteredArray) FilteredArray {
|
func processStar(subcol any, ret FilteredArray) FilteredArray {
|
||||||
if array, ok := subcol.(ReadOnlyArray[any]); ok {
|
if array, ok := subcol.(ReadOnlyArray[any]); ok {
|
||||||
ret = append(ret, array.GetEnumerator()...)
|
ret = append(ret, array.GetEnumerator()...)
|
||||||
} else if obj, ok := subcol.(ReadOnlyObject[any]); ok {
|
} else if obj, ok := subcol.(ReadOnlyObject[any]); ok {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
// Test boolean and comparison operations using the evaluator.
|
// Test boolean and comparison operations using the evaluator.
|
||||||
func TestEvaluator_BooleanOps(t *testing.T) {
|
func TestEvaluator_BooleanOps(t *testing.T) {
|
||||||
ctx := &EvaluationContext{Variables: CaseInsensitiveObject[any](map[string]interface{}{"a": 5, "b": 3})}
|
ctx := &EvaluationContext{Variables: CaseInsensitiveObject[any](map[string]any{"a": 5, "b": 3})}
|
||||||
eval := NewEvaluator(ctx)
|
eval := NewEvaluator(ctx)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@@ -44,7 +44,7 @@ func TestEvaluator_Raw(t *testing.T) {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
expr string
|
expr string
|
||||||
want interface{}
|
want any
|
||||||
}{
|
}{
|
||||||
{"a.b['x']", nil},
|
{"a.b['x']", nil},
|
||||||
{"(a.b).c['x']", nil},
|
{"(a.b).c['x']", nil},
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/internal/eval/functions"
|
"gitea.com/gitea/act_runner/internal/eval/functions"
|
||||||
exprparser "github.com/actions-oss/act-cli/internal/expr"
|
exprparser "gitea.com/gitea/act_runner/internal/expr"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FromJSON struct {
|
type FromJSON struct {
|
||||||
@@ -113,7 +113,7 @@ func (Format) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResu
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sargs := []interface{}{}
|
sargs := []any{}
|
||||||
for _, arg := range args[1:] {
|
for _, arg := range args[1:] {
|
||||||
el, err := eval.Evaluate(arg)
|
el, err := eval.Evaluate(arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type Node interface {
|
|||||||
|
|
||||||
type ValueNode struct {
|
type ValueNode struct {
|
||||||
Kind TokenKind
|
Kind TokenKind
|
||||||
Value interface{}
|
Value any
|
||||||
}
|
}
|
||||||
|
|
||||||
// FunctionNode represents a function call with arguments.
|
// FunctionNode represents a function call with arguments.
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const (
|
|||||||
type Token struct {
|
type Token struct {
|
||||||
Kind TokenKind
|
Kind TokenKind
|
||||||
Raw string
|
Raw string
|
||||||
Value interface{}
|
Value any
|
||||||
Index int
|
Index int
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ func (l *Lexer) readNumber() *Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Try to parse as float64
|
// Try to parse as float64
|
||||||
var val interface{} = raw
|
var val any = raw
|
||||||
if f, err := strconv.ParseFloat(raw, 64); err == nil {
|
if f, err := strconv.ParseFloat(raw, 64); err == nil {
|
||||||
val = f
|
val = f
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func TestLexerMultiple(t *testing.T) {
|
|||||||
cases := []struct {
|
cases := []struct {
|
||||||
expr string
|
expr string
|
||||||
expected []TokenKind
|
expected []TokenKind
|
||||||
values []interface{} // optional, nil if not checking values
|
values []any // optional, nil if not checking values
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
expr: "github.event_name == 'push'",
|
expr: "github.event_name == 'push'",
|
||||||
@@ -67,12 +67,12 @@ func TestLexerMultiple(t *testing.T) {
|
|||||||
{
|
{
|
||||||
expr: "true",
|
expr: "true",
|
||||||
expected: []TokenKind{TokenKindBoolean},
|
expected: []TokenKind{TokenKindBoolean},
|
||||||
values: []interface{}{true},
|
values: []any{true},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expr: "123",
|
expr: "123",
|
||||||
expected: []TokenKind{TokenKindNumber},
|
expected: []TokenKind{TokenKindNumber},
|
||||||
values: []interface{}{123.0},
|
values: []any{123.0},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expr: "(a && b)",
|
expr: "(a && b)",
|
||||||
@@ -85,7 +85,7 @@ func TestLexerMultiple(t *testing.T) {
|
|||||||
{
|
{
|
||||||
expr: "'Hello i''s escaped'",
|
expr: "'Hello i''s escaped'",
|
||||||
expected: []TokenKind{TokenKindString},
|
expected: []TokenKind{TokenKindString},
|
||||||
values: []interface{}{"Hello i's escaped"},
|
values: []any{"Hello i's escaped"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ func TestLexerMultiple(t *testing.T) {
|
|||||||
}
|
}
|
||||||
tokens = append(tokens, tok)
|
tokens = append(tokens, tok)
|
||||||
}
|
}
|
||||||
assert.Equal(t, len(tc.expected), len(tokens), "expression: %s", tc.expr)
|
assert.Len(t, tokens, len(tc.expected), "expression: %s", tc.expr)
|
||||||
for i, kind := range tc.expected {
|
for i, kind := range tc.expected {
|
||||||
assert.Equal(t, kind, tokens[i].Kind, "expr %s token %d", tc.expr, i)
|
assert.Equal(t, kind, tokens[i].Kind, "expr %s token %d", tc.expr, i)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ func TestLexer(t *testing.T) {
|
|||||||
for i, tok := range tokens {
|
for i, tok := range tokens {
|
||||||
t.Logf("Token %d: Kind=%v, Value=%v", i, tok.Kind, tok.Value)
|
t.Logf("Token %d: Kind=%v, Value=%v", i, tok.Kind, tok.Value)
|
||||||
}
|
}
|
||||||
assert.Equal(t, tokens[1].Kind, TokenKindDereference)
|
assert.Equal(t, TokenKindDereference, tokens[1].Kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLexerNumbers(t *testing.T) {
|
func TestLexerNumbers(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
in string
|
in string
|
||||||
out interface{}
|
out any
|
||||||
}{
|
}{
|
||||||
{"-Infinity", math.Inf(-1)},
|
{"-Infinity", math.Inf(-1)},
|
||||||
{"Infinity", math.Inf(1)},
|
{"Infinity", math.Inf(1)},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"maps"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// TraceWriter is an interface for logging trace information.
|
// TraceWriter is an interface for logging trace information.
|
||||||
// Implementations can write to console, file, or any other sink.
|
// Implementations can write to console, file, or any other sink.
|
||||||
type TraceWriter interface {
|
type TraceWriter interface {
|
||||||
Info(format string, args ...interface{})
|
Info(format string, args ...any)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StrategyResult holds the result of expanding a strategy.
|
// StrategyResult holds the result of expanding a strategy.
|
||||||
@@ -46,14 +46,14 @@ func (strategyContext *strategyContext) handleInclude() error {
|
|||||||
if len(strategyContext.include) > 0 {
|
if len(strategyContext.include) > 0 {
|
||||||
for _, incNode := range strategyContext.include {
|
for _, incNode := range strategyContext.include {
|
||||||
if incNode.Kind != yaml.MappingNode {
|
if incNode.Kind != yaml.MappingNode {
|
||||||
return fmt.Errorf("include entry is not a mapping node")
|
return errors.New("include entry is not a mapping node")
|
||||||
}
|
}
|
||||||
incMap := make(map[string]yaml.Node)
|
incMap := make(map[string]yaml.Node)
|
||||||
for i := 0; i < len(incNode.Content); i += 2 {
|
for i := 0; i < len(incNode.Content); i += 2 {
|
||||||
keyNode := incNode.Content[i]
|
keyNode := incNode.Content[i]
|
||||||
valNode := incNode.Content[i+1]
|
valNode := incNode.Content[i+1]
|
||||||
if keyNode.Kind != yaml.ScalarNode {
|
if keyNode.Kind != yaml.ScalarNode {
|
||||||
return fmt.Errorf("include key is not scalar")
|
return errors.New("include key is not scalar")
|
||||||
}
|
}
|
||||||
incMap[keyNode.Value] = *valNode
|
incMap[keyNode.Value] = *valNode
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ func (strategyContext *strategyContext) handleExclude() error {
|
|||||||
for _, exNode := range strategyContext.exclude {
|
for _, exNode := range strategyContext.exclude {
|
||||||
// exNode is expected to be a mapping node
|
// exNode is expected to be a mapping node
|
||||||
if exNode.Kind != yaml.MappingNode {
|
if exNode.Kind != yaml.MappingNode {
|
||||||
return fmt.Errorf("exclude entry is not a mapping node")
|
return errors.New("exclude entry is not a mapping node")
|
||||||
}
|
}
|
||||||
// Convert mapping to map[string]yaml.Node
|
// Convert mapping to map[string]yaml.Node
|
||||||
exMap := make(map[string]yaml.Node)
|
exMap := make(map[string]yaml.Node)
|
||||||
@@ -102,7 +102,7 @@ func (strategyContext *strategyContext) handleExclude() error {
|
|||||||
keyNode := exNode.Content[i]
|
keyNode := exNode.Content[i]
|
||||||
valNode := exNode.Content[i+1]
|
valNode := exNode.Content[i+1]
|
||||||
if keyNode.Kind != yaml.ScalarNode {
|
if keyNode.Kind != yaml.ScalarNode {
|
||||||
return fmt.Errorf("exclude key is not scalar")
|
return errors.New("exclude key is not scalar")
|
||||||
}
|
}
|
||||||
exMap[keyNode.Value] = *valNode
|
exMap[keyNode.Value] = *valNode
|
||||||
}
|
}
|
||||||
@@ -158,9 +158,7 @@ func ExpandStrategy(strategy *Strategy, jobTraceWriter TraceWriter) (*StrategyRe
|
|||||||
for _, row := range strategyContext.flatMatrix {
|
for _, row := range strategyContext.flatMatrix {
|
||||||
for _, val := range values {
|
for _, val := range values {
|
||||||
newRow := make(map[string]yaml.Node)
|
newRow := make(map[string]yaml.Node)
|
||||||
for k, v := range row {
|
maps.Copy(newRow, row)
|
||||||
newRow[k] = v
|
|
||||||
}
|
|
||||||
newRow[key] = val
|
newRow[key] = val
|
||||||
next = append(next, newRow)
|
next = append(next, newRow)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
type EmptyTraceWriter struct {
|
type EmptyTraceWriter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EmptyTraceWriter) Info(_ string, _ ...interface{}) {
|
func (e *EmptyTraceWriter) Info(_ string, _ ...any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStrategy(t *testing.T) {
|
func TestStrategy(t *testing.T) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package model
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
v2 "github.com/actions-oss/act-cli/internal/eval/v2"
|
v2 "gitea.com/gitea/act_runner/internal/eval/v2"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ func (a *On) UnmarshalYAML(node *yaml.Node) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *On) MarshalYAML() (interface{}, error) {
|
func (a *On) MarshalYAML() (any, error) {
|
||||||
return a.Data, nil
|
return a.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
v2 "github.com/actions-oss/act-cli/internal/eval/v2"
|
v2 "gitea.com/gitea/act_runner/internal/eval/v2"
|
||||||
"github.com/actions-oss/act-cli/internal/templateeval"
|
"gitea.com/gitea/act_runner/internal/templateeval"
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -95,7 +95,7 @@ jobs:
|
|||||||
|
|
||||||
var raw any
|
var raw any
|
||||||
err = node.Content[0].Decode(&raw)
|
err = node.Content[0].Decode(&raw)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ee.RestrictEval = true
|
ee.RestrictEval = true
|
||||||
ee.EvaluationContext.Variables = v2.CaseInsensitiveObject[any]{
|
ee.EvaluationContext.Variables = v2.CaseInsensitiveObject[any]{
|
||||||
@@ -136,6 +136,6 @@ jobs:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out, err := yaml.Marshal(&myw)
|
out, err := yaml.Marshal(&myw)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotEmpty(t, out)
|
assert.NotEmpty(t, out)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ package labels
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gotest.tools/v3/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParse(t *testing.T) {
|
func TestParse(t *testing.T) {
|
||||||
@@ -57,7 +57,7 @@ func TestParse(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.DeepEqual(t, got, tt.want)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
v2 "github.com/actions-oss/act-cli/internal/eval/v2"
|
v2 "gitea.com/gitea/act_runner/internal/eval/v2"
|
||||||
exprparser "github.com/actions-oss/act-cli/internal/expr"
|
exprparser "gitea.com/gitea/act_runner/internal/expr"
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
v2 "github.com/actions-oss/act-cli/internal/eval/v2"
|
v2 "gitea.com/gitea/act_runner/internal/eval/v2"
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRewriteSubExpression_NoExpression(t *testing.T) {
|
func TestRewriteSubExpression_NoExpression(t *testing.T) {
|
||||||
in := "Hello world"
|
in := "Hello world"
|
||||||
out, ok, err := rewriteSubExpression(in, false)
|
out, ok, err := rewriteSubExpression(in, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if ok {
|
if ok {
|
||||||
t.Fatalf("expected ok=false for no expression, got true with output %q", out)
|
t.Fatalf("expected ok=false for no expression, got true with output %q", out)
|
||||||
}
|
}
|
||||||
@@ -21,7 +22,7 @@ func TestRewriteSubExpression_NoExpression(t *testing.T) {
|
|||||||
func TestRewriteSubExpression_SingleExpression(t *testing.T) {
|
func TestRewriteSubExpression_SingleExpression(t *testing.T) {
|
||||||
in := "Hello ${{ 'world' }}"
|
in := "Hello ${{ 'world' }}"
|
||||||
out, ok, err := rewriteSubExpression(in, false)
|
out, ok, err := rewriteSubExpression(in, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("expected ok=true for single expression, got false")
|
t.Fatalf("expected ok=true for single expression, got false")
|
||||||
}
|
}
|
||||||
@@ -34,7 +35,7 @@ func TestRewriteSubExpression_SingleExpression(t *testing.T) {
|
|||||||
func TestRewriteSubExpression_MultipleExpressions(t *testing.T) {
|
func TestRewriteSubExpression_MultipleExpressions(t *testing.T) {
|
||||||
in := "Hello ${{ 'world' }}, you are ${{ 'awesome' }}"
|
in := "Hello ${{ 'world' }}, you are ${{ 'awesome' }}"
|
||||||
out, ok, err := rewriteSubExpression(in, false)
|
out, ok, err := rewriteSubExpression(in, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("expected ok=true for multiple expressions, got false")
|
t.Fatalf("expected ok=true for multiple expressions, got false")
|
||||||
}
|
}
|
||||||
@@ -47,7 +48,7 @@ func TestRewriteSubExpression_MultipleExpressions(t *testing.T) {
|
|||||||
func TestRewriteSubExpression_ForceFormatSingle(t *testing.T) {
|
func TestRewriteSubExpression_ForceFormatSingle(t *testing.T) {
|
||||||
in := "Hello ${{ 'world' }}"
|
in := "Hello ${{ 'world' }}"
|
||||||
out, ok, err := rewriteSubExpression(in, true)
|
out, ok, err := rewriteSubExpression(in, true)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("expected ok=true when forceFormat, got false")
|
t.Fatalf("expected ok=true when forceFormat, got false")
|
||||||
}
|
}
|
||||||
@@ -60,7 +61,7 @@ func TestRewriteSubExpression_ForceFormatSingle(t *testing.T) {
|
|||||||
func TestRewriteSubExpression_ForceFormatMultiple(t *testing.T) {
|
func TestRewriteSubExpression_ForceFormatMultiple(t *testing.T) {
|
||||||
in := "Hello ${{ 'world' }}, you are ${{ 'awesome' }}"
|
in := "Hello ${{ 'world' }}, you are ${{ 'awesome' }}"
|
||||||
out, ok, err := rewriteSubExpression(in, true)
|
out, ok, err := rewriteSubExpression(in, true)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("expected ok=true when forceFormat, got false")
|
t.Fatalf("expected ok=true when forceFormat, got false")
|
||||||
}
|
}
|
||||||
@@ -73,14 +74,14 @@ func TestRewriteSubExpression_ForceFormatMultiple(t *testing.T) {
|
|||||||
func TestRewriteSubExpression_UnclosedExpression(t *testing.T) {
|
func TestRewriteSubExpression_UnclosedExpression(t *testing.T) {
|
||||||
in := "Hello ${{ 'world' " // missing closing }}
|
in := "Hello ${{ 'world' " // missing closing }}
|
||||||
_, _, err := rewriteSubExpression(in, false)
|
_, _, err := rewriteSubExpression(in, false)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "unclosed expression")
|
assert.Contains(t, err.Error(), "unclosed expression")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRewriteSubExpression_UnclosedString(t *testing.T) {
|
func TestRewriteSubExpression_UnclosedString(t *testing.T) {
|
||||||
in := "Hello ${{ 'world }}, you are ${{ 'awesome' }}"
|
in := "Hello ${{ 'world }}, you are ${{ 'awesome' }}"
|
||||||
_, _, err := rewriteSubExpression(in, false)
|
_, _, err := rewriteSubExpression(in, false)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "unclosed string")
|
assert.Contains(t, err.Error(), "unclosed string")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@ func TestRewriteSubExpression_EscapedStringLiteral(t *testing.T) {
|
|||||||
// Two single quotes represent an escaped quote inside a string
|
// Two single quotes represent an escaped quote inside a string
|
||||||
in := "Hello ${{ 'It''s a test' }}"
|
in := "Hello ${{ 'It''s a test' }}"
|
||||||
out, ok, err := rewriteSubExpression(in, false)
|
out, ok, err := rewriteSubExpression(in, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
expected := "format('Hello {0}', 'It''s a test')"
|
expected := "format('Hello {0}', 'It''s a test')"
|
||||||
assert.Equal(t, expected, out)
|
assert.Equal(t, expected, out)
|
||||||
@@ -98,7 +99,7 @@ func TestRewriteSubExpression_ExpressionAtEnd(t *testing.T) {
|
|||||||
// Expression ends exactly at the string end – should be valid
|
// Expression ends exactly at the string end – should be valid
|
||||||
in := "Hello ${{ 'world' }}"
|
in := "Hello ${{ 'world' }}"
|
||||||
out, ok, err := rewriteSubExpression(in, false)
|
out, ok, err := rewriteSubExpression(in, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
expected := "format('Hello {0}', 'world')"
|
expected := "format('Hello {0}', 'world')"
|
||||||
assert.Equal(t, expected, out)
|
assert.Equal(t, expected, out)
|
||||||
@@ -108,7 +109,7 @@ func TestRewriteSubExpression_ExpressionNotAtEnd(t *testing.T) {
|
|||||||
// Expression followed by additional text – should still be valid
|
// Expression followed by additional text – should still be valid
|
||||||
in := "Hello ${{ 'world' }}, how are you?"
|
in := "Hello ${{ 'world' }}, how are you?"
|
||||||
out, ok, err := rewriteSubExpression(in, false)
|
out, ok, err := rewriteSubExpression(in, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
expected := "format('Hello {0}, how are you?', 'world')"
|
expected := "format('Hello {0}, how are you?', 'world')"
|
||||||
assert.Equal(t, expected, out)
|
assert.Equal(t, expected, out)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"github.com/timshannon/bolthold"
|
"github.com/timshannon/bolthold"
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -75,7 +75,7 @@ func StartHandler(dir, outboundIP string, port uint16, logger logrus.FieldLogger
|
|||||||
if outboundIP != "" {
|
if outboundIP != "" {
|
||||||
h.outboundIP = outboundIP
|
h.outboundIP = outboundIP
|
||||||
} else if ip := common.GetOutboundIP(); ip == nil {
|
} else if ip := common.GetOutboundIP(); ip == nil {
|
||||||
return nil, fmt.Errorf("unable to determine outbound IP address")
|
return nil, errors.New("unable to determine outbound IP address")
|
||||||
} else {
|
} else {
|
||||||
h.outboundIP = ip.String()
|
h.outboundIP = ip.String()
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ func CreateHandler(dir, externalAddress string, logger logrus.FieldLogger) (*Han
|
|||||||
if externalAddress != "" {
|
if externalAddress != "" {
|
||||||
h.externalAddress = externalAddress
|
h.externalAddress = externalAddress
|
||||||
} else if ip := common.GetOutboundIP(); ip == nil {
|
} else if ip := common.GetOutboundIP(); ip == nil {
|
||||||
return nil, nil, fmt.Errorf("unable to determine outbound IP address")
|
return nil, nil, errors.New("unable to determine outbound IP address")
|
||||||
} else {
|
} else {
|
||||||
h.outboundIP = ip.String()
|
h.outboundIP = ip.String()
|
||||||
}
|
}
|
||||||
@@ -420,7 +420,7 @@ func findCache(db *bolthold.Store, keys []string, version string) (*Cache, error
|
|||||||
}
|
}
|
||||||
return cache, nil
|
return cache, nil
|
||||||
}
|
}
|
||||||
prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix))
|
prefixPattern := "^" + regexp.QuoteMeta(prefix)
|
||||||
re, err := regexp.Compile(prefixPattern)
|
re, err := regexp.Compile(prefixPattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func TestHandler(t *testing.T) {
|
|||||||
assert.Nil(t, handler.server)
|
assert.Nil(t, handler.server)
|
||||||
assert.Nil(t, handler.listener)
|
assert.Nil(t, handler.listener)
|
||||||
_, err := http.Post(fmt.Sprintf("%s/caches/%d", base, 1), "", nil)
|
_, err := http.Post(fmt.Sprintf("%s/caches/%d", base, 1), "", nil)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ func TestHandler(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("clean", func(t *testing.T) {
|
t.Run("clean", func(t *testing.T) {
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/clean", base), "", nil)
|
resp, err := http.Post(base+"/clean", "", nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -72,7 +72,7 @@ func TestHandler(t *testing.T) {
|
|||||||
t.Run("reserve with bad request", func(t *testing.T) {
|
t.Run("reserve with bad request", func(t *testing.T) {
|
||||||
body := []byte(`invalid json`)
|
body := []byte(`invalid json`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -90,7 +90,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ func TestHandler(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("upload with bad id", func(t *testing.T) {
|
t.Run("upload with bad id", func(t *testing.T) {
|
||||||
req, err := http.NewRequest(http.MethodPatch,
|
req, err := http.NewRequest(http.MethodPatch,
|
||||||
fmt.Sprintf("%s/caches/invalid_id", base), bytes.NewReader(nil))
|
base+"/caches/invalid_id", bytes.NewReader(nil))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||||
@@ -151,7 +151,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ func TestHandler(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("commit with bad id", func(t *testing.T) {
|
t.Run("commit with bad id", func(t *testing.T) {
|
||||||
{
|
{
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches/invalid_id", base), "", nil)
|
resp, err := http.Post(base+"/caches/invalid_id", "", nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -300,7 +300,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -328,7 +328,7 @@ func TestHandler(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get with bad id", func(t *testing.T) {
|
t.Run("get with bad id", func(t *testing.T) {
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/artifacts/invalid_id", base))
|
resp, err := http.Get(base + "/artifacts/invalid_id")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 400, resp.StatusCode)
|
require.Equal(t, 400, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -537,7 +537,7 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte
|
|||||||
Size: int64(len(content)),
|
Size: int64(len(content)),
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -687,7 +687,7 @@ func TestHandler_gcCache(t *testing.T) {
|
|||||||
cache := &Cache{}
|
cache := &Cache{}
|
||||||
err = db.Get(v.Cache.ID, cache)
|
err = db.Get(v.Cache.ID, cache)
|
||||||
if v.Kept {
|
if v.Kept {
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
assert.ErrorIs(t, err, bolthold.ErrNotFound)
|
assert.ErrorIs(t, err, bolthold.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Storage struct {
|
type Storage struct {
|
||||||
@@ -103,11 +104,11 @@ func (s *Storage) Remove(id uint64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) filename(id uint64) string {
|
func (s *Storage) filename(id uint64) string {
|
||||||
return filepath.Join(s.rootDir, fmt.Sprintf("%02x", id%0xff), fmt.Sprint(id))
|
return filepath.Join(s.rootDir, fmt.Sprintf("%02x", id%0xff), strconv.FormatUint(id, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) tempDir(id uint64) string {
|
func (s *Storage) tempDir(id uint64) string {
|
||||||
return filepath.Join(s.rootDir, "tmp", fmt.Sprint(id))
|
return filepath.Join(s.rootDir, "tmp", strconv.FormatUint(id, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) tempName(id uint64, offset int64) string {
|
func (s *Storage) tempName(id uint64, offset int64) string {
|
||||||
|
|||||||
@@ -126,22 +126,22 @@ func artifactNameToID(s string) int64 {
|
|||||||
return int64(h.Sum32())
|
return int64(h.Sum32())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ArtifactContext) Error(status int, _ ...interface{}) {
|
func (c ArtifactContext) Error(status int, _ ...any) {
|
||||||
c.Resp.WriteHeader(status)
|
c.Resp.WriteHeader(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ArtifactContext) JSON(status int, _ ...interface{}) {
|
func (c ArtifactContext) JSON(status int, _ ...any) {
|
||||||
c.Resp.WriteHeader(status)
|
c.Resp.WriteHeader(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateRunIDV4(ctx *ArtifactContext, rawRunID string) (interface{}, int64, bool) {
|
func validateRunIDV4(ctx *ArtifactContext, rawRunID string) (int64, bool) {
|
||||||
runID, err := strconv.ParseInt(rawRunID, 10, 64)
|
runID, err := strconv.ParseInt(rawRunID, 10, 64)
|
||||||
if err != nil /* || task.Job.RunID != runID*/ {
|
if err != nil /* || task.Job.RunID != runID*/ {
|
||||||
log.Error("Error runID not match")
|
log.Error("Error runID not match")
|
||||||
ctx.Error(http.StatusBadRequest, "run-id does not match")
|
ctx.Error(http.StatusBadRequest, "run-id does not match")
|
||||||
return nil, 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return nil, runID, true
|
return runID, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func RoutesV4(router *httprouter.Router, baseDir string, fsys WriteFS, rfs fs.FS) {
|
func RoutesV4(router *httprouter.Router, baseDir string, fsys WriteFS, rfs fs.FS) {
|
||||||
@@ -210,7 +210,7 @@ func (r artifactV4Routes) buildSignature(endp, expires, artifactName string, tas
|
|||||||
func (r artifactV4Routes) buildArtifactURL(endp, artifactName string, taskID int64) string {
|
func (r artifactV4Routes) buildArtifactURL(endp, artifactName string, taskID int64) string {
|
||||||
expires := time.Now().Add(60 * time.Minute).Format("2006-01-02 15:04:05.999999999 -0700 MST")
|
expires := time.Now().Add(60 * time.Minute).Format("2006-01-02 15:04:05.999999999 -0700 MST")
|
||||||
uploadURL := "http://" + strings.TrimSuffix(r.AppURL, "/") + strings.TrimSuffix(r.prefix, "/") +
|
uploadURL := "http://" + strings.TrimSuffix(r.AppURL, "/") + strings.TrimSuffix(r.prefix, "/") +
|
||||||
"/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + fmt.Sprint(taskID)
|
"/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + strconv.FormatInt(taskID, 10)
|
||||||
return uploadURL
|
return uploadURL
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,14 +271,14 @@ func (r *artifactV4Routes) createArtifact(ctx *ArtifactContext) {
|
|||||||
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
artifactName := req.Name
|
artifactName := req.Name
|
||||||
|
|
||||||
safeRunPath := safeResolve(r.baseDir, fmt.Sprint(runID))
|
safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10))
|
||||||
safePath := safeResolve(safeRunPath, artifactName)
|
safePath := safeResolve(safeRunPath, artifactName)
|
||||||
safePath = safeResolve(safePath, artifactName+".zip")
|
safePath = safeResolve(safePath, artifactName+".zip")
|
||||||
file, err := r.fs.OpenWritable(safePath)
|
file, err := r.fs.OpenWritable(safePath)
|
||||||
@@ -305,7 +305,7 @@ func (r *artifactV4Routes) uploadArtifact(ctx *ArtifactContext) {
|
|||||||
switch comp {
|
switch comp {
|
||||||
case "block", "appendBlock":
|
case "block", "appendBlock":
|
||||||
|
|
||||||
safeRunPath := safeResolve(r.baseDir, fmt.Sprint(task))
|
safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(task, 10))
|
||||||
safePath := safeResolve(safeRunPath, artifactName)
|
safePath := safeResolve(safeRunPath, artifactName)
|
||||||
safePath = safeResolve(safePath, artifactName+".zip")
|
safePath = safeResolve(safePath, artifactName+".zip")
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
|
|||||||
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, _, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
_, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -360,12 +360,12 @@ func (r *artifactV4Routes) listArtifacts(ctx *ArtifactContext) {
|
|||||||
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
safePath := safeResolve(r.baseDir, fmt.Sprint(runID))
|
safePath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10))
|
||||||
|
|
||||||
entries, err := fs.ReadDir(r.rfs, safePath)
|
entries, err := fs.ReadDir(r.rfs, safePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -405,7 +405,7 @@ func (r *artifactV4Routes) getSignedArtifactURL(ctx *ArtifactContext) {
|
|||||||
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -424,7 +424,7 @@ func (r *artifactV4Routes) downloadArtifact(ctx *ArtifactContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
safeRunPath := safeResolve(r.baseDir, fmt.Sprint(task))
|
safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(task, 10))
|
||||||
safePath := safeResolve(safeRunPath, artifactName)
|
safePath := safeResolve(safeRunPath, artifactName)
|
||||||
safePath = safeResolve(safePath, artifactName+".zip")
|
safePath = safeResolve(safePath, artifactName+".zip")
|
||||||
|
|
||||||
@@ -439,11 +439,11 @@ func (r *artifactV4Routes) deleteArtifact(ctx *ArtifactContext) {
|
|||||||
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
if ok := r.parseProtbufBody(ctx, &req); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
safeRunPath := safeResolve(r.baseDir, fmt.Sprint(runID))
|
safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10))
|
||||||
safePath := safeResolve(safeRunPath, req.Name)
|
safePath := safeResolve(safeRunPath, req.Name)
|
||||||
|
|
||||||
_ = os.RemoveAll(safePath)
|
_ = os.RemoveAll(safePath)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileContainerResourceURL struct {
|
type FileContainerResourceURL struct {
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ import (
|
|||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/actions-oss/act-cli/pkg/runner"
|
"gitea.com/gitea/act_runner/pkg/runner"
|
||||||
)
|
)
|
||||||
|
|
||||||
type writableMapFile struct {
|
type writableMapFile struct {
|
||||||
@@ -68,7 +69,7 @@ func TestNewArtifactUploadPrepare(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
||||||
|
|
||||||
req, _ := http.NewRequest("POST", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
req, _ := http.NewRequest(http.MethodPost, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -94,7 +95,7 @@ func TestArtifactUploadBlob(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
||||||
|
|
||||||
req, _ := http.NewRequest("PUT", "http://localhost/upload/1?itemPath=some/file", strings.NewReader("content"))
|
req, _ := http.NewRequest(http.MethodPut, "http://localhost/upload/1?itemPath=some/file", strings.NewReader("content"))
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -121,7 +122,7 @@ func TestFinalizeArtifactUpload(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
||||||
|
|
||||||
req, _ := http.NewRequest("PATCH", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
req, _ := http.NewRequest(http.MethodPatch, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -151,7 +152,7 @@ func TestListArtifacts(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
downloads(router, "artifact/server/path", memfs)
|
downloads(router, "artifact/server/path", memfs)
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
req, _ := http.NewRequest(http.MethodGet, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -183,7 +184,7 @@ func TestListArtifactContainer(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
downloads(router, "artifact/server/path", memfs)
|
downloads(router, "artifact/server/path", memfs)
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "http://localhost/download/1?itemPath=some/file", nil)
|
req, _ := http.NewRequest(http.MethodGet, "http://localhost/download/1?itemPath=some/file", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -198,7 +199,7 @@ func TestListArtifactContainer(t *testing.T) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(1, len(response.Value))
|
assert.Len(response.Value, 1)
|
||||||
assert.Equal("some/file", response.Value[0].Path)
|
assert.Equal("some/file", response.Value[0].Path)
|
||||||
assert.Equal("file", response.Value[0].ItemType)
|
assert.Equal("file", response.Value[0].ItemType)
|
||||||
assert.Equal("http://localhost/artifact/1/some/file/.", response.Value[0].ContentLocation)
|
assert.Equal("http://localhost/artifact/1/some/file/.", response.Value[0].ContentLocation)
|
||||||
@@ -216,7 +217,7 @@ func TestDownloadArtifactFile(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
downloads(router, "artifact/server/path", memfs)
|
downloads(router, "artifact/server/path", memfs)
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "http://localhost/artifact/1/some/file", nil)
|
req, _ := http.NewRequest(http.MethodGet, "http://localhost/artifact/1/some/file", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -276,14 +277,14 @@ func TestArtifactFlow(t *testing.T) {
|
|||||||
|
|
||||||
func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
|
func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
|
||||||
t.Run(tjfi.workflowPath, func(t *testing.T) {
|
t.Run(tjfi.workflowPath, func(t *testing.T) {
|
||||||
fmt.Printf("::group::%s\n", tjfi.workflowPath)
|
t.Logf("::group::%s\n", tjfi.workflowPath)
|
||||||
|
|
||||||
if err := os.RemoveAll(artifactsPath); err != nil {
|
if err := os.RemoveAll(artifactsPath); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
workdir, err := filepath.Abs(tjfi.workdir)
|
workdir, err := filepath.Abs(tjfi.workdir)
|
||||||
assert.Nil(t, err, workdir)
|
require.NoError(t, err, workdir)
|
||||||
fullWorkflowPath := filepath.Join(workdir, tjfi.workflowPath)
|
fullWorkflowPath := filepath.Join(workdir, tjfi.workflowPath)
|
||||||
runnerConfig := &runner.Config{
|
runnerConfig := &runner.Config{
|
||||||
Workdir: workdir,
|
Workdir: workdir,
|
||||||
@@ -299,24 +300,24 @@ func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
runner, err := runner.New(runnerConfig)
|
runner, err := runner.New(runnerConfig)
|
||||||
assert.Nil(t, err, tjfi.workflowPath)
|
require.NoError(t, err, tjfi.workflowPath)
|
||||||
|
|
||||||
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, model.PlannerConfig{})
|
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, model.PlannerConfig{})
|
||||||
assert.Nil(t, err, fullWorkflowPath)
|
require.NoError(t, err, fullWorkflowPath)
|
||||||
|
|
||||||
plan, err := planner.PlanEvent(tjfi.eventName)
|
plan, err := planner.PlanEvent(tjfi.eventName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = runner.NewPlanExecutor(plan)(ctx)
|
err = runner.NewPlanExecutor(plan)(ctx)
|
||||||
if tjfi.errorMessage == "" {
|
if tjfi.errorMessage == "" {
|
||||||
assert.Nil(t, err, fullWorkflowPath)
|
require.NoError(t, err, fullWorkflowPath)
|
||||||
} else {
|
} else {
|
||||||
assert.Error(t, err, tjfi.errorMessage)
|
require.Error(t, err, tjfi.errorMessage)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert.Nil(t, plan)
|
assert.Nil(t, plan)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("::endgroup::")
|
t.Log("::endgroup::")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,7 +357,7 @@ func TestDownloadArtifactFileUnsafePath(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
downloads(router, "artifact/server/path", memfs)
|
downloads(router, "artifact/server/path", memfs)
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "http://localhost/artifact/2/../../some/file", nil)
|
req, _ := http.NewRequest(http.MethodGet, "http://localhost/artifact/2/../../some/file", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -378,7 +379,7 @@ func TestArtifactUploadBlobUnsafePath(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
||||||
|
|
||||||
req, _ := http.NewRequest("PUT", "http://localhost/upload/1?itemPath=../../some/file", strings.NewReader("content"))
|
req, _ := http.NewRequest(http.MethodPut, "http://localhost/upload/1?itemPath=../../some/file", strings.NewReader("content"))
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -78,7 +79,7 @@ func ParseAuthorizationToken(req *http.Request) (int64, error) {
|
|||||||
parts := strings.SplitN(h, " ", 2)
|
parts := strings.SplitN(h, " ", 2)
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
log.Errorf("split token failed: %s", h)
|
log.Errorf("split token failed: %s", h)
|
||||||
return 0, fmt.Errorf("split token failed")
|
return 0, errors.New("split token failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := jwt.ParseWithClaims(parts[1], &actionsClaims{}, func(t *jwt.Token) (any, error) {
|
token, err := jwt.ParseWithClaims(parts[1], &actionsClaims{}, func(t *jwt.Token) (any, error) {
|
||||||
@@ -93,7 +94,7 @@ func ParseAuthorizationToken(req *http.Request) (int64, error) {
|
|||||||
|
|
||||||
c, ok := token.Claims.(*actionsClaims)
|
c, ok := token.Claims.(*actionsClaims)
|
||||||
if !token.Valid || !ok {
|
if !token.Valid || !ok {
|
||||||
return 0, fmt.Errorf("invalid token claim")
|
return 0, errors.New("invalid token claim")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.TaskID, nil
|
return c.TaskID, nil
|
||||||
|
|||||||
@@ -10,18 +10,19 @@ import (
|
|||||||
|
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateAuthorizationToken(t *testing.T) {
|
func TestCreateAuthorizationToken(t *testing.T) {
|
||||||
var taskID int64 = 23
|
var taskID int64 = 23
|
||||||
token, err := CreateAuthorizationToken(taskID, 1, 2)
|
token, err := CreateAuthorizationToken(taskID, 1, 2)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotEqual(t, "", token)
|
assert.NotEmpty(t, token)
|
||||||
claims := jwt.MapClaims{}
|
claims := jwt.MapClaims{}
|
||||||
_, err = jwt.ParseWithClaims(token, claims, func(_ *jwt.Token) (interface{}, error) {
|
_, err = jwt.ParseWithClaims(token, claims, func(_ *jwt.Token) (any, error) {
|
||||||
return []byte{}, nil
|
return []byte{}, nil
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
scp, ok := claims["scp"]
|
scp, ok := claims["scp"]
|
||||||
assert.True(t, ok, "Has scp claim in jwt token")
|
assert.True(t, ok, "Has scp claim in jwt token")
|
||||||
assert.Contains(t, scp, "Actions.Results:1:2")
|
assert.Contains(t, scp, "Actions.Results:1:2")
|
||||||
@@ -34,21 +35,21 @@ func TestCreateAuthorizationToken(t *testing.T) {
|
|||||||
assert.True(t, ok, "ac claim is a string for buildx gha cache")
|
assert.True(t, ok, "ac claim is a string for buildx gha cache")
|
||||||
scopes := []actionsCacheScope{}
|
scopes := []actionsCacheScope{}
|
||||||
err = json.Unmarshal([]byte(ac), &scopes)
|
err = json.Unmarshal([]byte(ac), &scopes)
|
||||||
assert.NoError(t, err, "ac claim is a json list for buildx gha cache")
|
require.NoError(t, err, "ac claim is a json list for buildx gha cache")
|
||||||
assert.GreaterOrEqual(t, len(scopes), 1, "Expected at least one action cache scope for buildx gha cache")
|
assert.GreaterOrEqual(t, len(scopes), 1, "Expected at least one action cache scope for buildx gha cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseAuthorizationToken(t *testing.T) {
|
func TestParseAuthorizationToken(t *testing.T) {
|
||||||
var taskID int64 = 23
|
var taskID int64 = 23
|
||||||
token, err := CreateAuthorizationToken(taskID, 1, 2)
|
token, err := CreateAuthorizationToken(taskID, 1, 2)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotEqual(t, "", token)
|
assert.NotEmpty(t, token)
|
||||||
headers := http.Header{}
|
headers := http.Header{}
|
||||||
headers.Set("Authorization", "Bearer "+token)
|
headers.Set("Authorization", "Bearer "+token)
|
||||||
rTaskID, err := ParseAuthorizationToken(&http.Request{
|
rTaskID, err := ParseAuthorizationToken(&http.Request{
|
||||||
Header: headers,
|
Header: headers,
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, taskID, rTaskID)
|
assert.Equal(t, taskID, rTaskID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +58,6 @@ func TestParseAuthorizationTokenNoAuthHeader(t *testing.T) {
|
|||||||
rTaskID, err := ParseAuthorizationToken(&http.Request{
|
rTaskID, err := ParseAuthorizationToken(&http.Request{
|
||||||
Header: headers,
|
Header: headers,
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(0), rTaskID)
|
assert.Equal(t, int64(0), rTaskID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
// CartesianProduct takes map of lists and returns list of unique tuples
|
// CartesianProduct takes map of lists and returns list of unique tuples
|
||||||
func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interface{} {
|
func CartesianProduct(mapOfLists map[string][]any) []map[string]any {
|
||||||
listNames := make([]string, 0)
|
listNames := make([]string, 0)
|
||||||
lists := make([][]interface{}, 0)
|
lists := make([][]any, 0)
|
||||||
for k, v := range mapOfLists {
|
for k, v := range mapOfLists {
|
||||||
listNames = append(listNames, k)
|
listNames = append(listNames, k)
|
||||||
lists = append(lists, v)
|
lists = append(lists, v)
|
||||||
@@ -11,9 +11,9 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac
|
|||||||
|
|
||||||
listCart := cartN(lists...)
|
listCart := cartN(lists...)
|
||||||
|
|
||||||
rtn := make([]map[string]interface{}, 0)
|
rtn := make([]map[string]any, 0)
|
||||||
for _, list := range listCart {
|
for _, list := range listCart {
|
||||||
vMap := make(map[string]interface{})
|
vMap := make(map[string]any)
|
||||||
for i, v := range list {
|
for i, v := range list {
|
||||||
vMap[listNames[i]] = v
|
vMap[listNames[i]] = v
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac
|
|||||||
return rtn
|
return rtn
|
||||||
}
|
}
|
||||||
|
|
||||||
func cartN(a ...[]interface{}) [][]interface{} {
|
func cartN(a ...[]any) [][]any {
|
||||||
c := 1
|
c := 1
|
||||||
for _, a := range a {
|
for _, a := range a {
|
||||||
c *= len(a)
|
c *= len(a)
|
||||||
@@ -30,8 +30,8 @@ func cartN(a ...[]interface{}) [][]interface{} {
|
|||||||
if c == 0 || len(a) == 0 {
|
if c == 0 || len(a) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
p := make([][]interface{}, c)
|
p := make([][]any, c)
|
||||||
b := make([]interface{}, c*len(a))
|
b := make([]any, c*len(a))
|
||||||
n := make([]int, len(a))
|
n := make([]int, len(a))
|
||||||
s := 0
|
s := 0
|
||||||
for i := range p {
|
for i := range p {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
func TestCartesianProduct(t *testing.T) {
|
func TestCartesianProduct(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
input := map[string][]interface{}{
|
input := map[string][]any{
|
||||||
"foo": {1, 2, 3, 4},
|
"foo": {1, 2, 3, 4},
|
||||||
"bar": {"a", "b", "c"},
|
"bar": {"a", "b", "c"},
|
||||||
"baz": {false, true},
|
"baz": {false, true},
|
||||||
@@ -25,15 +25,15 @@ func TestCartesianProduct(t *testing.T) {
|
|||||||
assert.Contains(v, "baz")
|
assert.Contains(v, "baz")
|
||||||
}
|
}
|
||||||
|
|
||||||
input = map[string][]interface{}{
|
input = map[string][]any{
|
||||||
"foo": {1, 2, 3, 4},
|
"foo": {1, 2, 3, 4},
|
||||||
"bar": {},
|
"bar": {},
|
||||||
"baz": {false, true},
|
"baz": {false, true},
|
||||||
}
|
}
|
||||||
output = CartesianProduct(input)
|
output = CartesianProduct(input)
|
||||||
assert.Len(output, 0)
|
assert.Empty(output)
|
||||||
|
|
||||||
input = map[string][]interface{}{}
|
input = map[string][]any{}
|
||||||
output = CartesianProduct(input)
|
output = CartesianProduct(input)
|
||||||
assert.Len(output, 0)
|
assert.Empty(output)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGracefulJobCancellationViaSigint(t *testing.T) {
|
func TestGracefulJobCancellationViaSigint(t *testing.T) {
|
||||||
@@ -18,8 +19,8 @@ func TestGracefulJobCancellationViaSigint(t *testing.T) {
|
|||||||
assert.NotNil(t, channel)
|
assert.NotNil(t, channel)
|
||||||
cancelCtx := JobCancelContext(ctx)
|
cancelCtx := JobCancelContext(ctx)
|
||||||
assert.NotNil(t, cancelCtx)
|
assert.NotNil(t, cancelCtx)
|
||||||
assert.NoError(t, ctx.Err())
|
require.NoError(t, ctx.Err())
|
||||||
assert.NoError(t, cancelCtx.Err())
|
require.NoError(t, cancelCtx.Err())
|
||||||
channel <- os.Interrupt
|
channel <- os.Interrupt
|
||||||
select {
|
select {
|
||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1 * time.Second):
|
||||||
@@ -30,7 +31,7 @@ func TestGracefulJobCancellationViaSigint(t *testing.T) {
|
|||||||
if assert.Error(t, cancelCtx.Err(), "context canceled") {
|
if assert.Error(t, cancelCtx.Err(), "context canceled") {
|
||||||
assert.Equal(t, context.Canceled, cancelCtx.Err())
|
assert.Equal(t, context.Canceled, cancelCtx.Err())
|
||||||
}
|
}
|
||||||
assert.NoError(t, ctx.Err())
|
require.NoError(t, ctx.Err())
|
||||||
channel <- os.Interrupt
|
channel <- os.Interrupt
|
||||||
select {
|
select {
|
||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1 * time.Second):
|
||||||
@@ -50,8 +51,8 @@ func TestForceCancellationViaSigterm(t *testing.T) {
|
|||||||
assert.NotNil(t, channel)
|
assert.NotNil(t, channel)
|
||||||
cancelCtx := JobCancelContext(ctx)
|
cancelCtx := JobCancelContext(ctx)
|
||||||
assert.NotNil(t, cancelCtx)
|
assert.NotNil(t, cancelCtx)
|
||||||
assert.NoError(t, ctx.Err())
|
require.NoError(t, ctx.Err())
|
||||||
assert.NoError(t, cancelCtx.Err())
|
require.NoError(t, cancelCtx.Err())
|
||||||
channel <- syscall.SIGTERM
|
channel <- syscall.SIGTERM
|
||||||
select {
|
select {
|
||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1 * time.Second):
|
||||||
@@ -78,7 +79,7 @@ func TestCreateGracefulJobCancellationContext(t *testing.T) {
|
|||||||
assert.NotNil(t, cancel)
|
assert.NotNil(t, cancel)
|
||||||
cancelCtx := JobCancelContext(ctx)
|
cancelCtx := JobCancelContext(ctx)
|
||||||
assert.NotNil(t, cancelCtx)
|
assert.NotNil(t, cancelCtx)
|
||||||
assert.NoError(t, cancelCtx.Err())
|
require.NoError(t, cancelCtx.Err())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateGracefulJobCancellationContextCancelFunc(t *testing.T) {
|
func TestCreateGracefulJobCancellationContextCancelFunc(t *testing.T) {
|
||||||
@@ -87,7 +88,7 @@ func TestCreateGracefulJobCancellationContextCancelFunc(t *testing.T) {
|
|||||||
assert.NotNil(t, cancel)
|
assert.NotNil(t, cancel)
|
||||||
cancelCtx := JobCancelContext(ctx)
|
cancelCtx := JobCancelContext(ctx)
|
||||||
assert.NotNil(t, cancelCtx)
|
assert.NotNil(t, cancelCtx)
|
||||||
assert.NoError(t, cancelCtx.Err())
|
require.NoError(t, cancelCtx.Err())
|
||||||
cancel()
|
cancel()
|
||||||
if assert.Error(t, ctx.Err(), "context canceled") {
|
if assert.Error(t, ctx.Err(), "context canceled") {
|
||||||
assert.Equal(t, context.Canceled, ctx.Err())
|
assert.Equal(t, context.Canceled, ctx.Err())
|
||||||
|
|||||||
@@ -125,11 +125,8 @@ func (p *Pen) DrawBoxes(labels ...string) *Drawing {
|
|||||||
|
|
||||||
// Draw to writer
|
// Draw to writer
|
||||||
func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) {
|
func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) {
|
||||||
padSize := (centerOnWidth - d.GetWidth()) / 2
|
padSize := max((centerOnWidth-d.GetWidth())/2, 0)
|
||||||
if padSize < 0 {
|
for l := range strings.SplitSeq(d.buf.String(), "\n") {
|
||||||
padSize = 0
|
|
||||||
}
|
|
||||||
for _, l := range strings.Split(d.buf.String(), "\n") {
|
|
||||||
if len(l) > 0 {
|
if len(l) > 0 {
|
||||||
padding := strings.Repeat(" ", padSize)
|
padding := strings.Repeat(" ", padSize)
|
||||||
fmt.Fprintf(writer, "%s%s\n", padding, l)
|
fmt.Fprintf(writer, "%s%s\n", padding, l)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (w Warning) Error() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Warningf create a warning
|
// Warningf create a warning
|
||||||
func Warningf(format string, args ...interface{}) Warning {
|
func Warningf(format string, args ...any) Warning {
|
||||||
w := Warning{
|
w := Warning{
|
||||||
Message: fmt.Sprintf(format, args...),
|
Message: fmt.Sprintf(format, args...),
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ type Executor func(ctx context.Context) error
|
|||||||
type Conditional func(ctx context.Context) bool
|
type Conditional func(ctx context.Context) bool
|
||||||
|
|
||||||
// NewInfoExecutor is an executor that logs messages
|
// NewInfoExecutor is an executor that logs messages
|
||||||
func NewInfoExecutor(format string, args ...interface{}) Executor {
|
func NewInfoExecutor(format string, args ...any) Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
logger := Logger(ctx)
|
logger := Logger(ctx)
|
||||||
logger.Infof(format, args...)
|
logger.Infof(format, args...)
|
||||||
@@ -42,7 +42,7 @@ func NewInfoExecutor(format string, args ...interface{}) Executor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewDebugExecutor is an executor that logs messages
|
// NewDebugExecutor is an executor that logs messages
|
||||||
func NewDebugExecutor(format string, args ...interface{}) Executor {
|
func NewDebugExecutor(format string, args ...any) Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
logger := Logger(ctx)
|
logger := Logger(ctx)
|
||||||
logger.Debugf(format, args...)
|
logger.Debugf(format, args...)
|
||||||
@@ -110,14 +110,14 @@ func NewParallelExecutor(parallel int, executors ...Executor) Executor {
|
|||||||
}(work, errs)
|
}(work, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(executors); i++ {
|
for i := range executors {
|
||||||
work <- executors[i]
|
work <- executors[i]
|
||||||
}
|
}
|
||||||
close(work)
|
close(work)
|
||||||
|
|
||||||
// Executor waits all executors to cleanup these resources.
|
// Executor waits all executors to cleanup these resources.
|
||||||
var firstErr error
|
var firstErr error
|
||||||
for i := 0; i < len(executors); i++ {
|
for range executors {
|
||||||
err := <-errs
|
err := <-errs
|
||||||
if firstErr == nil {
|
if firstErr == nil {
|
||||||
firstErr = err
|
firstErr = err
|
||||||
@@ -131,7 +131,7 @@ func NewParallelExecutor(parallel int, executors ...Executor) Executor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFieldExecutor(name string, value interface{}, exec Executor) Executor {
|
func NewFieldExecutor(name string, value any, exec Executor) Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
return exec(WithLogger(ctx, Logger(ctx).WithField(name, value)))
|
return exec(WithLogger(ctx, Logger(ctx).WithField(name, value)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewWorkflow(t *testing.T) {
|
func TestNewWorkflow(t *testing.T) {
|
||||||
@@ -16,11 +17,11 @@ func TestNewWorkflow(t *testing.T) {
|
|||||||
|
|
||||||
// empty
|
// empty
|
||||||
emptyWorkflow := NewPipelineExecutor()
|
emptyWorkflow := NewPipelineExecutor()
|
||||||
assert.Nil(emptyWorkflow(ctx))
|
require.NoError(t, emptyWorkflow(ctx))
|
||||||
|
|
||||||
// error case
|
// error case
|
||||||
errorWorkflow := NewErrorExecutor(fmt.Errorf("test error"))
|
errorWorkflow := NewErrorExecutor(errors.New("test error"))
|
||||||
assert.NotNil(errorWorkflow(ctx))
|
require.Error(t, errorWorkflow(ctx))
|
||||||
|
|
||||||
// multiple success case
|
// multiple success case
|
||||||
runcount := 0
|
runcount := 0
|
||||||
@@ -33,7 +34,7 @@ func TestNewWorkflow(t *testing.T) {
|
|||||||
runcount++
|
runcount++
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
assert.Nil(successWorkflow(ctx))
|
require.NoError(t, successWorkflow(ctx))
|
||||||
assert.Equal(2, runcount)
|
assert.Equal(2, runcount)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ func TestNewConditionalExecutor(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
})(ctx)
|
})(ctx)
|
||||||
|
|
||||||
assert.Nil(err)
|
require.NoError(t, err)
|
||||||
assert.Equal(0, trueCount)
|
assert.Equal(0, trueCount)
|
||||||
assert.Equal(1, falseCount)
|
assert.Equal(1, falseCount)
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ func TestNewConditionalExecutor(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
})(ctx)
|
})(ctx)
|
||||||
|
|
||||||
assert.Nil(err)
|
require.NoError(t, err)
|
||||||
assert.Equal(1, trueCount)
|
assert.Equal(1, trueCount)
|
||||||
assert.Equal(1, falseCount)
|
assert.Equal(1, falseCount)
|
||||||
}
|
}
|
||||||
@@ -99,7 +100,7 @@ func TestNewParallelExecutor(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(3, count, "should run all 3 executors")
|
assert.Equal(3, count, "should run all 3 executors")
|
||||||
assert.Equal(2, maxCount, "should run at most 2 executors in parallel")
|
assert.Equal(2, maxCount, "should run at most 2 executors in parallel")
|
||||||
assert.Nil(err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Reset to test running the executor with 0 parallelism
|
// Reset to test running the executor with 0 parallelism
|
||||||
count = 0
|
count = 0
|
||||||
@@ -110,7 +111,7 @@ func TestNewParallelExecutor(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(3, count, "should run all 3 executors")
|
assert.Equal(3, count, "should run all 3 executors")
|
||||||
assert.Equal(1, maxCount, "should run at most 1 executors in parallel")
|
assert.Equal(1, maxCount, "should run at most 1 executors in parallel")
|
||||||
assert.Nil(errSingle)
|
require.NoError(t, errSingle)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewParallelExecutorFailed(t *testing.T) {
|
func TestNewParallelExecutorFailed(t *testing.T) {
|
||||||
@@ -122,7 +123,7 @@ func TestNewParallelExecutorFailed(t *testing.T) {
|
|||||||
count := 0
|
count := 0
|
||||||
errorWorkflow := NewPipelineExecutor(func(_ context.Context) error {
|
errorWorkflow := NewPipelineExecutor(func(_ context.Context) error {
|
||||||
count++
|
count++
|
||||||
return fmt.Errorf("fake error")
|
return errors.New("fake error")
|
||||||
})
|
})
|
||||||
err := NewParallelExecutor(1, errorWorkflow)(ctx)
|
err := NewParallelExecutor(1, errorWorkflow)(ctx)
|
||||||
assert.Equal(1, count)
|
assert.Equal(1, count)
|
||||||
@@ -135,7 +136,7 @@ func TestNewParallelExecutorCanceled(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
errExpected := fmt.Errorf("fake error")
|
errExpected := errors.New("fake error")
|
||||||
|
|
||||||
count := 0
|
count := 0
|
||||||
successWorkflow := NewPipelineExecutor(func(_ context.Context) error {
|
successWorkflow := NewPipelineExecutor(func(_ context.Context) error {
|
||||||
@@ -148,5 +149,5 @@ func TestNewParallelExecutorCanceled(t *testing.T) {
|
|||||||
})
|
})
|
||||||
err := NewParallelExecutor(3, errorWorkflow, successWorkflow, successWorkflow)(ctx)
|
err := NewParallelExecutor(3, errorWorkflow, successWorkflow, successWorkflow)(ctx)
|
||||||
assert.Equal(3, count)
|
assert.Equal(3, count)
|
||||||
assert.Error(errExpected, err)
|
assert.ErrorIs(errExpected, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -74,7 +74,7 @@ func FindGitRevision(ctx context.Context, file string) (shortSha string, sha str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if head.Hash().IsZero() {
|
if head.Hash().IsZero() {
|
||||||
return "", "", fmt.Errorf("head sha1 could not be resolved")
|
return "", "", errors.New("head sha1 could not be resolved")
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := head.Hash().String()
|
hash := head.Hash().String()
|
||||||
@@ -319,7 +319,7 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor {
|
|||||||
cloneLock.Lock()
|
cloneLock.Lock()
|
||||||
defer cloneLock.Unlock()
|
defer cloneLock.Unlock()
|
||||||
|
|
||||||
refName := plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", input.Ref))
|
refName := plumbing.ReferenceName("refs/heads/" + input.Ref)
|
||||||
r, err := CloneIfRequired(ctx, refName, input, logger)
|
r, err := CloneIfRequired(ctx, refName, input, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFindGitSlug(t *testing.T) {
|
func TestFindGitSlug(t *testing.T) {
|
||||||
@@ -40,7 +40,7 @@ func TestFindGitSlug(t *testing.T) {
|
|||||||
for _, tt := range slugTests {
|
for _, tt := range slugTests {
|
||||||
provider, slug, err := findGitSlug(tt.url, "github.com")
|
provider, slug, err := findGitSlug(tt.url, "github.com")
|
||||||
|
|
||||||
assert.NoError(err)
|
require.NoError(t, err)
|
||||||
assert.Equal(tt.provider, provider)
|
assert.Equal(tt.provider, provider)
|
||||||
assert.Equal(tt.slug, slug)
|
assert.Equal(tt.slug, slug)
|
||||||
}
|
}
|
||||||
@@ -80,23 +80,23 @@ func TestFindGitRemoteURL(t *testing.T) {
|
|||||||
basedir := testDir(t)
|
basedir := testDir(t)
|
||||||
gitConfig()
|
gitConfig()
|
||||||
err := gitCmd("init", basedir)
|
err := gitCmd("init", basedir)
|
||||||
assert.NoError(err)
|
require.NoError(t, err)
|
||||||
err = cleanGitHooks(basedir)
|
err = cleanGitHooks(basedir)
|
||||||
assert.NoError(err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
remoteURL := "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name"
|
remoteURL := "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name"
|
||||||
err = gitCmd("-C", basedir, "remote", "add", "origin", remoteURL)
|
err = gitCmd("-C", basedir, "remote", "add", "origin", remoteURL)
|
||||||
assert.NoError(err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
u, err := findGitRemoteURL(context.Background(), basedir, "origin")
|
u, err := findGitRemoteURL(context.Background(), basedir, "origin")
|
||||||
assert.NoError(err)
|
require.NoError(t, err)
|
||||||
assert.Equal(remoteURL, u)
|
assert.Equal(remoteURL, u)
|
||||||
|
|
||||||
remoteURL = "git@github.com/AwesomeOwner/MyAwesomeRepo.git"
|
remoteURL = "git@github.com/AwesomeOwner/MyAwesomeRepo.git"
|
||||||
err = gitCmd("-C", basedir, "remote", "add", "upstream", remoteURL)
|
err = gitCmd("-C", basedir, "remote", "add", "upstream", remoteURL)
|
||||||
assert.NoError(err)
|
require.NoError(t, err)
|
||||||
u, err = findGitRemoteURL(context.Background(), basedir, "upstream")
|
u, err = findGitRemoteURL(context.Background(), basedir, "upstream")
|
||||||
assert.NoError(err)
|
require.NoError(t, err)
|
||||||
assert.Equal(remoteURL, u)
|
assert.Equal(remoteURL, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,10 +213,10 @@ func TestGitCloneExecutor(t *testing.T) {
|
|||||||
|
|
||||||
err := clone(context.Background())
|
err := clone(context.Background())
|
||||||
if tt.Err != nil {
|
if tt.Err != nil {
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, tt.Err, err)
|
assert.Equal(t, tt.Err, err)
|
||||||
} else {
|
} else {
|
||||||
assert.Empty(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -258,7 +258,7 @@ func TestCloneIfRequired(t *testing.T) {
|
|||||||
URL: "https://github.com/actions/checkout",
|
URL: "https://github.com/actions/checkout",
|
||||||
Dir: tempDir,
|
Dir: tempDir,
|
||||||
}, common.Logger(ctx))
|
}, common.Logger(ctx))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, repo)
|
assert.NotNil(t, repo)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLineWriter(t *testing.T) {
|
func TestLineWriter(t *testing.T) {
|
||||||
@@ -18,7 +19,7 @@ func TestLineWriter(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
write := func(s string) {
|
write := func(s string) {
|
||||||
n, err := lineWriter.Write([]byte(s))
|
n, err := lineWriter.Write([]byte(s))
|
||||||
assert.NoError(err)
|
require.NoError(t, err)
|
||||||
assert.Equal(len(s), n, s)
|
assert.Equal(len(s), n, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/docker/cli/cli/config"
|
"github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/cli/cli/config/credentials"
|
"github.com/docker/cli/cli/config/credentials"
|
||||||
"github.com/docker/docker/api/types/registry"
|
"github.com/docker/docker/api/types/registry"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
"github.com/moby/patternmatcher"
|
"github.com/moby/patternmatcher"
|
||||||
"github.com/moby/patternmatcher/ignorefile"
|
"github.com/moby/patternmatcher/ignorefile"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDockerBuildExecutor function to create a run executor for the container
|
// NewDockerBuildExecutor function to create a run executor for the container
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -559,7 +560,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
|||||||
return nil, errors.Errorf("--health-retries cannot be negative")
|
return nil, errors.Errorf("--health-retries cannot be negative")
|
||||||
}
|
}
|
||||||
if copts.healthStartPeriod < 0 {
|
if copts.healthStartPeriod < 0 {
|
||||||
return nil, fmt.Errorf("--health-start-period cannot be negative")
|
return nil, errors.New("--health-start-period cannot be negative")
|
||||||
}
|
}
|
||||||
|
|
||||||
healthConfig = &container.HealthConfig{
|
healthConfig = &container.HealthConfig{
|
||||||
@@ -836,7 +837,7 @@ func convertToStandardNotation(ports []string) ([]string, error) {
|
|||||||
for _, publish := range ports {
|
for _, publish := range ports {
|
||||||
if strings.Contains(publish, "=") {
|
if strings.Contains(publish, "=") {
|
||||||
params := map[string]string{"protocol": "tcp"}
|
params := map[string]string{"protocol": "tcp"}
|
||||||
for _, param := range strings.Split(publish, ",") {
|
for param := range strings.SplitSeq(publish, ",") {
|
||||||
opt := strings.Split(param, "=")
|
opt := strings.Split(param, "=")
|
||||||
if len(opt) < 2 {
|
if len(opt) < 2 {
|
||||||
return optsList, errors.Errorf("invalid publish opts format (should be name=value but got '%s')", param)
|
return optsList, errors.Errorf("invalid publish opts format (should be name=value but got '%s')", param)
|
||||||
@@ -1066,10 +1067,8 @@ func validateLinuxPath(val string, validator func(string) bool) (string, error)
|
|||||||
// validateAttach validates that the specified string is a valid attach option.
|
// validateAttach validates that the specified string is a valid attach option.
|
||||||
func validateAttach(val string) (string, error) {
|
func validateAttach(val string) (string, error) {
|
||||||
s := strings.ToLower(val)
|
s := strings.ToLower(val)
|
||||||
for _, str := range []string{"stdin", "stdout", "stderr"} {
|
if slices.Contains([]string{"stdin", "stdout", "stderr"}, s) {
|
||||||
if s == str {
|
return s, nil
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR")
|
return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
is "gotest.tools/v3/assert/cmp"
|
is "gotest.tools/v3/assert/cmp"
|
||||||
"gotest.tools/v3/skip"
|
"gotest.tools/v3/skip"
|
||||||
@@ -185,7 +186,7 @@ func TestParseRunWithInvalidArgs(t *testing.T) {
|
|||||||
flags, _ := setupRunFlags()
|
flags, _ := setupRunFlags()
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
|
t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
|
||||||
assert.Error(t, flags.Parse(tc.args), tc.error)
|
require.Error(t, flags.Parse(tc.args), tc.error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,7 +302,7 @@ func TestParseWithMacAddress(t *testing.T) {
|
|||||||
t.Fatalf("Expected an error with %v mac-address, got %v", invalidMacAddress, err)
|
t.Fatalf("Expected an error with %v mac-address, got %v", invalidMacAddress, err)
|
||||||
}
|
}
|
||||||
config, hostConfig, _ := mustParse(t, validMacAddress)
|
config, hostConfig, _ := mustParse(t, validMacAddress)
|
||||||
fmt.Printf("MacAddress: %+v\n", hostConfig)
|
t.Logf("MacAddress: %+v\n", hostConfig)
|
||||||
assert.Equal(t, "92:d0:c6:0a:29:33", config.MacAddress) //nolint:staticcheck
|
assert.Equal(t, "92:d0:c6:0a:29:33", config.MacAddress) //nolint:staticcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +340,7 @@ func TestParseHostname(t *testing.T) {
|
|||||||
hostnameWithDomain := "--hostname=hostname.domainname"
|
hostnameWithDomain := "--hostname=hostname.domainname"
|
||||||
hostnameWithDomainTld := "--hostname=hostname.domainname.tld"
|
hostnameWithDomainTld := "--hostname=hostname.domainname.tld"
|
||||||
for hostname, expectedHostname := range validHostnames {
|
for hostname, expectedHostname := range validHostnames {
|
||||||
if config, _, _ := mustParse(t, fmt.Sprintf("--hostname=%s", hostname)); config.Hostname != expectedHostname {
|
if config, _, _ := mustParse(t, "--hostname="+hostname); config.Hostname != expectedHostname {
|
||||||
t.Fatalf("Expected the config to have 'hostname' as %q, got %q", expectedHostname, config.Hostname)
|
t.Fatalf("Expected the config to have 'hostname' as %q, got %q", expectedHostname, config.Hostname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -606,7 +607,7 @@ func TestParseNetworkConfig(t *testing.T) {
|
|||||||
_, hConfig, nwConfig, err := parseRun(tc.flags)
|
_, hConfig, nwConfig, err := parseRun(tc.flags)
|
||||||
|
|
||||||
if tc.expectedErr != "" {
|
if tc.expectedErr != "" {
|
||||||
assert.Error(t, err, tc.expectedErr)
|
require.Error(t, err, tc.expectedErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,7 +678,7 @@ func TestParseRestartPolicy(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for restart, expectedError := range invalids {
|
for restart, expectedError := range invalids {
|
||||||
if _, _, _, err := parseRun([]string{fmt.Sprintf("--restart=%s", restart), "img", "cmd"}); err == nil || err.Error() != expectedError {
|
if _, _, _, err := parseRun([]string{"--restart=" + restart, "img", "cmd"}); err == nil || err.Error() != expectedError {
|
||||||
t.Fatalf("Expected an error with message '%v' for %v, got %v", expectedError, restart, err)
|
t.Fatalf("Expected an error with message '%v' for %v, got %v", expectedError, restart, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -26,17 +27,17 @@ func TestImageExistsLocally(t *testing.T) {
|
|||||||
|
|
||||||
// Test if image exists with specific tag
|
// Test if image exists with specific tag
|
||||||
invalidImageTag, err := ImageExistsLocally(ctx, "library/alpine:this-random-tag-will-never-exist", "linux/amd64")
|
invalidImageTag, err := ImageExistsLocally(ctx, "library/alpine:this-random-tag-will-never-exist", "linux/amd64")
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, false, invalidImageTag)
|
assert.False(t, invalidImageTag)
|
||||||
|
|
||||||
// Test if image exists with specific architecture (image platform)
|
// Test if image exists with specific architecture (image platform)
|
||||||
invalidImagePlatform, err := ImageExistsLocally(ctx, "alpine:latest", "windows/amd64")
|
invalidImagePlatform, err := ImageExistsLocally(ctx, "alpine:latest", "windows/amd64")
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, false, invalidImagePlatform)
|
assert.False(t, invalidImagePlatform)
|
||||||
|
|
||||||
// pull an image
|
// pull an image
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
cli.NegotiateAPIVersion(context.Background())
|
cli.NegotiateAPIVersion(context.Background())
|
||||||
|
|
||||||
// Chose alpine latest because it's so small
|
// Chose alpine latest because it's so small
|
||||||
@@ -44,14 +45,14 @@ func TestImageExistsLocally(t *testing.T) {
|
|||||||
readerDefault, err := cli.ImagePull(ctx, "node:16-buster-slim", image.PullOptions{
|
readerDefault, err := cli.ImagePull(ctx, "node:16-buster-slim", image.PullOptions{
|
||||||
Platform: "linux/amd64",
|
Platform: "linux/amd64",
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
defer readerDefault.Close()
|
defer readerDefault.Close()
|
||||||
_, err = io.ReadAll(readerDefault)
|
_, err = io.ReadAll(readerDefault)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
imageDefaultArchExists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/amd64")
|
imageDefaultArchExists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/amd64")
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, imageDefaultArchExists)
|
assert.True(t, imageDefaultArchExists)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImageExistsLocallyQemu(t *testing.T) {
|
func TestImageExistsLocallyQemu(t *testing.T) {
|
||||||
@@ -66,19 +67,19 @@ func TestImageExistsLocallyQemu(t *testing.T) {
|
|||||||
|
|
||||||
// pull an image
|
// pull an image
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
cli.NegotiateAPIVersion(context.Background())
|
cli.NegotiateAPIVersion(context.Background())
|
||||||
|
|
||||||
// Validate if another architecture platform can be pulled
|
// Validate if another architecture platform can be pulled
|
||||||
readerArm64, err := cli.ImagePull(ctx, "node:16-buster-slim", image.PullOptions{
|
readerArm64, err := cli.ImagePull(ctx, "node:16-buster-slim", image.PullOptions{
|
||||||
Platform: "linux/arm64",
|
Platform: "linux/arm64",
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
defer readerArm64.Close()
|
defer readerArm64.Close()
|
||||||
_, err = io.ReadAll(readerArm64)
|
_, err = io.ReadAll(readerArm64)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
imageArm64Exists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/arm64")
|
imageArm64Exists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/arm64")
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, imageArm64Exists)
|
assert.True(t, imageArm64Exists)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func logDockerResponse(logger logrus.FieldLogger, dockerResponse io.ReadCloser,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeLog(logger logrus.FieldLogger, isError bool, format string, args ...interface{}) {
|
func writeLog(logger logrus.FieldLogger, isError bool, format string, args ...any) {
|
||||||
if isError {
|
if isError {
|
||||||
logger.Errorf(format, args...)
|
logger.Errorf(format, args...)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package container
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/docker/docker/api/types/image"
|
"github.com/docker/docker/api/types/image"
|
||||||
"github.com/docker/docker/api/types/registry"
|
"github.com/docker/docker/api/types/registry"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDockerPullExecutor function to create a run executor for the container
|
// NewDockerPullExecutor function to create a run executor for the container
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
assert "github.com/stretchr/testify/assert"
|
assert "github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -40,15 +41,15 @@ func TestGetImagePullOptions(t *testing.T) {
|
|||||||
config.SetDir("/non-existent/docker")
|
config.SetDir("/non-existent/docker")
|
||||||
|
|
||||||
options, err := getImagePullOptions(ctx, NewDockerPullExecutorInput{})
|
options, err := getImagePullOptions(ctx, NewDockerPullExecutorInput{})
|
||||||
assert.Nil(t, err, "Failed to create ImagePullOptions")
|
require.NoError(t, err, "Failed to create ImagePullOptions")
|
||||||
assert.Equal(t, "", options.RegistryAuth, "RegistryAuth should be empty if no username or password is set")
|
assert.Empty(t, options.RegistryAuth, "RegistryAuth should be empty if no username or password is set")
|
||||||
|
|
||||||
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
|
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
|
||||||
Image: "",
|
Image: "",
|
||||||
Username: "username",
|
Username: "username",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
})
|
})
|
||||||
assert.Nil(t, err, "Failed to create ImagePullOptions")
|
require.NoError(t, err, "Failed to create ImagePullOptions")
|
||||||
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9", options.RegistryAuth, "Username and Password should be provided")
|
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9", options.RegistryAuth, "Username and Password should be provided")
|
||||||
|
|
||||||
config.SetDir("testdata/docker-pull-options")
|
config.SetDir("testdata/docker-pull-options")
|
||||||
@@ -56,6 +57,6 @@ func TestGetImagePullOptions(t *testing.T) {
|
|||||||
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
|
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
|
||||||
Image: "nektos/act",
|
Image: "nektos/act",
|
||||||
})
|
})
|
||||||
assert.Nil(t, err, "Failed to create ImagePullOptions")
|
require.NoError(t, err, "Failed to create ImagePullOptions")
|
||||||
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZFxuIiwic2VydmVyYWRkcmVzcyI6Imh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyJ9", options.RegistryAuth, "RegistryAuth should be taken from local docker config")
|
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZFxuIiwic2VydmVyYWRkcmVzcyI6Imh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyJ9", options.RegistryAuth, "RegistryAuth should be taken from local docker config")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ import (
|
|||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/filecollector"
|
"gitea.com/gitea/act_runner/pkg/filecollector"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewContainer creates a reference to a container
|
// NewContainer creates a reference to a container
|
||||||
@@ -137,7 +137,7 @@ func (cr *containerReference) CopyDir(destPath string, srcPath string, useGitIgn
|
|||||||
|
|
||||||
func (cr *containerReference) GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error) {
|
func (cr *containerReference) GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error) {
|
||||||
if common.Dryrun(ctx) {
|
if common.Dryrun(ctx) {
|
||||||
return nil, fmt.Errorf("dryrun is not supported in GetContainerArchive")
|
return nil, errors.New("dryrun is not supported in GetContainerArchive")
|
||||||
}
|
}
|
||||||
a, _, err := cr.cli.CopyFromContainer(ctx, cr.id, srcPath)
|
a, _, err := cr.cli.CopyFromContainer(ctx, cr.id, srcPath)
|
||||||
return a, err
|
return a, err
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -16,12 +16,13 @@ import (
|
|||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDocker(t *testing.T) {
|
func TestDocker(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
client, err := GetDockerClient(ctx)
|
client, err := GetDockerClient(ctx)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
dockerBuild := NewDockerBuildExecutor(NewDockerBuildExecutorInput{
|
dockerBuild := NewDockerBuildExecutor(NewDockerBuildExecutorInput{
|
||||||
@@ -30,7 +31,7 @@ func TestDocker(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
err = dockerBuild(ctx)
|
err = dockerBuild(ctx)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cr := &containerReference{
|
cr := &containerReference{
|
||||||
cli: client,
|
cli: client,
|
||||||
@@ -47,7 +48,7 @@ func TestDocker(t *testing.T) {
|
|||||||
|
|
||||||
envExecutor := cr.extractFromImageEnv(&env)
|
envExecutor := cr.extractFromImageEnv(&env)
|
||||||
err = envExecutor(ctx)
|
err = envExecutor(ctx)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, map[string]string{
|
assert.Equal(t, map[string]string{
|
||||||
"PATH": "/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:/this/path/does/not/exists/anywhere:/this/either",
|
"PATH": "/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:/this/path/does/not/exists/anywhere:/this/either",
|
||||||
"RANDOM_VAR": "WITH_VALUE",
|
"RANDOM_VAR": "WITH_VALUE",
|
||||||
@@ -153,7 +154,7 @@ func TestDockerExecAbort(t *testing.T) {
|
|||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
err := <-channel
|
err := <-channel
|
||||||
assert.ErrorIs(t, err, context.Canceled)
|
require.ErrorIs(t, err, context.Canceled)
|
||||||
|
|
||||||
conn.AssertExpectations(t)
|
conn.AssertExpectations(t)
|
||||||
client.AssertExpectations(t)
|
client.AssertExpectations(t)
|
||||||
@@ -183,7 +184,7 @@ func TestDockerExecFailure(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := cr.execExt([]string{""}, map[string]string{}, "user", "workdir")(ctx)
|
err := cr.execExt([]string{""}, map[string]string{}, "user", "workdir")(ctx)
|
||||||
assert.Error(t, err, "exit with `FAILURE`: 1")
|
require.Error(t, err, "exit with `FAILURE`: 1")
|
||||||
|
|
||||||
conn.AssertExpectations(t)
|
conn.AssertExpectations(t)
|
||||||
client.AssertExpectations(t)
|
client.AssertExpectations(t)
|
||||||
@@ -216,7 +217,7 @@ func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) {
|
|||||||
|
|
||||||
conn := &mockConn{}
|
conn := &mockConn{}
|
||||||
|
|
||||||
merr := fmt.Errorf("failure")
|
merr := errors.New("failure")
|
||||||
|
|
||||||
client := &mockDockerClient{}
|
client := &mockDockerClient{}
|
||||||
client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("container.CopyToContainerOptions")).Return(merr)
|
client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("container.CopyToContainerOptions")).Return(merr)
|
||||||
@@ -230,7 +231,7 @@ func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{})
|
err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{})
|
||||||
assert.ErrorIs(t, err, merr)
|
require.ErrorIs(t, err, merr)
|
||||||
|
|
||||||
conn.AssertExpectations(t)
|
conn.AssertExpectations(t)
|
||||||
client.AssertExpectations(t)
|
client.AssertExpectations(t)
|
||||||
@@ -241,7 +242,7 @@ func TestDockerCopyTarStreamErrorInMkdir(t *testing.T) {
|
|||||||
|
|
||||||
conn := &mockConn{}
|
conn := &mockConn{}
|
||||||
|
|
||||||
merr := fmt.Errorf("failure")
|
merr := errors.New("failure")
|
||||||
|
|
||||||
client := &mockDockerClient{}
|
client := &mockDockerClient{}
|
||||||
client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("container.CopyToContainerOptions")).Return(nil)
|
client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("container.CopyToContainerOptions")).Return(nil)
|
||||||
@@ -255,7 +256,7 @@ func TestDockerCopyTarStreamErrorInMkdir(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{})
|
err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{})
|
||||||
assert.ErrorIs(t, err, merr)
|
require.ErrorIs(t, err, merr)
|
||||||
|
|
||||||
conn.AssertExpectations(t)
|
conn.AssertExpectations(t)
|
||||||
client.AssertExpectations(t)
|
client.AssertExpectations(t)
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ func socketLocation() (string, bool) {
|
|||||||
// indicating that the `daemonPath` is a Docker host URI. If it doesn't, or if the "://" delimiter
|
// indicating that the `daemonPath` is a Docker host URI. If it doesn't, or if the "://" delimiter
|
||||||
// is not found in the `daemonPath`, the function returns false.
|
// is not found in the `daemonPath`, the function returns false.
|
||||||
func isDockerHostURI(daemonPath string) bool {
|
func isDockerHostURI(daemonPath string) bool {
|
||||||
if protoIndex := strings.Index(daemonPath, "://"); protoIndex != -1 {
|
if before, _, ok := strings.Cut(daemonPath, "://"); ok {
|
||||||
scheme := daemonPath[:protoIndex]
|
scheme := before
|
||||||
if strings.IndexFunc(scheme, func(r rune) bool {
|
if strings.IndexFunc(scheme, func(r rune) bool {
|
||||||
return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z')
|
return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z')
|
||||||
}) == -1 {
|
}) == -1 {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
assert "github.com/stretchr/testify/assert"
|
assert "github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -19,26 +20,26 @@ func TestGetSocketAndHostWithSocket(t *testing.T) {
|
|||||||
CommonSocketLocations = originalCommonSocketLocations
|
CommonSocketLocations = originalCommonSocketLocations
|
||||||
dockerHost := "unix:///my/docker/host.sock"
|
dockerHost := "unix:///my/docker/host.sock"
|
||||||
socketURI := "/path/to/my.socket"
|
socketURI := "/path/to/my.socket"
|
||||||
os.Setenv("DOCKER_HOST", dockerHost)
|
t.Setenv("DOCKER_HOST", dockerHost)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ret, err := GetSocketAndHost(socketURI)
|
ret, err := GetSocketAndHost(socketURI)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, SocketAndHost{socketURI, dockerHost}, ret)
|
assert.Equal(t, SocketAndHost{socketURI, dockerHost}, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSocketAndHostNoSocket(t *testing.T) {
|
func TestGetSocketAndHostNoSocket(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
dockerHost := "unix:///my/docker/host.sock"
|
dockerHost := "unix:///my/docker/host.sock"
|
||||||
os.Setenv("DOCKER_HOST", dockerHost)
|
t.Setenv("DOCKER_HOST", dockerHost)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ret, err := GetSocketAndHost("")
|
ret, err := GetSocketAndHost("")
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, SocketAndHost{dockerHost, dockerHost}, ret)
|
assert.Equal(t, SocketAndHost{dockerHost, dockerHost}, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +54,8 @@ func TestGetSocketAndHostOnlySocket(t *testing.T) {
|
|||||||
ret, err := GetSocketAndHost(socketURI)
|
ret, err := GetSocketAndHost(socketURI)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.NoError(t, err, "Expected no error from GetSocketAndHost")
|
require.NoError(t, err, "Expected no error from GetSocketAndHost")
|
||||||
assert.Equal(t, true, defaultSocketFound, "Expected to find default socket")
|
assert.True(t, defaultSocketFound, "Expected to find default socket")
|
||||||
assert.Equal(t, socketURI, ret.Socket, "Expected socket to match common location")
|
assert.Equal(t, socketURI, ret.Socket, "Expected socket to match common location")
|
||||||
assert.Equal(t, defaultSocket, ret.Host, "Expected ret.Host to match default socket location")
|
assert.Equal(t, defaultSocket, ret.Host, "Expected ret.Host to match default socket location")
|
||||||
}
|
}
|
||||||
@@ -63,13 +64,13 @@ func TestGetSocketAndHostDontMount(t *testing.T) {
|
|||||||
// Arrange
|
// Arrange
|
||||||
CommonSocketLocations = originalCommonSocketLocations
|
CommonSocketLocations = originalCommonSocketLocations
|
||||||
dockerHost := "unix:///my/docker/host.sock"
|
dockerHost := "unix:///my/docker/host.sock"
|
||||||
os.Setenv("DOCKER_HOST", dockerHost)
|
t.Setenv("DOCKER_HOST", dockerHost)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ret, err := GetSocketAndHost("-")
|
ret, err := GetSocketAndHost("-")
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, SocketAndHost{"-", dockerHost}, ret)
|
assert.Equal(t, SocketAndHost{"-", dockerHost}, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,8 +84,8 @@ func TestGetSocketAndHostNoHostNoSocket(t *testing.T) {
|
|||||||
ret, err := GetSocketAndHost("")
|
ret, err := GetSocketAndHost("")
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Equal(t, true, found, "Expected a default socket to be found")
|
assert.True(t, found, "Expected a default socket to be found")
|
||||||
assert.Nil(t, err, "Expected no error from GetSocketAndHost")
|
require.NoError(t, err, "Expected no error from GetSocketAndHost")
|
||||||
assert.Equal(t, SocketAndHost{defaultSocket, defaultSocket}, ret, "Expected to match default socket location")
|
assert.Equal(t, SocketAndHost{defaultSocket, defaultSocket}, ret, "Expected to match default socket location")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,11 +94,11 @@ func TestGetSocketAndHostNoHostNoSocket(t *testing.T) {
|
|||||||
// > This happens if neither DOCKER_HOST nor --container-daemon-socket has a value, but socketLocation() returns a URI
|
// > This happens if neither DOCKER_HOST nor --container-daemon-socket has a value, but socketLocation() returns a URI
|
||||||
func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
|
func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
mySocketFile, tmpErr := os.CreateTemp("", "act-*.sock")
|
mySocketFile, tmpErr := os.CreateTemp(t.TempDir(), "act-*.sock")
|
||||||
mySocket := mySocketFile.Name()
|
mySocket := mySocketFile.Name()
|
||||||
unixSocket := "unix://" + mySocket
|
unixSocket := "unix://" + mySocket
|
||||||
defer os.RemoveAll(mySocket)
|
defer os.RemoveAll(mySocket)
|
||||||
assert.NoError(t, tmpErr)
|
require.NoError(t, tmpErr)
|
||||||
os.Unsetenv("DOCKER_HOST")
|
os.Unsetenv("DOCKER_HOST")
|
||||||
|
|
||||||
CommonSocketLocations = []string{mySocket}
|
CommonSocketLocations = []string{mySocket}
|
||||||
@@ -108,8 +109,8 @@ func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Equal(t, unixSocket, defaultSocket, "Expected default socket to match common socket location")
|
assert.Equal(t, unixSocket, defaultSocket, "Expected default socket to match common socket location")
|
||||||
assert.Equal(t, true, found, "Expected default socket to be found")
|
assert.True(t, found, "Expected default socket to be found")
|
||||||
assert.Nil(t, err, "Expected no error from GetSocketAndHost")
|
require.NoError(t, err, "Expected no error from GetSocketAndHost")
|
||||||
assert.Equal(t, SocketAndHost{unixSocket, unixSocket}, ret, "Expected to match default socket location")
|
assert.Equal(t, SocketAndHost{unixSocket, unixSocket}, ret, "Expected to match default socket location")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,10 +125,10 @@ func TestGetSocketAndHostNoHostInvalidSocket(t *testing.T) {
|
|||||||
ret, err := GetSocketAndHost(mySocket)
|
ret, err := GetSocketAndHost(mySocket)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Equal(t, false, found, "Expected no default socket to be found")
|
assert.False(t, found, "Expected no default socket to be found")
|
||||||
assert.Equal(t, "", defaultSocket, "Expected no default socket to be found")
|
assert.Empty(t, defaultSocket, "Expected no default socket to be found")
|
||||||
assert.Equal(t, SocketAndHost{}, ret, "Expected to match default socket location")
|
assert.Equal(t, SocketAndHost{}, ret, "Expected to match default socket location")
|
||||||
assert.Error(t, err, "Expected an error in invalid state")
|
require.Error(t, err, "Expected an error in invalid state")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSocketAndHostOnlySocketValidButUnusualLocation(t *testing.T) {
|
func TestGetSocketAndHostOnlySocketValidButUnusualLocation(t *testing.T) {
|
||||||
@@ -142,9 +143,9 @@ func TestGetSocketAndHostOnlySocketValidButUnusualLocation(t *testing.T) {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
// Default socket locations
|
// Default socket locations
|
||||||
assert.Equal(t, "", defaultSocket, "Expect default socket location to be empty")
|
assert.Empty(t, defaultSocket, "Expect default socket location to be empty")
|
||||||
assert.Equal(t, false, found, "Expected no default socket to be found")
|
assert.False(t, found, "Expected no default socket to be found")
|
||||||
// Sane default
|
// Sane default
|
||||||
assert.Nil(t, err, "Expect no error from GetSocketAndHost")
|
require.NoError(t, err, "Expect no error from GetSocketAndHost")
|
||||||
assert.Equal(t, socketURI, ret.Host, "Expect host to default to unusual socket")
|
assert.Equal(t, socketURI, ret.Host, "Expect host to default to unusual socket")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/docker/docker/api/types/system"
|
"github.com/docker/docker/api/types/system"
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package container
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/volume"
|
"github.com/docker/docker/api/types/volume"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type ExecutionsEnvironment interface {
|
|||||||
GetPathVariableName() string
|
GetPathVariableName() string
|
||||||
DefaultPathVariable() string
|
DefaultPathVariable() string
|
||||||
JoinPathVariable(...string) string
|
JoinPathVariable(...string) string
|
||||||
GetRunnerContext(ctx context.Context) map[string]interface{}
|
GetRunnerContext(ctx context.Context) map[string]any
|
||||||
// On windows PATH and Path are the same key
|
// On windows PATH and Path are the same key
|
||||||
IsEnvironmentCaseInsensitive() bool
|
IsEnvironmentCaseInsensitive() bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import (
|
|||||||
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
|
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/filecollector"
|
"gitea.com/gitea/act_runner/pkg/filecollector"
|
||||||
"github.com/actions-oss/act-cli/pkg/lookpath"
|
"gitea.com/gitea/act_runner/pkg/lookpath"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HostEnvironment struct {
|
type HostEnvironment struct {
|
||||||
@@ -83,7 +83,7 @@ func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, ta
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
return fmt.Errorf("copyTarStream has been cancelled")
|
return errors.New("copyTarStream has been cancelled")
|
||||||
}
|
}
|
||||||
if err := cp.WriteFile(ti.Name, ti.FileInfo(), ti.Linkname, tr); err != nil {
|
if err := cp.WriteFile(ti.Name, ti.FileInfo(), ti.Linkname, tr); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -224,7 +224,7 @@ func (l *localEnv) Getenv(name string) string {
|
|||||||
func lookupPathHost(cmd string, env map[string]string, writer io.Writer) (string, error) {
|
func lookupPathHost(cmd string, env map[string]string, writer io.Writer) (string, error) {
|
||||||
f, err := lookpath.LookPath2(cmd, &localEnv{env: env})
|
f, err := lookpath.LookPath2(cmd, &localEnv{env: env})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := "Cannot find: " + fmt.Sprint(cmd) + " in PATH"
|
err := "Cannot find: " + cmd + " in PATH"
|
||||||
if _, _err := writer.Write([]byte(err + "\n")); _err != nil {
|
if _, _err := writer.Write([]byte(err + "\n")); _err != nil {
|
||||||
return "", fmt.Errorf("%v: %w", err, _err)
|
return "", fmt.Errorf("%v: %w", err, _err)
|
||||||
}
|
}
|
||||||
@@ -343,7 +343,7 @@ func (e *HostEnvironment) exec(ctx context.Context, command []string, cmdline st
|
|||||||
}
|
}
|
||||||
if tty != nil {
|
if tty != nil {
|
||||||
writer.AutoStop = true
|
writer.AutoStop = true
|
||||||
if _, err := tty.Write([]byte("\x04")); err != nil {
|
if _, err := tty.WriteString("\x04"); err != nil {
|
||||||
common.Logger(ctx).Debug("Failed to write EOT")
|
common.Logger(ctx).Debug("Failed to write EOT")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,8 +451,8 @@ func goOsToActionOs(os string) string {
|
|||||||
return os
|
return os
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]interface{} {
|
func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]any {
|
||||||
return map[string]interface{}{
|
return map[string]any{
|
||||||
"os": goOsToActionOs(runtime.GOOS),
|
"os": goOsToActionOs(runtime.GOOS),
|
||||||
"arch": goArchToActionArch(runtime.GOARCH),
|
"arch": goArchToActionArch(runtime.GOARCH),
|
||||||
"temp": e.TmpDir,
|
"temp": e.TmpDir,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Type assert HostEnvironment implements ExecutionsEnvironment
|
// Type assert HostEnvironment implements ExecutionsEnvironment
|
||||||
@@ -17,7 +18,7 @@ var _ ExecutionsEnvironment = &HostEnvironment{}
|
|||||||
|
|
||||||
func TestCopyDir(t *testing.T) {
|
func TestCopyDir(t *testing.T) {
|
||||||
dir, err := os.MkdirTemp("", "test-host-env-*")
|
dir, err := os.MkdirTemp("", "test-host-env-*")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
e := &HostEnvironment{
|
e := &HostEnvironment{
|
||||||
@@ -33,12 +34,11 @@ func TestCopyDir(t *testing.T) {
|
|||||||
_ = os.MkdirAll(e.ToolCache, 0700)
|
_ = os.MkdirAll(e.ToolCache, 0700)
|
||||||
_ = os.MkdirAll(e.ActPath, 0700)
|
_ = os.MkdirAll(e.ActPath, 0700)
|
||||||
err = e.CopyDir(e.Workdir, e.Path, true)(ctx)
|
err = e.CopyDir(e.Workdir, e.Path, true)(ctx)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetContainerArchive(t *testing.T) {
|
func TestGetContainerArchive(t *testing.T) {
|
||||||
dir, err := os.MkdirTemp("", "test-host-env-*")
|
dir := t.TempDir()
|
||||||
assert.NoError(t, err)
|
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
e := &HostEnvironment{
|
e := &HostEnvironment{
|
||||||
@@ -54,17 +54,17 @@ func TestGetContainerArchive(t *testing.T) {
|
|||||||
_ = os.MkdirAll(e.ToolCache, 0700)
|
_ = os.MkdirAll(e.ToolCache, 0700)
|
||||||
_ = os.MkdirAll(e.ActPath, 0700)
|
_ = os.MkdirAll(e.ActPath, 0700)
|
||||||
expectedContent := []byte("sdde/7sh")
|
expectedContent := []byte("sdde/7sh")
|
||||||
err = os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0600)
|
err := os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0600)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
archive, err := e.GetContainerArchive(ctx, e.Path)
|
archive, err := e.GetContainerArchive(ctx, e.Path)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer archive.Close()
|
defer archive.Close()
|
||||||
reader := tar.NewReader(archive)
|
reader := tar.NewReader(archive)
|
||||||
h, err := reader.Next()
|
h, err := reader.Next()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "action.yml", h.Name)
|
assert.Equal(t, "action.yml", h.Name)
|
||||||
content, err := io.ReadAll(reader)
|
content, err := io.ReadAll(reader)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expectedContent, content)
|
assert.Equal(t, expectedContent, content)
|
||||||
_, err = reader.Next()
|
_, err = reader.Next()
|
||||||
assert.ErrorIs(t, err, io.EOF)
|
assert.ErrorIs(t, err, io.EOF)
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ func (*LinuxContainerEnvironmentExtensions) JoinPathVariable(paths ...string) st
|
|||||||
return strings.Join(paths, ":")
|
return strings.Join(paths, ":")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]interface{} {
|
func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]any {
|
||||||
return map[string]interface{}{
|
return map[string]any{
|
||||||
"os": "Linux",
|
"os": "Linux",
|
||||||
"arch": RunnerArch(ctx),
|
"arch": RunnerArch(ctx),
|
||||||
"temp": "/tmp",
|
"temp": "/tmp",
|
||||||
|
|||||||
@@ -31,22 +31,17 @@ func TestContainerPath(t *testing.T) {
|
|||||||
for _, v := range []containerPathJob{
|
for _, v := range []containerPathJob{
|
||||||
{"/mnt/c/Users/act/go/src/github.com/nektos/act", "C:\\Users\\act\\go\\src\\github.com\\nektos\\act\\", ""},
|
{"/mnt/c/Users/act/go/src/github.com/nektos/act", "C:\\Users\\act\\go\\src\\github.com\\nektos\\act\\", ""},
|
||||||
{"/mnt/f/work/dir", `F:\work\dir`, ""},
|
{"/mnt/f/work/dir", `F:\work\dir`, ""},
|
||||||
{"/mnt/c/windows/to/unix", "windows\\to\\unix", fmt.Sprintf("%s\\", rootDrive)},
|
{"/mnt/c/windows/to/unix", "windows\\to\\unix", rootDrive + "\\"},
|
||||||
{fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", fmt.Sprintf("%s\\", rootDrive)},
|
{fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", rootDrive + "\\"},
|
||||||
} {
|
} {
|
||||||
if v.workDir != "" {
|
if v.workDir != "" {
|
||||||
if err := os.Chdir(v.workDir); err != nil {
|
t.Chdir(v.workDir)
|
||||||
log.Error(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, v.destinationPath, linuxcontainerext.ToContainerPath(v.sourcePath))
|
assert.Equal(t, v.destinationPath, linuxcontainerext.ToContainerPath(v.sourcePath))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Chdir(cwd); err != nil {
|
t.Chdir(cwd)
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseEnvFile(e Container, srcPath string, env *map[string]string) common.Executor {
|
func parseEnvFile(e Container, srcPath string, env *map[string]string) common.Executor {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package exprparser
|
package exprparser
|
||||||
|
|
||||||
import "github.com/actions-oss/act-cli/pkg/model"
|
import "gitea.com/gitea/act_runner/pkg/model"
|
||||||
|
|
||||||
func (impl *interperterImpl) getNeedsTransitive(job *model.Job) []string {
|
func (impl *interperterImpl) getNeedsTransitive(job *model.Job) []string {
|
||||||
needs := job.Needs()
|
needs := job.Needs()
|
||||||
@@ -13,11 +13,11 @@ func (impl *interperterImpl) getNeedsTransitive(job *model.Job) []string {
|
|||||||
return needs
|
return needs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (impl *interperterImpl) always() (interface{}, error) {
|
func (impl *interperterImpl) always() (any, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (impl *interperterImpl) jobSuccess() (interface{}, error) {
|
func (impl *interperterImpl) jobSuccess() (any, error) {
|
||||||
jobs := impl.config.Run.Workflow.Jobs
|
jobs := impl.config.Run.Workflow.Jobs
|
||||||
jobNeeds := impl.getNeedsTransitive(impl.config.Run.Job())
|
jobNeeds := impl.getNeedsTransitive(impl.config.Run.Job())
|
||||||
|
|
||||||
@@ -30,11 +30,11 @@ func (impl *interperterImpl) jobSuccess() (interface{}, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (impl *interperterImpl) stepSuccess() (interface{}, error) {
|
func (impl *interperterImpl) stepSuccess() (any, error) {
|
||||||
return impl.env.Job.Status == "success", nil
|
return impl.env.Job.Status == "success", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (impl *interperterImpl) jobFailure() (interface{}, error) {
|
func (impl *interperterImpl) jobFailure() (any, error) {
|
||||||
jobs := impl.config.Run.Workflow.Jobs
|
jobs := impl.config.Run.Workflow.Jobs
|
||||||
jobNeeds := impl.getNeedsTransitive(impl.config.Run.Job())
|
jobNeeds := impl.getNeedsTransitive(impl.config.Run.Job())
|
||||||
|
|
||||||
@@ -47,10 +47,10 @@ func (impl *interperterImpl) jobFailure() (interface{}, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (impl *interperterImpl) stepFailure() (interface{}, error) {
|
func (impl *interperterImpl) stepFailure() (any, error) {
|
||||||
return impl.env.Job.Status == "failure", nil
|
return impl.env.Job.Status == "failure", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (impl *interperterImpl) cancelled() (interface{}, error) {
|
func (impl *interperterImpl) cancelled() (any, error) {
|
||||||
return impl.env.Job.Status == "cancelled", nil
|
return impl.env.Job.Status == "cancelled", nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
eval "github.com/actions-oss/act-cli/internal/eval/v2"
|
eval "gitea.com/gitea/act_runner/internal/eval/v2"
|
||||||
exprparser "github.com/actions-oss/act-cli/internal/expr"
|
exprparser "gitea.com/gitea/act_runner/internal/expr"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EvaluationEnvironment struct {
|
type EvaluationEnvironment struct {
|
||||||
@@ -18,16 +18,16 @@ type EvaluationEnvironment struct {
|
|||||||
Job *model.JobContext
|
Job *model.JobContext
|
||||||
Jobs *map[string]*model.WorkflowCallResult
|
Jobs *map[string]*model.WorkflowCallResult
|
||||||
Steps map[string]*model.StepResult
|
Steps map[string]*model.StepResult
|
||||||
Runner map[string]interface{}
|
Runner map[string]any
|
||||||
Secrets map[string]string
|
Secrets map[string]string
|
||||||
Vars map[string]string
|
Vars map[string]string
|
||||||
Strategy map[string]interface{}
|
Strategy map[string]any
|
||||||
Matrix map[string]interface{}
|
Matrix map[string]any
|
||||||
Needs map[string]Needs
|
Needs map[string]Needs
|
||||||
Inputs map[string]interface{}
|
Inputs map[string]any
|
||||||
HashFiles func([]reflect.Value) (interface{}, error)
|
HashFiles func([]reflect.Value) (any, error)
|
||||||
EnvCS bool
|
EnvCS bool
|
||||||
CtxData map[string]interface{}
|
CtxData map[string]any
|
||||||
}
|
}
|
||||||
|
|
||||||
type CaseSensitiveDict map[string]string
|
type CaseSensitiveDict map[string]string
|
||||||
@@ -69,7 +69,7 @@ func (dsc DefaultStatusCheck) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Interpreter interface {
|
type Interpreter interface {
|
||||||
Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (interface{}, error)
|
Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (any, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type interperterImpl struct {
|
type interperterImpl struct {
|
||||||
@@ -151,7 +151,7 @@ func toRaw(left reflect.Value) any {
|
|||||||
|
|
||||||
// All values are evaluated as string, funcs that takes objects are implemented elsewhere
|
// All values are evaluated as string, funcs that takes objects are implemented elsewhere
|
||||||
type externalFunc struct {
|
type externalFunc struct {
|
||||||
f func([]reflect.Value) (interface{}, error)
|
f func([]reflect.Value) (any, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e externalFunc) Evaluate(ev *eval.Evaluator, args []exprparser.Node) (*eval.EvaluationResult, error) {
|
func (e externalFunc) Evaluate(ev *eval.Evaluator, args []exprparser.Node) (*eval.EvaluationResult, error) {
|
||||||
@@ -170,7 +170,7 @@ func (e externalFunc) Evaluate(ev *eval.Evaluator, args []exprparser.Node) (*eva
|
|||||||
return eval.CreateIntermediateResult(ev.Context(), res), nil
|
return eval.CreateIntermediateResult(ev.Context(), res), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (impl *interperterImpl) Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (interface{}, error) {
|
func (impl *interperterImpl) Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (any, error) {
|
||||||
input = strings.TrimPrefix(input, "${{")
|
input = strings.TrimPrefix(input, "${{")
|
||||||
input = strings.TrimSuffix(input, "}}")
|
input = strings.TrimSuffix(input, "}}")
|
||||||
if defaultStatusCheck != DefaultStatusCheckNone && input == "" {
|
if defaultStatusCheck != DefaultStatusCheckNone && input == "" {
|
||||||
@@ -226,10 +226,10 @@ func (impl *interperterImpl) GetFunctions() eval.CaseInsensitiveObject[eval.Func
|
|||||||
if impl.env.HashFiles != nil {
|
if impl.env.HashFiles != nil {
|
||||||
functions["hashfiles"] = &externalFunc{impl.env.HashFiles}
|
functions["hashfiles"] = &externalFunc{impl.env.HashFiles}
|
||||||
}
|
}
|
||||||
functions["always"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) {
|
functions["always"] = &externalFunc{func(_ []reflect.Value) (any, error) {
|
||||||
return impl.always()
|
return impl.always()
|
||||||
}}
|
}}
|
||||||
functions["success"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) {
|
functions["success"] = &externalFunc{func(_ []reflect.Value) (any, error) {
|
||||||
if impl.config.Context == "job" {
|
if impl.config.Context == "job" {
|
||||||
return impl.jobSuccess()
|
return impl.jobSuccess()
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ func (impl *interperterImpl) GetFunctions() eval.CaseInsensitiveObject[eval.Func
|
|||||||
}
|
}
|
||||||
return nil, fmt.Errorf("context '%s' must be one of 'job' or 'step'", impl.config.Context)
|
return nil, fmt.Errorf("context '%s' must be one of 'job' or 'step'", impl.config.Context)
|
||||||
}}
|
}}
|
||||||
functions["failure"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) {
|
functions["failure"] = &externalFunc{func(_ []reflect.Value) (any, error) {
|
||||||
if impl.config.Context == "job" {
|
if impl.config.Context == "job" {
|
||||||
return impl.jobFailure()
|
return impl.jobFailure()
|
||||||
}
|
}
|
||||||
@@ -247,7 +247,7 @@ func (impl *interperterImpl) GetFunctions() eval.CaseInsensitiveObject[eval.Func
|
|||||||
}
|
}
|
||||||
return nil, fmt.Errorf("context '%s' must be one of 'job' or 'step'", impl.config.Context)
|
return nil, fmt.Errorf("context '%s' must be one of 'job' or 'step'", impl.config.Context)
|
||||||
}}
|
}}
|
||||||
functions["cancelled"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) {
|
functions["cancelled"] = &externalFunc{func(_ []reflect.Value) (any, error) {
|
||||||
return impl.cancelled()
|
return impl.cancelled()
|
||||||
}}
|
}}
|
||||||
return functions
|
return functions
|
||||||
@@ -287,7 +287,7 @@ func (impl *interperterImpl) GetVariables() eval.ReadOnlyObject[any] {
|
|||||||
res := eval.CreateIntermediateResult(eval.NewEvaluationContext(), rawOtherCtx)
|
res := eval.CreateIntermediateResult(eval.NewEvaluationContext(), rawOtherCtx)
|
||||||
if rOtherCd, ok := res.TryGetCollectionInterface(); ok {
|
if rOtherCd, ok := res.TryGetCollectionInterface(); ok {
|
||||||
if otherCd, ok := rOtherCd.(eval.ReadOnlyObject[any]); ok {
|
if otherCd, ok := rOtherCd.(eval.ReadOnlyObject[any]); ok {
|
||||||
if rawPayload, ok := cd.(map[string]interface{}); ok {
|
if rawPayload, ok := cd.(map[string]any); ok {
|
||||||
for k, v := range rawPayload {
|
for k, v := range rawPayload {
|
||||||
// skip empty values, because github.workspace was set by Gitea Actions to an empty string
|
// skip empty values, because github.workspace was set by Gitea Actions to an empty string
|
||||||
if mk, _ := otherCd.GetKv(k); v != "" && v != nil {
|
if mk, _ := otherCd.GetKv(k); v != "" && v != nil {
|
||||||
@@ -304,7 +304,7 @@ func (impl *interperterImpl) GetVariables() eval.ReadOnlyObject[any] {
|
|||||||
return vars
|
return vars
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsTruthy(input interface{}) bool {
|
func IsTruthy(input any) bool {
|
||||||
value := reflect.ValueOf(input)
|
value := reflect.ValueOf(input)
|
||||||
switch value.Kind() {
|
switch value.Kind() {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
|
|||||||
@@ -4,14 +4,15 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLiterals(t *testing.T) {
|
func TestLiterals(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
input string
|
input string
|
||||||
expected interface{}
|
expected any
|
||||||
name string
|
name string
|
||||||
}{
|
}{
|
||||||
{"true", true, "true"},
|
{"true", true, "true"},
|
||||||
@@ -30,7 +31,7 @@ func TestLiterals(t *testing.T) {
|
|||||||
for _, tt := range table {
|
for _, tt := range table {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, tt.expected, output)
|
assert.Equal(t, tt.expected, output)
|
||||||
})
|
})
|
||||||
@@ -40,7 +41,7 @@ func TestLiterals(t *testing.T) {
|
|||||||
func TestOperators(t *testing.T) {
|
func TestOperators(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
input string
|
input string
|
||||||
expected interface{}
|
expected any
|
||||||
name string
|
name string
|
||||||
error string
|
error string
|
||||||
}{
|
}{
|
||||||
@@ -69,7 +70,7 @@ func TestOperators(t *testing.T) {
|
|||||||
{`true && false`, false, "and", ""},
|
{`true && false`, false, "and", ""},
|
||||||
{`true || false`, true, "or", ""},
|
{`true || false`, true, "or", ""},
|
||||||
{`fromJSON('{}') && true`, true, "and-boolean-object", ""},
|
{`fromJSON('{}') && true`, true, "and-boolean-object", ""},
|
||||||
{`fromJSON('{}') || false`, make(map[string]interface{}), "or-boolean-object", ""},
|
{`fromJSON('{}') || false`, make(map[string]any), "or-boolean-object", ""},
|
||||||
{"github.event.commits[0].author.username != github.event.commits[1].author.username", true, "property-comparison1", ""},
|
{"github.event.commits[0].author.username != github.event.commits[1].author.username", true, "property-comparison1", ""},
|
||||||
{"github.event.commits[0].author.username1 != github.event.commits[1].author.username", true, "property-comparison2", ""},
|
{"github.event.commits[0].author.username1 != github.event.commits[1].author.username", true, "property-comparison2", ""},
|
||||||
{"github.event.commits[0].author.username != github.event.commits[1].author.username1", true, "property-comparison3", ""},
|
{"github.event.commits[0].author.username != github.event.commits[1].author.username1", true, "property-comparison3", ""},
|
||||||
@@ -81,15 +82,15 @@ func TestOperators(t *testing.T) {
|
|||||||
env := &EvaluationEnvironment{
|
env := &EvaluationEnvironment{
|
||||||
Github: &model.GithubContext{
|
Github: &model.GithubContext{
|
||||||
Action: "push",
|
Action: "push",
|
||||||
Event: map[string]interface{}{
|
Event: map[string]any{
|
||||||
"commits": []interface{}{
|
"commits": []any{
|
||||||
map[string]interface{}{
|
map[string]any{
|
||||||
"author": map[string]interface{}{
|
"author": map[string]any{
|
||||||
"username": "someone",
|
"username": "someone",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
map[string]any{
|
||||||
"author": map[string]interface{}{
|
"author": map[string]any{
|
||||||
"username": "someone-else",
|
"username": "someone-else",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -102,10 +103,10 @@ func TestOperators(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
||||||
if tt.error != "" {
|
if tt.error != "" {
|
||||||
assert.NotNil(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, tt.error, err.Error())
|
assert.Equal(t, tt.error, err.Error())
|
||||||
} else {
|
} else {
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, tt.expected, output)
|
assert.Equal(t, tt.expected, output)
|
||||||
@@ -116,7 +117,7 @@ func TestOperators(t *testing.T) {
|
|||||||
func TestOperatorsCompare(t *testing.T) {
|
func TestOperatorsCompare(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
input string
|
input string
|
||||||
expected interface{}
|
expected any
|
||||||
name string
|
name string
|
||||||
}{
|
}{
|
||||||
{"!null", true, "not-null"},
|
{"!null", true, "not-null"},
|
||||||
@@ -154,7 +155,7 @@ func TestOperatorsCompare(t *testing.T) {
|
|||||||
for _, tt := range table {
|
for _, tt := range table {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, tt.expected, output)
|
assert.Equal(t, tt.expected, output)
|
||||||
})
|
})
|
||||||
@@ -164,7 +165,7 @@ func TestOperatorsCompare(t *testing.T) {
|
|||||||
func TestOperatorsBooleanEvaluation(t *testing.T) {
|
func TestOperatorsBooleanEvaluation(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
input string
|
input string
|
||||||
expected interface{}
|
expected any
|
||||||
name string
|
name string
|
||||||
}{
|
}{
|
||||||
// true &&
|
// true &&
|
||||||
@@ -517,7 +518,7 @@ func TestOperatorsBooleanEvaluation(t *testing.T) {
|
|||||||
for _, tt := range table {
|
for _, tt := range table {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Normalize int => float64
|
// Normalize int => float64
|
||||||
if i, ok := tt.expected.(int); ok {
|
if i, ok := tt.expected.(int); ok {
|
||||||
@@ -536,15 +537,15 @@ func TestOperatorsBooleanEvaluation(t *testing.T) {
|
|||||||
func TestContexts(t *testing.T) {
|
func TestContexts(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
input string
|
input string
|
||||||
expected interface{}
|
expected any
|
||||||
name string
|
name string
|
||||||
caseSensitiveEnv bool
|
caseSensitiveEnv bool
|
||||||
ctxdata map[string]interface{}
|
ctxdata map[string]any
|
||||||
}{
|
}{
|
||||||
{input: "github.action", expected: "push", name: "github-context"},
|
{input: "github.action", expected: "push", name: "github-context"},
|
||||||
{input: "github.action", expected: "push", name: "github-context", ctxdata: map[string]interface{}{"github": map[string]interface{}{"ref": "refs/heads/test-data"}}},
|
{input: "github.action", expected: "push", name: "github-context", ctxdata: map[string]any{"github": map[string]any{"ref": "refs/heads/test-data"}}},
|
||||||
{input: "github.ref", expected: "refs/heads/test-data", name: "github-context", ctxdata: map[string]interface{}{"github": map[string]interface{}{"ref": "refs/heads/test-data"}}},
|
{input: "github.ref", expected: "refs/heads/test-data", name: "github-context", ctxdata: map[string]any{"github": map[string]any{"ref": "refs/heads/test-data"}}},
|
||||||
{input: "github.custom-field", expected: "custom-value", name: "github-context", ctxdata: map[string]interface{}{"github": map[string]interface{}{"custom-field": "custom-value"}}},
|
{input: "github.custom-field", expected: "custom-value", name: "github-context", ctxdata: map[string]any{"github": map[string]any{"custom-field": "custom-value"}}},
|
||||||
{input: "github.event.commits[0].message", expected: nil, name: "github-context-noexist-prop"},
|
{input: "github.event.commits[0].message", expected: nil, name: "github-context-noexist-prop"},
|
||||||
{input: "fromjson('{\"commits\":[]}').commits[0].message", expected: nil, name: "github-context-noexist-prop"},
|
{input: "fromjson('{\"commits\":[]}').commits[0].message", expected: nil, name: "github-context-noexist-prop"},
|
||||||
{input: "github.event.pull_request.labels.*.name", expected: nil, name: "github-context-noexist-prop"},
|
{input: "github.event.pull_request.labels.*.name", expected: nil, name: "github-context-noexist-prop"},
|
||||||
@@ -581,8 +582,8 @@ func TestContexts(t *testing.T) {
|
|||||||
{input: "contains(needs.*.result, 'success')", expected: true, name: "needs-wildcard-context-contains-success"},
|
{input: "contains(needs.*.result, 'success')", expected: true, name: "needs-wildcard-context-contains-success"},
|
||||||
{input: "contains(needs.*.result, 'failure')", expected: false, name: "needs-wildcard-context-contains-failure"},
|
{input: "contains(needs.*.result, 'failure')", expected: false, name: "needs-wildcard-context-contains-failure"},
|
||||||
{input: "inputs.name", expected: "value", name: "inputs-context"},
|
{input: "inputs.name", expected: "value", name: "inputs-context"},
|
||||||
{input: "vars.MY_VAR", expected: "refs/heads/test-data", name: "vars-context", ctxdata: map[string]interface{}{"vars": map[string]interface{}{"MY_VAR": "refs/heads/test-data"}}},
|
{input: "vars.MY_VAR", expected: "refs/heads/test-data", name: "vars-context", ctxdata: map[string]any{"vars": map[string]any{"MY_VAR": "refs/heads/test-data"}}},
|
||||||
{input: "vars.MY_VAR", expected: "refs/heads/test-data", name: "vars-context", ctxdata: map[string]interface{}{"vars": map[string]interface{}{"my_var": "refs/heads/test-data"}}},
|
{input: "vars.MY_VAR", expected: "refs/heads/test-data", name: "vars-context", ctxdata: map[string]any{"vars": map[string]any{"my_var": "refs/heads/test-data"}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
env := EvaluationEnvironment{
|
env := EvaluationEnvironment{
|
||||||
@@ -606,7 +607,7 @@ func TestContexts(t *testing.T) {
|
|||||||
Conclusion: model.StepStatusSkipped,
|
Conclusion: model.StepStatusSkipped,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Runner: map[string]interface{}{
|
Runner: map[string]any{
|
||||||
"os": "Linux",
|
"os": "Linux",
|
||||||
"temp": "/tmp",
|
"temp": "/tmp",
|
||||||
"tool_cache": "/opt/hostedtoolcache",
|
"tool_cache": "/opt/hostedtoolcache",
|
||||||
@@ -617,10 +618,10 @@ func TestContexts(t *testing.T) {
|
|||||||
Vars: map[string]string{
|
Vars: map[string]string{
|
||||||
"name": "value",
|
"name": "value",
|
||||||
},
|
},
|
||||||
Strategy: map[string]interface{}{
|
Strategy: map[string]any{
|
||||||
"fail-fast": true,
|
"fail-fast": true,
|
||||||
},
|
},
|
||||||
Matrix: map[string]interface{}{
|
Matrix: map[string]any{
|
||||||
"os": "Linux",
|
"os": "Linux",
|
||||||
},
|
},
|
||||||
Needs: map[string]Needs{
|
Needs: map[string]Needs{
|
||||||
@@ -637,7 +638,7 @@ func TestContexts(t *testing.T) {
|
|||||||
Result: "success",
|
Result: "success",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Inputs: map[string]interface{}{
|
Inputs: map[string]any{
|
||||||
"name": "value",
|
"name": "value",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -648,7 +649,7 @@ func TestContexts(t *testing.T) {
|
|||||||
tenv.EnvCS = tt.caseSensitiveEnv
|
tenv.EnvCS = tt.caseSensitiveEnv
|
||||||
tenv.CtxData = tt.ctxdata
|
tenv.CtxData = tt.ctxdata
|
||||||
output, err := NewInterpeter(&tenv, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
output, err := NewInterpeter(&tenv, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, tt.expected, output)
|
assert.Equal(t, tt.expected, output)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package filecollector
|
|||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
@@ -134,7 +135,7 @@ func (fc *FileCollector) CollectFiles(ctx context.Context, submodulePath []strin
|
|||||||
if ctx != nil {
|
if ctx != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return fmt.Errorf("copy cancelled")
|
return errors.New("copy cancelled")
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/go-git/go-git/v5/plumbing/format/index"
|
"github.com/go-git/go-git/v5/plumbing/format/index"
|
||||||
"github.com/go-git/go-git/v5/storage/filesystem"
|
"github.com/go-git/go-git/v5/storage/filesystem"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type memoryFs struct {
|
type memoryFs struct {
|
||||||
@@ -27,7 +28,7 @@ func (mfs *memoryFs) walk(root string, fn filepath.WalkFunc) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for i := 0; i < len(dir); i++ {
|
for i := range dir {
|
||||||
filename := filepath.Join(root, dir[i].Name())
|
filename := filepath.Join(root, dir[i].Name())
|
||||||
err = fn(filename, dir[i], nil)
|
err = fn(filename, dir[i], nil)
|
||||||
if dir[i].IsDir() {
|
if dir[i].IsDir() {
|
||||||
@@ -105,12 +106,12 @@ func TestIgnoredTrackedfile(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
|
err := fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
|
||||||
assert.NoError(t, err, "successfully collect files")
|
require.NoError(t, err, "successfully collect files")
|
||||||
tw.Close()
|
tw.Close()
|
||||||
_, _ = tmpTar.Seek(0, io.SeekStart)
|
_, _ = tmpTar.Seek(0, io.SeekStart)
|
||||||
tr := tar.NewReader(tmpTar)
|
tr := tar.NewReader(tmpTar)
|
||||||
h, err := tr.Next()
|
h, err := tr.Next()
|
||||||
assert.NoError(t, err, "tar must not be empty")
|
require.NoError(t, err, "tar must not be empty")
|
||||||
assert.Equal(t, ".gitignore", h.Name)
|
assert.Equal(t, ".gitignore", h.Name)
|
||||||
_, err = tr.Next()
|
_, err = tr.Next()
|
||||||
assert.ErrorIs(t, err, io.EOF, "tar must only contain one element")
|
assert.ErrorIs(t, err, io.EOF, "tar must only contain one element")
|
||||||
@@ -124,21 +125,21 @@ func TestSymlinks(t *testing.T) {
|
|||||||
repo, _ := git.Init(filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()), worktree)
|
repo, _ := git.Init(filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()), worktree)
|
||||||
// This file shouldn't be in the tar
|
// This file shouldn't be in the tar
|
||||||
f, err := worktree.Create(".env")
|
f, err := worktree.Create(".env")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = f.Write([]byte("test=val1\n"))
|
_, err = f.Write([]byte("test=val1\n"))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
f.Close()
|
f.Close()
|
||||||
err = worktree.Symlink(".env", "test.env")
|
err = worktree.Symlink(".env", "test.env")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
w, err := repo.Worktree()
|
w, err := repo.Worktree()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// .gitignore is in the tar after adding it to the index
|
// .gitignore is in the tar after adding it to the index
|
||||||
_, err = w.Add(".env")
|
_, err = w.Add(".env")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = w.Add("test.env")
|
_, err = w.Add("test.env")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tmpTar, _ := fs.Create("temp.tar")
|
tmpTar, _ := fs.Create("temp.tar")
|
||||||
tw := tar.NewWriter(tmpTar)
|
tw := tar.NewWriter(tmpTar)
|
||||||
@@ -154,7 +155,7 @@ func TestSymlinks(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
|
err = fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
|
||||||
assert.NoError(t, err, "successfully collect files")
|
require.NoError(t, err, "successfully collect files")
|
||||||
tw.Close()
|
tw.Close()
|
||||||
_, _ = tmpTar.Seek(0, io.SeekStart)
|
_, _ = tmpTar.Seek(0, io.SeekStart)
|
||||||
tr := tar.NewReader(tmpTar)
|
tr := tar.NewReader(tmpTar)
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ActionRunsUsing is the type of runner for the action
|
// ActionRunsUsing is the type of runner for the action
|
||||||
type ActionRunsUsing string
|
type ActionRunsUsing string
|
||||||
|
|
||||||
func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(any) error) error {
|
||||||
var using string
|
var using string
|
||||||
if err := unmarshal(&using); err != nil {
|
if err := unmarshal(&using); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package model
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,9 +17,9 @@ test:
|
|||||||
*node.Content[0].Content[1].Content[1] = yaml.Node{
|
*node.Content[0].Content[1].Content[1] = yaml.Node{
|
||||||
Kind: yaml.AliasNode,
|
Kind: yaml.AliasNode,
|
||||||
}
|
}
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = resolveAliases(&node)
|
err = resolveAliases(&node)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyNoRecursion(t *testing.T) {
|
func TestVerifyNoRecursion(t *testing.T) {
|
||||||
@@ -99,15 +99,15 @@ c: *a
|
|||||||
var node yaml.Node
|
var node yaml.Node
|
||||||
err := yaml.Unmarshal([]byte(tt.yaml), &node)
|
err := yaml.Unmarshal([]byte(tt.yaml), &node)
|
||||||
if tt.yamlErr {
|
if tt.yamlErr {
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = resolveAliases(&node)
|
err = resolveAliases(&node)
|
||||||
if tt.anchorErr {
|
if tt.anchorErr {
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
} else {
|
} else {
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,44 +5,44 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/common/git"
|
"gitea.com/gitea/act_runner/pkg/common/git"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GithubContext struct {
|
type GithubContext struct {
|
||||||
Event map[string]interface{} `json:"event"`
|
Event map[string]any `json:"event"`
|
||||||
EventPath string `json:"event_path"`
|
EventPath string `json:"event_path"`
|
||||||
Workflow string `json:"workflow"`
|
Workflow string `json:"workflow"`
|
||||||
RunAttempt string `json:"run_attempt"`
|
RunAttempt string `json:"run_attempt"`
|
||||||
RunID string `json:"run_id"`
|
RunID string `json:"run_id"`
|
||||||
RunNumber string `json:"run_number"`
|
RunNumber string `json:"run_number"`
|
||||||
Actor string `json:"actor"`
|
Actor string `json:"actor"`
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
EventName string `json:"event_name"`
|
EventName string `json:"event_name"`
|
||||||
Sha string `json:"sha"`
|
Sha string `json:"sha"`
|
||||||
Ref string `json:"ref"`
|
Ref string `json:"ref"`
|
||||||
RefName string `json:"ref_name"`
|
RefName string `json:"ref_name"`
|
||||||
RefType string `json:"ref_type"`
|
RefType string `json:"ref_type"`
|
||||||
HeadRef string `json:"head_ref"`
|
HeadRef string `json:"head_ref"`
|
||||||
BaseRef string `json:"base_ref"`
|
BaseRef string `json:"base_ref"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
Workspace string `json:"workspace"`
|
Workspace string `json:"workspace"`
|
||||||
Action string `json:"action"`
|
Action string `json:"action"`
|
||||||
ActionPath string `json:"action_path"`
|
ActionPath string `json:"action_path"`
|
||||||
ActionRef string `json:"action_ref"`
|
ActionRef string `json:"action_ref"`
|
||||||
ActionRepository string `json:"action_repository"`
|
ActionRepository string `json:"action_repository"`
|
||||||
Job string `json:"job"`
|
Job string `json:"job"`
|
||||||
JobName string `json:"job_name"`
|
JobName string `json:"job_name"`
|
||||||
RepositoryOwner string `json:"repository_owner"`
|
RepositoryOwner string `json:"repository_owner"`
|
||||||
RetentionDays string `json:"retention_days"`
|
RetentionDays string `json:"retention_days"`
|
||||||
RunnerPerflog string `json:"runner_perflog"`
|
RunnerPerflog string `json:"runner_perflog"`
|
||||||
RunnerTrackingID string `json:"runner_tracking_id"`
|
RunnerTrackingID string `json:"runner_tracking_id"`
|
||||||
ServerURL string `json:"server_url"`
|
ServerURL string `json:"server_url"`
|
||||||
APIURL string `json:"api_url"`
|
APIURL string `json:"api_url"`
|
||||||
GraphQLURL string `json:"graphql_url"`
|
GraphQLURL string `json:"graphql_url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func asString(v interface{}) string {
|
func asString(v any) string {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return ""
|
return ""
|
||||||
} else if s, ok := v.(string); ok {
|
} else if s, ok := v.(string); ok {
|
||||||
@@ -51,7 +51,7 @@ func asString(v interface{}) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) {
|
func nestedMapLookup(m map[string]any, ks ...string) (rval any) {
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
if len(ks) == 0 { // degenerate input
|
if len(ks) == 0 { // degenerate input
|
||||||
@@ -61,20 +61,20 @@ func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{})
|
|||||||
return nil
|
return nil
|
||||||
} else if len(ks) == 1 { // we've reached the final key
|
} else if len(ks) == 1 { // we've reached the final key
|
||||||
return rval
|
return rval
|
||||||
} else if m, ok = rval.(map[string]interface{}); !ok {
|
} else if m, ok = rval.(map[string]any); !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// 1+ more keys
|
// 1+ more keys
|
||||||
return nestedMapLookup(m, ks[1:]...)
|
return nestedMapLookup(m, ks[1:]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func withDefaultBranch(ctx context.Context, b string, event map[string]interface{}) map[string]interface{} {
|
func withDefaultBranch(ctx context.Context, b string, event map[string]any) map[string]any {
|
||||||
repoI, ok := event["repository"]
|
repoI, ok := event["repository"]
|
||||||
if !ok {
|
if !ok {
|
||||||
repoI = make(map[string]interface{})
|
repoI = make(map[string]any)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, ok := repoI.(map[string]interface{})
|
repo, ok := repoI.(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.Logger(ctx).Warnf("unable to set default branch to %v", b)
|
common.Logger(ctx).Warnf("unable to set default branch to %v", b)
|
||||||
return event
|
return event
|
||||||
@@ -101,19 +101,19 @@ func (ghc *GithubContext) SetRef(ctx context.Context, defaultBranch string, repo
|
|||||||
// https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads
|
// https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads
|
||||||
switch ghc.EventName {
|
switch ghc.EventName {
|
||||||
case "pull_request_target":
|
case "pull_request_target":
|
||||||
ghc.Ref = fmt.Sprintf("refs/heads/%s", ghc.BaseRef)
|
ghc.Ref = "refs/heads/" + ghc.BaseRef
|
||||||
case "pull_request", "pull_request_review", "pull_request_review_comment":
|
case "pull_request", "pull_request_review", "pull_request_review_comment":
|
||||||
ghc.Ref = fmt.Sprintf("refs/pull/%.0f/merge", ghc.Event["number"])
|
ghc.Ref = fmt.Sprintf("refs/pull/%.0f/merge", ghc.Event["number"])
|
||||||
case "deployment", "deployment_status":
|
case "deployment", "deployment_status":
|
||||||
ghc.Ref = asString(nestedMapLookup(ghc.Event, "deployment", "ref"))
|
ghc.Ref = asString(nestedMapLookup(ghc.Event, "deployment", "ref"))
|
||||||
case "release":
|
case "release":
|
||||||
ghc.Ref = fmt.Sprintf("refs/tags/%s", asString(nestedMapLookup(ghc.Event, "release", "tag_name")))
|
ghc.Ref = "refs/tags/" + asString(nestedMapLookup(ghc.Event, "release", "tag_name"))
|
||||||
case "push", "create", "workflow_dispatch":
|
case "push", "create", "workflow_dispatch":
|
||||||
ghc.Ref = asString(ghc.Event["ref"])
|
ghc.Ref = asString(ghc.Event["ref"])
|
||||||
default:
|
default:
|
||||||
defaultBranch := asString(nestedMapLookup(ghc.Event, "repository", "default_branch"))
|
defaultBranch := asString(nestedMapLookup(ghc.Event, "repository", "default_branch"))
|
||||||
if defaultBranch != "" {
|
if defaultBranch != "" {
|
||||||
ghc.Ref = fmt.Sprintf("refs/heads/%s", defaultBranch)
|
ghc.Ref = "refs/heads/" + defaultBranch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ func (ghc *GithubContext) SetRef(ctx context.Context, defaultBranch string, repo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ghc.Ref == "" {
|
if ghc.Ref == "" {
|
||||||
ghc.Ref = fmt.Sprintf("refs/heads/%s", asString(nestedMapLookup(ghc.Event, "repository", "default_branch")))
|
ghc.Ref = "refs/heads/" + asString(nestedMapLookup(ghc.Event, "repository", "default_branch"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@@ -27,19 +27,19 @@ func TestSetRef(t *testing.T) {
|
|||||||
|
|
||||||
tables := []struct {
|
tables := []struct {
|
||||||
eventName string
|
eventName string
|
||||||
event map[string]interface{}
|
event map[string]any
|
||||||
ref string
|
ref string
|
||||||
refName string
|
refName string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
eventName: "pull_request_target",
|
eventName: "pull_request_target",
|
||||||
event: map[string]interface{}{},
|
event: map[string]any{},
|
||||||
ref: "refs/heads/master",
|
ref: "refs/heads/master",
|
||||||
refName: "master",
|
refName: "master",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "pull_request",
|
eventName: "pull_request",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"number": 1234.,
|
"number": 1234.,
|
||||||
},
|
},
|
||||||
ref: "refs/pull/1234/merge",
|
ref: "refs/pull/1234/merge",
|
||||||
@@ -47,8 +47,8 @@ func TestSetRef(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "deployment",
|
eventName: "deployment",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"deployment": map[string]interface{}{
|
"deployment": map[string]any{
|
||||||
"ref": "refs/heads/somebranch",
|
"ref": "refs/heads/somebranch",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -57,8 +57,8 @@ func TestSetRef(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "release",
|
eventName: "release",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"release": map[string]interface{}{
|
"release": map[string]any{
|
||||||
"tag_name": "v1.0.0",
|
"tag_name": "v1.0.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -67,7 +67,7 @@ func TestSetRef(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "push",
|
eventName: "push",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"ref": "refs/heads/somebranch",
|
"ref": "refs/heads/somebranch",
|
||||||
},
|
},
|
||||||
ref: "refs/heads/somebranch",
|
ref: "refs/heads/somebranch",
|
||||||
@@ -75,8 +75,8 @@ func TestSetRef(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "unknown",
|
eventName: "unknown",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"repository": map[string]interface{}{
|
"repository": map[string]any{
|
||||||
"default_branch": "main",
|
"default_branch": "main",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -85,7 +85,7 @@ func TestSetRef(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "no-event",
|
eventName: "no-event",
|
||||||
event: map[string]interface{}{},
|
event: map[string]any{},
|
||||||
ref: "refs/heads/master",
|
ref: "refs/heads/master",
|
||||||
refName: "master",
|
refName: "master",
|
||||||
},
|
},
|
||||||
@@ -109,12 +109,12 @@ func TestSetRef(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("no-default-branch", func(t *testing.T) {
|
t.Run("no-default-branch", func(t *testing.T) {
|
||||||
findGitRef = func(_ context.Context, _ string) (string, error) {
|
findGitRef = func(_ context.Context, _ string) (string, error) {
|
||||||
return "", fmt.Errorf("no default branch")
|
return "", errors.New("no default branch")
|
||||||
}
|
}
|
||||||
|
|
||||||
ghc := &GithubContext{
|
ghc := &GithubContext{
|
||||||
EventName: "no-default-branch",
|
EventName: "no-default-branch",
|
||||||
Event: map[string]interface{}{},
|
Event: map[string]any{},
|
||||||
}
|
}
|
||||||
|
|
||||||
ghc.SetRef(context.Background(), "", "/some/dir")
|
ghc.SetRef(context.Background(), "", "/some/dir")
|
||||||
@@ -141,14 +141,14 @@ func TestSetSha(t *testing.T) {
|
|||||||
|
|
||||||
tables := []struct {
|
tables := []struct {
|
||||||
eventName string
|
eventName string
|
||||||
event map[string]interface{}
|
event map[string]any
|
||||||
sha string
|
sha string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
eventName: "pull_request_target",
|
eventName: "pull_request_target",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"pull_request": map[string]interface{}{
|
"pull_request": map[string]any{
|
||||||
"base": map[string]interface{}{
|
"base": map[string]any{
|
||||||
"sha": "pr-base-sha",
|
"sha": "pr-base-sha",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -157,15 +157,15 @@ func TestSetSha(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "pull_request",
|
eventName: "pull_request",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"number": 1234.,
|
"number": 1234.,
|
||||||
},
|
},
|
||||||
sha: "1234fakesha",
|
sha: "1234fakesha",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "deployment",
|
eventName: "deployment",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"deployment": map[string]interface{}{
|
"deployment": map[string]any{
|
||||||
"sha": "deployment-sha",
|
"sha": "deployment-sha",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -173,12 +173,12 @@ func TestSetSha(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "release",
|
eventName: "release",
|
||||||
event: map[string]interface{}{},
|
event: map[string]any{},
|
||||||
sha: "1234fakesha",
|
sha: "1234fakesha",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "push",
|
eventName: "push",
|
||||||
event: map[string]interface{}{
|
event: map[string]any{
|
||||||
"after": "push-sha",
|
"after": "push-sha",
|
||||||
"deleted": false,
|
"deleted": false,
|
||||||
},
|
},
|
||||||
@@ -186,12 +186,12 @@ func TestSetSha(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "unknown",
|
eventName: "unknown",
|
||||||
event: map[string]interface{}{},
|
event: map[string]any{},
|
||||||
sha: "1234fakesha",
|
sha: "1234fakesha",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventName: "no-event",
|
eventName: "no-event",
|
||||||
event: map[string]interface{}{},
|
event: map[string]any{},
|
||||||
sha: "1234fakesha",
|
sha: "1234fakesha",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"slices"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@@ -60,6 +60,13 @@ type PlannerConfig struct {
|
|||||||
Workflow WorkflowConfig
|
Workflow WorkflowConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CombineWorkflowPlanner combines workflows to a WorkflowPlanner
|
||||||
|
func CombineWorkflowPlanner(workflows ...*Workflow) WorkflowPlanner {
|
||||||
|
return &workflowPlanner{
|
||||||
|
workflows: workflows,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewWorkflowPlanner will load a specific workflow, all workflows from a directory or all workflows from a directory and its subdirectories
|
// NewWorkflowPlanner will load a specific workflow, all workflows from a directory or all workflows from a directory and its subdirectories
|
||||||
func NewWorkflowPlanner(path string, config PlannerConfig) (WorkflowPlanner, error) {
|
func NewWorkflowPlanner(path string, config PlannerConfig) (WorkflowPlanner, error) {
|
||||||
path, err := filepath.Abs(path)
|
path, err := filepath.Abs(path)
|
||||||
@@ -281,11 +288,8 @@ func (wp *workflowPlanner) GetEvents() []string {
|
|||||||
for _, w := range wp.workflows {
|
for _, w := range wp.workflows {
|
||||||
found := false
|
found := false
|
||||||
for _, e := range events {
|
for _, e := range events {
|
||||||
for _, we := range w.On() {
|
if slices.Contains(w.On(), e) {
|
||||||
if e == we {
|
found = true
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if found {
|
if found {
|
||||||
break
|
break
|
||||||
@@ -298,9 +302,7 @@ func (wp *workflowPlanner) GetEvents() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sort the list based on depth of dependencies
|
// sort the list based on depth of dependencies
|
||||||
sort.Slice(events, func(i, j int) bool {
|
slices.Sort(events)
|
||||||
return events[i] < events[j]
|
|
||||||
})
|
|
||||||
|
|
||||||
return events
|
return events
|
||||||
}
|
}
|
||||||
@@ -331,7 +333,7 @@ func (s *Stage) GetJobIDs() []string {
|
|||||||
// Merge stages with existing stages in plan
|
// Merge stages with existing stages in plan
|
||||||
func (p *Plan) mergeStages(stages []*Stage) {
|
func (p *Plan) mergeStages(stages []*Stage) {
|
||||||
newStages := make([]*Stage, int(math.Max(float64(len(p.Stages)), float64(len(stages)))))
|
newStages := make([]*Stage, int(math.Max(float64(len(p.Stages)), float64(len(stages)))))
|
||||||
for i := 0; i < len(newStages); i++ {
|
for i := range newStages {
|
||||||
newStages[i] = new(Stage)
|
newStages[i] = new(Stage)
|
||||||
if i >= len(p.Stages) {
|
if i >= len(p.Stages) {
|
||||||
newStages[i].Runs = append(newStages[i].Runs, stages[i].Runs...)
|
newStages[i].Runs = append(newStages[i].Runs, stages[i].Runs...)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WorkflowPlanTest struct {
|
type WorkflowPlanTest struct {
|
||||||
@@ -28,14 +29,14 @@ func TestPlanner(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
workdir, err := filepath.Abs("testdata")
|
workdir, err := filepath.Abs("testdata")
|
||||||
assert.NoError(t, err, workdir)
|
require.NoError(t, err, workdir)
|
||||||
for _, table := range tables {
|
for _, table := range tables {
|
||||||
fullWorkflowPath := filepath.Join(workdir, table.workflowPath)
|
fullWorkflowPath := filepath.Join(workdir, table.workflowPath)
|
||||||
_, err = NewWorkflowPlanner(fullWorkflowPath, PlannerConfig{
|
_, err = NewWorkflowPlanner(fullWorkflowPath, PlannerConfig{
|
||||||
Recursive: !table.noWorkflowRecurse,
|
Recursive: !table.noWorkflowRecurse,
|
||||||
})
|
})
|
||||||
if table.errorMessage == "" {
|
if table.errorMessage == "" {
|
||||||
assert.NoError(t, err, "WorkflowPlanner should exit without any error")
|
require.NoError(t, err, "WorkflowPlanner should exit without any error")
|
||||||
} else {
|
} else {
|
||||||
assert.EqualError(t, err, table.errorMessage)
|
assert.EqualError(t, err, table.errorMessage)
|
||||||
}
|
}
|
||||||
@@ -55,6 +56,6 @@ func TestWorkflow(t *testing.T) {
|
|||||||
|
|
||||||
// Check that a valid job id returns non-error
|
// Check that a valid job id returns non-error
|
||||||
result, err := createStages(&workflow, "valid_job")
|
result, err := createStages(&workflow, "valid_job")
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"maps"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/schema"
|
"gitea.com/gitea/act_runner/pkg/schema"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -61,7 +63,7 @@ func (w *Workflow) On() []string {
|
|||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
case yaml.MappingNode:
|
case yaml.MappingNode:
|
||||||
var val map[string]interface{}
|
var val map[string]any
|
||||||
err := w.RawOn.Decode(&val)
|
err := w.RawOn.Decode(&val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -75,9 +77,9 @@ func (w *Workflow) On() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Workflow) OnEvent(event string) interface{} {
|
func (w *Workflow) OnEvent(event string) any {
|
||||||
if w.RawOn.Kind == yaml.MappingNode {
|
if w.RawOn.Kind == yaml.MappingNode {
|
||||||
var val map[string]interface{}
|
var val map[string]any
|
||||||
if !decodeNode(w.RawOn, &val) {
|
if !decodeNode(w.RawOn, &val) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -128,10 +130,8 @@ func (w *Workflow) WorkflowDispatchConfig() *WorkflowDispatch {
|
|||||||
if !decodeNode(w.RawOn, &val) {
|
if !decodeNode(w.RawOn, &val) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, v := range val {
|
if slices.Contains(val, "workflow_dispatch") {
|
||||||
if v == "workflow_dispatch" {
|
return &WorkflowDispatch{}
|
||||||
return &WorkflowDispatch{}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case yaml.MappingNode:
|
case yaml.MappingNode:
|
||||||
var val map[string]yaml.Node
|
var val map[string]yaml.Node
|
||||||
@@ -206,7 +206,7 @@ type Job struct {
|
|||||||
Defaults Defaults `yaml:"defaults"`
|
Defaults Defaults `yaml:"defaults"`
|
||||||
Outputs map[string]string `yaml:"outputs"`
|
Outputs map[string]string `yaml:"outputs"`
|
||||||
Uses string `yaml:"uses"`
|
Uses string `yaml:"uses"`
|
||||||
With map[string]interface{} `yaml:"with"`
|
With map[string]any `yaml:"with"`
|
||||||
RawSecrets yaml.Node `yaml:"secrets"`
|
RawSecrets yaml.Node `yaml:"secrets"`
|
||||||
Result string
|
Result string
|
||||||
}
|
}
|
||||||
@@ -384,9 +384,9 @@ func (j *Job) Environment() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Matrix decodes RawMatrix YAML node
|
// Matrix decodes RawMatrix YAML node
|
||||||
func (j *Job) Matrix() map[string][]interface{} {
|
func (j *Job) Matrix() map[string][]any {
|
||||||
if j.Strategy.RawMatrix.Kind == yaml.MappingNode {
|
if j.Strategy.RawMatrix.Kind == yaml.MappingNode {
|
||||||
var val map[string][]interface{}
|
var val map[string][]any
|
||||||
if !decodeNode(j.Strategy.RawMatrix, &val) {
|
if !decodeNode(j.Strategy.RawMatrix, &val) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -397,32 +397,32 @@ func (j *Job) Matrix() map[string][]interface{} {
|
|||||||
|
|
||||||
// GetMatrixes returns the matrix cross product
|
// GetMatrixes returns the matrix cross product
|
||||||
// It skips includes and hard fails excludes for non-existing keys
|
// It skips includes and hard fails excludes for non-existing keys
|
||||||
func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
|
func (j *Job) GetMatrixes() ([]map[string]any, error) {
|
||||||
matrixes := make([]map[string]interface{}, 0)
|
matrixes := make([]map[string]any, 0)
|
||||||
if j.Strategy != nil {
|
if j.Strategy != nil {
|
||||||
j.Strategy.FailFast = j.Strategy.GetFailFast()
|
j.Strategy.FailFast = j.Strategy.GetFailFast()
|
||||||
j.Strategy.MaxParallel = j.Strategy.GetMaxParallel()
|
j.Strategy.MaxParallel = j.Strategy.GetMaxParallel()
|
||||||
|
|
||||||
if m := j.Matrix(); m != nil {
|
if m := j.Matrix(); m != nil {
|
||||||
includes := make([]map[string]interface{}, 0)
|
includes := make([]map[string]any, 0)
|
||||||
extraIncludes := make([]map[string]interface{}, 0)
|
extraIncludes := make([]map[string]any, 0)
|
||||||
for _, v := range m["include"] {
|
for _, v := range m["include"] {
|
||||||
switch t := v.(type) {
|
switch t := v.(type) {
|
||||||
case []interface{}:
|
case []any:
|
||||||
for _, i := range t {
|
for _, i := range t {
|
||||||
i := i.(map[string]interface{})
|
i := i.(map[string]any)
|
||||||
includes = append(includes, i)
|
includes = append(includes, i)
|
||||||
}
|
}
|
||||||
case interface{}:
|
case any:
|
||||||
v := v.(map[string]interface{})
|
v := v.(map[string]any)
|
||||||
includes = append(includes, v)
|
includes = append(includes, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(m, "include")
|
delete(m, "include")
|
||||||
|
|
||||||
excludes := make([]map[string]interface{}, 0)
|
excludes := make([]map[string]any, 0)
|
||||||
for _, e := range m["exclude"] {
|
for _, e := range m["exclude"] {
|
||||||
e := e.(map[string]interface{})
|
e := e.(map[string]any)
|
||||||
for k := range e {
|
for k := range e {
|
||||||
if _, ok := m[k]; ok {
|
if _, ok := m[k]; ok {
|
||||||
excludes = append(excludes, e)
|
excludes = append(excludes, e)
|
||||||
@@ -451,9 +451,7 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
|
|||||||
if commonKeysMatch2(matrix, include, m) {
|
if commonKeysMatch2(matrix, include, m) {
|
||||||
matched = true
|
matched = true
|
||||||
log.Debugf("Adding include values '%v' to existing entry", include)
|
log.Debugf("Adding include values '%v' to existing entry", include)
|
||||||
for k, v := range include {
|
maps.Copy(matrix, include)
|
||||||
matrix[k] = v
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !matched {
|
if !matched {
|
||||||
@@ -465,19 +463,19 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
|
|||||||
matrixes = append(matrixes, include)
|
matrixes = append(matrixes, include)
|
||||||
}
|
}
|
||||||
if len(matrixes) == 0 {
|
if len(matrixes) == 0 {
|
||||||
matrixes = append(matrixes, make(map[string]interface{}))
|
matrixes = append(matrixes, make(map[string]any))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
matrixes = append(matrixes, make(map[string]interface{}))
|
matrixes = append(matrixes, make(map[string]any))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
matrixes = append(matrixes, make(map[string]interface{}))
|
matrixes = append(matrixes, make(map[string]any))
|
||||||
log.Debugf("Empty Strategy, matrixes=%v", matrixes)
|
log.Debugf("Empty Strategy, matrixes=%v", matrixes)
|
||||||
}
|
}
|
||||||
return matrixes, nil
|
return matrixes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonKeysMatch(a map[string]interface{}, b map[string]interface{}) bool {
|
func commonKeysMatch(a map[string]any, b map[string]any) bool {
|
||||||
for aKey, aVal := range a {
|
for aKey, aVal := range a {
|
||||||
if bVal, ok := b[aKey]; ok && !reflect.DeepEqual(aVal, bVal) {
|
if bVal, ok := b[aKey]; ok && !reflect.DeepEqual(aVal, bVal) {
|
||||||
return false
|
return false
|
||||||
@@ -486,7 +484,7 @@ func commonKeysMatch(a map[string]interface{}, b map[string]interface{}) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonKeysMatch2(a map[string]interface{}, b map[string]interface{}, m map[string][]interface{}) bool {
|
func commonKeysMatch2(a map[string]any, b map[string]any, m map[string][]any) bool {
|
||||||
for aKey, aVal := range a {
|
for aKey, aVal := range a {
|
||||||
_, useKey := m[aKey]
|
_, useKey := m[aKey]
|
||||||
if bVal, ok := b[aKey]; useKey && ok && !reflect.DeepEqual(aVal, bVal) {
|
if bVal, ok := b[aKey]; useKey && ok && !reflect.DeepEqual(aVal, bVal) {
|
||||||
@@ -604,7 +602,7 @@ func (s *Step) GetEnv() map[string]string {
|
|||||||
|
|
||||||
for k, v := range s.With {
|
for k, v := range s.With {
|
||||||
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(k), "_")
|
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(k), "_")
|
||||||
envKey = fmt.Sprintf("INPUT_%s", strings.ToUpper(envKey))
|
envKey = "INPUT_" + strings.ToUpper(envKey)
|
||||||
env[envKey] = v
|
env[envKey] = v
|
||||||
}
|
}
|
||||||
return env
|
return env
|
||||||
@@ -752,11 +750,11 @@ func (w *Workflow) GetJobIDs() []string {
|
|||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
var OnDecodeNodeError = func(node yaml.Node, out interface{}, err error) {
|
var OnDecodeNodeError = func(node yaml.Node, out any, err error) {
|
||||||
log.Fatalf("Failed to decode node %v into %T: %v", node, out, err)
|
log.Fatalf("Failed to decode node %v into %T: %v", node, out, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeNode(node yaml.Node, out interface{}) bool {
|
func decodeNode(node yaml.Node, out any) bool {
|
||||||
if err := node.Decode(out); err != nil {
|
if err := node.Decode(out); err != nil {
|
||||||
if OnDecodeNodeError != nil {
|
if OnDecodeNodeError != nil {
|
||||||
OnDecodeNodeError(node, out, err)
|
OnDecodeNodeError(node, out, err)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
|
|
||||||
assert.Len(t, workflow.On(), 1)
|
assert.Len(t, workflow.On(), 1)
|
||||||
assert.Contains(t, workflow.On(), "push")
|
assert.Contains(t, workflow.On(), "push")
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
|
|
||||||
assert.Len(t, workflow.On(), 2)
|
assert.Len(t, workflow.On(), 2)
|
||||||
assert.Contains(t, workflow.On(), "push")
|
assert.Contains(t, workflow.On(), "push")
|
||||||
@@ -67,7 +67,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
assert.Len(t, workflow.On(), 2)
|
assert.Len(t, workflow.On(), 2)
|
||||||
assert.Contains(t, workflow.On(), "push")
|
assert.Contains(t, workflow.On(), "push")
|
||||||
assert.Contains(t, workflow.On(), "pull_request")
|
assert.Contains(t, workflow.On(), "pull_request")
|
||||||
@@ -86,8 +86,8 @@ jobs:
|
|||||||
- uses: ./actions/docker-url`
|
- uses: ./actions/docker-url`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest"})
|
assert.Equal(t, []string{"ubuntu-latest"}, workflow.Jobs["test"].RunsOn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadWorkflow_RunsOnLabelsWithGroup(t *testing.T) {
|
func TestReadWorkflow_RunsOnLabelsWithGroup(t *testing.T) {
|
||||||
@@ -104,8 +104,8 @@ jobs:
|
|||||||
- uses: ./actions/docker-url`
|
- uses: ./actions/docker-url`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest", "linux"})
|
assert.Equal(t, []string{"ubuntu-latest", "linux"}, workflow.Jobs["test"].RunsOn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadWorkflow_StringContainer(t *testing.T) {
|
func TestReadWorkflow_StringContainer(t *testing.T) {
|
||||||
@@ -129,7 +129,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
assert.Len(t, workflow.Jobs, 2)
|
assert.Len(t, workflow.Jobs, 2)
|
||||||
assert.Contains(t, workflow.Jobs["test"].Container().Image, "nginx:latest")
|
assert.Contains(t, workflow.Jobs["test"].Container().Image, "nginx:latest")
|
||||||
assert.Contains(t, workflow.Jobs["test2"].Container().Image, "nginx:latest")
|
assert.Contains(t, workflow.Jobs["test2"].Container().Image, "nginx:latest")
|
||||||
@@ -159,7 +159,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
assert.Len(t, workflow.Jobs, 1)
|
assert.Len(t, workflow.Jobs, 1)
|
||||||
|
|
||||||
container := workflow.GetJob("test").Container()
|
container := workflow.GetJob("test").Container()
|
||||||
@@ -197,31 +197,31 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
assert.Len(t, workflow.Jobs, 6)
|
assert.Len(t, workflow.Jobs, 6)
|
||||||
|
|
||||||
jobType, err := workflow.Jobs["default-job"].Type()
|
jobType, err := workflow.Jobs["default-job"].Type()
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, JobTypeDefault, jobType)
|
assert.Equal(t, JobTypeDefault, jobType)
|
||||||
|
|
||||||
jobType, err = workflow.Jobs["remote-reusable-workflow-yml"].Type()
|
jobType, err = workflow.Jobs["remote-reusable-workflow-yml"].Type()
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
|
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
|
||||||
|
|
||||||
jobType, err = workflow.Jobs["remote-reusable-workflow-yaml"].Type()
|
jobType, err = workflow.Jobs["remote-reusable-workflow-yaml"].Type()
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
|
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
|
||||||
|
|
||||||
jobType, err = workflow.Jobs["remote-reusable-workflow-custom-path"].Type()
|
jobType, err = workflow.Jobs["remote-reusable-workflow-custom-path"].Type()
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
|
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
|
||||||
|
|
||||||
jobType, err = workflow.Jobs["local-reusable-workflow-yml"].Type()
|
jobType, err = workflow.Jobs["local-reusable-workflow-yml"].Type()
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, JobTypeReusableWorkflowLocal, jobType)
|
assert.Equal(t, JobTypeReusableWorkflowLocal, jobType)
|
||||||
|
|
||||||
jobType, err = workflow.Jobs["local-reusable-workflow-yaml"].Type()
|
jobType, err = workflow.Jobs["local-reusable-workflow-yaml"].Type()
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, JobTypeReusableWorkflowLocal, jobType)
|
assert.Equal(t, JobTypeReusableWorkflowLocal, jobType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,24 +241,24 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
assert.Len(t, workflow.Jobs, 4)
|
assert.Len(t, workflow.Jobs, 4)
|
||||||
|
|
||||||
jobType, err := workflow.Jobs["remote-reusable-workflow-missing-version"].Type()
|
jobType, err := workflow.Jobs["remote-reusable-workflow-missing-version"].Type()
|
||||||
assert.Equal(t, JobTypeInvalid, jobType)
|
assert.Equal(t, JobTypeInvalid, jobType)
|
||||||
assert.NotEqual(t, nil, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
jobType, err = workflow.Jobs["remote-reusable-workflow-bad-extension"].Type()
|
jobType, err = workflow.Jobs["remote-reusable-workflow-bad-extension"].Type()
|
||||||
assert.Equal(t, JobTypeInvalid, jobType)
|
assert.Equal(t, JobTypeInvalid, jobType)
|
||||||
assert.NotEqual(t, nil, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
jobType, err = workflow.Jobs["local-reusable-workflow-bad-extension"].Type()
|
jobType, err = workflow.Jobs["local-reusable-workflow-bad-extension"].Type()
|
||||||
assert.Equal(t, JobTypeInvalid, jobType)
|
assert.Equal(t, JobTypeInvalid, jobType)
|
||||||
assert.NotEqual(t, nil, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
jobType, err = workflow.Jobs["local-reusable-workflow-bad-path"].Type()
|
jobType, err = workflow.Jobs["local-reusable-workflow-bad-path"].Type()
|
||||||
assert.Equal(t, JobTypeInvalid, jobType)
|
assert.Equal(t, JobTypeInvalid, jobType)
|
||||||
assert.NotEqual(t, nil, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadWorkflow_StepsTypes(t *testing.T) {
|
func TestReadWorkflow_StepsTypes(t *testing.T) {
|
||||||
@@ -283,7 +283,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
_, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
_, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.Error(t, err, "read workflow should fail")
|
require.Error(t, err, "read workflow should fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
// See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs
|
// See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs
|
||||||
@@ -315,7 +315,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
assert.Len(t, workflow.Jobs, 2)
|
assert.Len(t, workflow.Jobs, 2)
|
||||||
|
|
||||||
assert.Len(t, workflow.Jobs["test1"].Steps, 1)
|
assert.Len(t, workflow.Jobs["test1"].Steps, 1)
|
||||||
@@ -330,76 +330,74 @@ jobs:
|
|||||||
|
|
||||||
func TestReadWorkflow_Strategy(t *testing.T) {
|
func TestReadWorkflow_Strategy(t *testing.T) {
|
||||||
w, err := NewWorkflowPlanner("testdata/strategy/push.yml", PlannerConfig{})
|
w, err := NewWorkflowPlanner("testdata/strategy/push.yml", PlannerConfig{})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
p, err := w.PlanJob("strategy-only-max-parallel")
|
p, err := w.PlanJob("strategy-only-max-parallel")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, len(p.Stages), 1)
|
assert.Len(t, p.Stages, 1)
|
||||||
assert.Equal(t, len(p.Stages[0].Runs), 1)
|
assert.Len(t, p.Stages[0].Runs, 1)
|
||||||
|
|
||||||
wf := p.Stages[0].Runs[0].Workflow
|
wf := p.Stages[0].Runs[0].Workflow
|
||||||
|
|
||||||
job := wf.Jobs["strategy-only-max-parallel"]
|
job := wf.Jobs["strategy-only-max-parallel"]
|
||||||
matrixes, err := job.GetMatrixes()
|
matrixes, err := job.GetMatrixes()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, matrixes, []map[string]interface{}{{}})
|
assert.Equal(t, []map[string]any{{}}, matrixes)
|
||||||
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
|
assert.Equal(t, job.Matrix(), map[string][]any(nil))
|
||||||
assert.Equal(t, job.Strategy.MaxParallel, 2)
|
assert.Equal(t, 2, job.Strategy.MaxParallel)
|
||||||
assert.Equal(t, job.Strategy.FailFast, true)
|
assert.True(t, job.Strategy.FailFast)
|
||||||
|
|
||||||
job = wf.Jobs["strategy-only-fail-fast"]
|
job = wf.Jobs["strategy-only-fail-fast"]
|
||||||
matrixes, err = job.GetMatrixes()
|
matrixes, err = job.GetMatrixes()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, matrixes, []map[string]interface{}{{}})
|
assert.Equal(t, []map[string]any{{}}, matrixes)
|
||||||
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
|
assert.Equal(t, job.Matrix(), map[string][]any(nil))
|
||||||
assert.Equal(t, job.Strategy.MaxParallel, 4)
|
assert.Equal(t, 4, job.Strategy.MaxParallel)
|
||||||
assert.Equal(t, job.Strategy.FailFast, false)
|
assert.False(t, job.Strategy.FailFast)
|
||||||
|
|
||||||
job = wf.Jobs["strategy-no-matrix"]
|
job = wf.Jobs["strategy-no-matrix"]
|
||||||
matrixes, err = job.GetMatrixes()
|
matrixes, err = job.GetMatrixes()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, matrixes, []map[string]interface{}{{}})
|
assert.Equal(t, []map[string]any{{}}, matrixes)
|
||||||
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
|
assert.Equal(t, job.Matrix(), map[string][]any(nil))
|
||||||
assert.Equal(t, job.Strategy.MaxParallel, 2)
|
assert.Equal(t, 2, job.Strategy.MaxParallel)
|
||||||
assert.Equal(t, job.Strategy.FailFast, false)
|
assert.False(t, job.Strategy.FailFast)
|
||||||
|
|
||||||
job = wf.Jobs["strategy-all"]
|
job = wf.Jobs["strategy-all"]
|
||||||
matrixes, err = job.GetMatrixes()
|
matrixes, err = job.GetMatrixes()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, matrixes,
|
assert.Equal(t, []map[string]any{
|
||||||
[]map[string]interface{}{
|
{"datacenter": "site-c", "node-version": "14.x", "site": "staging", "php-version": 5.4},
|
||||||
{"datacenter": "site-c", "node-version": "14.x", "site": "staging", "php-version": 5.4},
|
{"datacenter": "site-c", "node-version": "16.x", "site": "staging", "php-version": 5.4},
|
||||||
{"datacenter": "site-c", "node-version": "16.x", "site": "staging", "php-version": 5.4},
|
{"datacenter": "site-d", "node-version": "16.x", "site": "staging", "php-version": 5.4},
|
||||||
{"datacenter": "site-d", "node-version": "16.x", "site": "staging", "php-version": 5.4},
|
{"datacenter": "site-a", "node-version": "10.x", "site": "prod"},
|
||||||
{"datacenter": "site-a", "node-version": "10.x", "site": "prod"},
|
{"datacenter": "site-b", "node-version": "12.x", "site": "dev"},
|
||||||
{"datacenter": "site-b", "node-version": "12.x", "site": "dev"},
|
}, matrixes,
|
||||||
},
|
|
||||||
)
|
)
|
||||||
assert.Equal(t, job.Matrix(),
|
assert.Equal(t, map[string][]any{
|
||||||
map[string][]interface{}{
|
"datacenter": {"site-c", "site-d"},
|
||||||
"datacenter": {"site-c", "site-d"},
|
"exclude": {
|
||||||
"exclude": {
|
map[string]any{"datacenter": "site-d", "node-version": "14.x", "site": "staging"},
|
||||||
map[string]interface{}{"datacenter": "site-d", "node-version": "14.x", "site": "staging"},
|
|
||||||
},
|
|
||||||
"include": {
|
|
||||||
map[string]interface{}{"php-version": 5.4},
|
|
||||||
map[string]interface{}{"datacenter": "site-a", "node-version": "10.x", "site": "prod"},
|
|
||||||
map[string]interface{}{"datacenter": "site-b", "node-version": "12.x", "site": "dev"},
|
|
||||||
},
|
|
||||||
"node-version": {"14.x", "16.x"},
|
|
||||||
"site": {"staging"},
|
|
||||||
},
|
},
|
||||||
|
"include": {
|
||||||
|
map[string]any{"php-version": 5.4},
|
||||||
|
map[string]any{"datacenter": "site-a", "node-version": "10.x", "site": "prod"},
|
||||||
|
map[string]any{"datacenter": "site-b", "node-version": "12.x", "site": "dev"},
|
||||||
|
},
|
||||||
|
"node-version": {"14.x", "16.x"},
|
||||||
|
"site": {"staging"},
|
||||||
|
}, job.Matrix(),
|
||||||
)
|
)
|
||||||
assert.Equal(t, job.Strategy.MaxParallel, 2)
|
assert.Equal(t, 2, job.Strategy.MaxParallel)
|
||||||
assert.Equal(t, job.Strategy.FailFast, false)
|
assert.False(t, job.Strategy.FailFast)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMatrixOnlyIncludes(t *testing.T) {
|
func TestMatrixOnlyIncludes(t *testing.T) {
|
||||||
matrix := map[string][]interface{}{
|
matrix := map[string][]any{
|
||||||
"include": []interface{}{
|
"include": []any{
|
||||||
map[string]interface{}{"a": "1", "b": "2"},
|
map[string]any{"a": "1", "b": "2"},
|
||||||
map[string]interface{}{"a": "3", "b": "4"},
|
map[string]any{"a": "3", "b": "4"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
rN := yaml.Node{}
|
rN := yaml.Node{}
|
||||||
@@ -413,11 +411,10 @@ func TestMatrixOnlyIncludes(t *testing.T) {
|
|||||||
assert.Equal(t, job.Matrix(), matrix)
|
assert.Equal(t, job.Matrix(), matrix)
|
||||||
matrixes, err := job.GetMatrixes()
|
matrixes, err := job.GetMatrixes()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, matrixes,
|
assert.Equal(t, []map[string]any{
|
||||||
[]map[string]interface{}{
|
{"a": "1", "b": "2"},
|
||||||
{"a": "1", "b": "2"},
|
{"a": "3", "b": "4"},
|
||||||
{"a": "3", "b": "4"},
|
}, matrixes,
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,7 +433,7 @@ func TestStep_ShellCommand(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.shell, func(t *testing.T) {
|
t.Run(tt.shell, func(t *testing.T) {
|
||||||
got := (&Step{Shell: tt.shell, WorkflowShell: tt.workflowShell}).ShellCommand()
|
got := (&Step{Shell: tt.shell, WorkflowShell: tt.workflowShell}).ShellCommand()
|
||||||
assert.Equal(t, got, tt.want)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -452,7 +449,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
|||||||
- run: echo Test
|
- run: echo Test
|
||||||
`
|
`
|
||||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
workflowDispatch := workflow.WorkflowDispatchConfig()
|
workflowDispatch := workflow.WorkflowDispatchConfig()
|
||||||
assert.Nil(t, workflowDispatch)
|
assert.Nil(t, workflowDispatch)
|
||||||
|
|
||||||
@@ -466,7 +463,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
|||||||
- run: echo Test
|
- run: echo Test
|
||||||
`
|
`
|
||||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||||
assert.NotNil(t, workflowDispatch)
|
assert.NotNil(t, workflowDispatch)
|
||||||
assert.Nil(t, workflowDispatch.Inputs)
|
assert.Nil(t, workflowDispatch.Inputs)
|
||||||
@@ -481,7 +478,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
|||||||
- run: echo Test
|
- run: echo Test
|
||||||
`
|
`
|
||||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||||
assert.Nil(t, workflowDispatch)
|
assert.Nil(t, workflowDispatch)
|
||||||
|
|
||||||
@@ -495,7 +492,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
|||||||
- run: echo Test
|
- run: echo Test
|
||||||
`
|
`
|
||||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||||
assert.NotNil(t, workflowDispatch)
|
assert.NotNil(t, workflowDispatch)
|
||||||
assert.Nil(t, workflowDispatch.Inputs)
|
assert.Nil(t, workflowDispatch.Inputs)
|
||||||
@@ -512,7 +509,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
|||||||
- run: echo Test
|
- run: echo Test
|
||||||
`
|
`
|
||||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||||
assert.NotNil(t, workflowDispatch)
|
assert.NotNil(t, workflowDispatch)
|
||||||
assert.Nil(t, workflowDispatch.Inputs)
|
assert.Nil(t, workflowDispatch.Inputs)
|
||||||
@@ -529,7 +526,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
|||||||
- run: echo Test
|
- run: echo Test
|
||||||
`
|
`
|
||||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||||
assert.Nil(t, workflowDispatch)
|
assert.Nil(t, workflowDispatch)
|
||||||
|
|
||||||
@@ -556,7 +553,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
|||||||
- run: echo Test
|
- run: echo Test
|
||||||
`
|
`
|
||||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||||
assert.NotNil(t, workflowDispatch)
|
assert.NotNil(t, workflowDispatch)
|
||||||
assert.Equal(t, WorkflowDispatchInput{
|
assert.Equal(t, WorkflowDispatchInput{
|
||||||
@@ -585,7 +582,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
_, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{Strict: true})
|
_, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{Strict: true})
|
||||||
assert.Error(t, err, "read workflow should succeed")
|
require.Error(t, err, "read workflow should succeed")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadWorkflow_AnchorStrict(t *testing.T) {
|
func TestReadWorkflow_AnchorStrict(t *testing.T) {
|
||||||
@@ -604,7 +601,7 @@ jobs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
w, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{Strict: true})
|
w, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{Strict: true})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
|
|
||||||
for _, job := range w.Jobs {
|
for _, job := range w.Jobs {
|
||||||
assert.Equal(t, []string{"ubuntu-latest"}, job.RunsOn())
|
assert.Equal(t, []string{"ubuntu-latest"}, job.RunsOn())
|
||||||
@@ -632,7 +629,7 @@ on: push #*trigger
|
|||||||
`
|
`
|
||||||
|
|
||||||
w, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
w, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||||
assert.NoError(t, err, "read workflow should succeed")
|
require.NoError(t, err, "read workflow should succeed")
|
||||||
|
|
||||||
for _, job := range w.Jobs {
|
for _, job := range w.Jobs {
|
||||||
assert.Equal(t, []string{"ubuntu-latest"}, job.RunsOn())
|
assert.Equal(t, []string{"ubuntu-latest"}, job.RunsOn())
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import (
|
|||||||
|
|
||||||
"github.com/kballard/go-shellquote"
|
"github.com/kballard/go-shellquote"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/container"
|
"gitea.com/gitea/act_runner/pkg/container"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type actionStep interface {
|
type actionStep interface {
|
||||||
@@ -154,14 +154,14 @@ func execAsDocker(ctx context.Context, step actionStep, actionName, subpath stri
|
|||||||
var prepImage common.Executor
|
var prepImage common.Executor
|
||||||
var image string
|
var image string
|
||||||
forcePull := false
|
forcePull := false
|
||||||
if strings.HasPrefix(action.Runs.Image, "docker://") {
|
if after, ok := strings.CutPrefix(action.Runs.Image, "docker://"); ok {
|
||||||
image = strings.TrimPrefix(action.Runs.Image, "docker://")
|
image = after
|
||||||
// Apply forcePull only for prebuild docker images
|
// Apply forcePull only for prebuild docker images
|
||||||
forcePull = rc.Config.ForcePull
|
forcePull = rc.Config.ForcePull
|
||||||
} else {
|
} else {
|
||||||
// "-dockeraction" ensures that "./", "./test " won't get converted to "act-:latest", "act-test-:latest" which are invalid docker image names
|
// "-dockeraction" ensures that "./", "./test " won't get converted to "act-:latest", "act-test-:latest" which are invalid docker image names
|
||||||
image = fmt.Sprintf("%s-dockeraction:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-"), "latest")
|
image = fmt.Sprintf("%s-dockeraction:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-"), "latest")
|
||||||
image = fmt.Sprintf("act-%s", strings.TrimLeft(image, "-"))
|
image = "act-" + strings.TrimLeft(image, "-")
|
||||||
image = strings.ToLower(image)
|
image = strings.ToLower(image)
|
||||||
contextDir, fileName := path.Split(path.Join(subpath, action.Runs.Image))
|
contextDir, fileName := path.Split(path.Join(subpath, action.Runs.Image))
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ func newStepContainer(ctx context.Context, step step, image string, cmd []string
|
|||||||
envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TEMP", "/tmp"))
|
envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TEMP", "/tmp"))
|
||||||
|
|
||||||
binds, mounts := rc.GetBindsAndMounts()
|
binds, mounts := rc.GetBindsAndMounts()
|
||||||
networkMode := fmt.Sprintf("container:%s", rc.jobContainerName())
|
networkMode := "container:" + rc.jobContainerName()
|
||||||
var workdir string
|
var workdir string
|
||||||
if rc.IsHostEnv(ctx) {
|
if rc.IsHostEnv(ctx) {
|
||||||
networkMode = "default"
|
networkMode = "default"
|
||||||
@@ -333,7 +333,7 @@ func populateEnvsFromSavedState(env *map[string]string, step actionStep, rc *Run
|
|||||||
state, ok := rc.IntraActionState[step.getStepModel().ID]
|
state, ok := rc.IntraActionState[step.getStepModel().ID]
|
||||||
if ok {
|
if ok {
|
||||||
for name, value := range state {
|
for name, value := range state {
|
||||||
envName := fmt.Sprintf("STATE_%s", name)
|
envName := "STATE_" + name
|
||||||
(*env)[envName] = value
|
(*env)[envName] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -343,7 +343,7 @@ func populateEnvsFromInput(ctx context.Context, env *map[string]string, action *
|
|||||||
eval := rc.NewExpressionEvaluator(ctx)
|
eval := rc.NewExpressionEvaluator(ctx)
|
||||||
for inputID, input := range action.Inputs {
|
for inputID, input := range action.Inputs {
|
||||||
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_")
|
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_")
|
||||||
envKey = fmt.Sprintf("INPUT_%s", envKey)
|
envKey = "INPUT_" + envKey
|
||||||
if _, ok := (*env)[envKey]; !ok {
|
if _, ok := (*env)[envKey]; !ok {
|
||||||
(*env)[envKey] = eval.Interpolate(ctx, input.Default)
|
(*env)[envKey] = eval.Interpolate(ctx, input.Default)
|
||||||
}
|
}
|
||||||
@@ -429,7 +429,7 @@ func runPreStep(step actionStep) common.Executor {
|
|||||||
if steps := step.getCompositeSteps(); steps != nil && steps.pre != nil {
|
if steps := step.getCompositeSteps(); steps != nil && steps.pre != nil {
|
||||||
return steps.pre(ctx)
|
return steps.pre(ctx)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("missing steps in composite action")
|
return errors.New("missing steps in composite action")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
@@ -512,7 +512,7 @@ func runPostStep(step actionStep) common.Executor {
|
|||||||
if steps := step.getCompositeSteps(); steps != nil && steps.post != nil {
|
if steps := step.getCompositeSteps(); steps != nil && steps.post != nil {
|
||||||
return steps.post(ctx)
|
return steps.post(ctx)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("missing steps in composite action")
|
return errors.New("missing steps in composite action")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
git "github.com/go-git/go-git/v5"
|
git "github.com/go-git/go-git/v5"
|
||||||
config "github.com/go-git/go-git/v5/config"
|
config "github.com/go-git/go-git/v5/config"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
git "github.com/go-git/go-git/v5"
|
git "github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gosec
|
//nolint:gosec
|
||||||
@@ -69,7 +70,7 @@ func TestActionCache(t *testing.T) {
|
|||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
// G110: Potential DoS vulnerability via decompression bomb (gosec)
|
// G110: Potential DoS vulnerability via decompression bomb (gosec)
|
||||||
_, err = io.Copy(buf, mytar)
|
_, err = io.Copy(buf, mytar)
|
||||||
a.NoError(err)
|
require.NoError(t, err)
|
||||||
str := buf.String()
|
str := buf.String()
|
||||||
a.NotEmpty(str)
|
a.NotEmpty(str)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package runner
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func evaluateCompositeInputAndEnv(ctx context.Context, parent *RunContext, step actionStep) map[string]string {
|
func evaluateCompositeInputAndEnv(ctx context.Context, parent *RunContext, step actionStep) map[string]string {
|
||||||
@@ -25,7 +26,7 @@ func evaluateCompositeInputAndEnv(ctx context.Context, parent *RunContext, step
|
|||||||
|
|
||||||
for inputID, input := range step.getActionModel().Inputs {
|
for inputID, input := range step.getActionModel().Inputs {
|
||||||
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_")
|
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_")
|
||||||
envKey = fmt.Sprintf("INPUT_%s", strings.ToUpper(envKey))
|
envKey = "INPUT_" + strings.ToUpper(envKey)
|
||||||
|
|
||||||
// lookup if key is defined in the step but the already
|
// lookup if key is defined in the step but the already
|
||||||
// evaluated value from the environment
|
// evaluated value from the environment
|
||||||
@@ -77,7 +78,7 @@ func newCompositeRunContext(ctx context.Context, parent *RunContext, step action
|
|||||||
nodeToolFullPath: parent.nodeToolFullPath,
|
nodeToolFullPath: parent.nodeToolFullPath,
|
||||||
}
|
}
|
||||||
if parent.ContextData != nil {
|
if parent.ContextData != nil {
|
||||||
compositerc.ContextData = map[string]interface{}{}
|
compositerc.ContextData = map[string]any{}
|
||||||
for k, v := range parent.ContextData {
|
for k, v := range parent.ContextData {
|
||||||
if !strings.EqualFold("inputs", k) {
|
if !strings.EqualFold("inputs", k) {
|
||||||
compositerc.ContextData[k] = v
|
compositerc.ContextData[k] = v
|
||||||
@@ -99,7 +100,7 @@ func execAsComposite(step actionStep) common.Executor {
|
|||||||
steps := step.getCompositeSteps()
|
steps := step.getCompositeSteps()
|
||||||
|
|
||||||
if steps == nil || steps.main == nil {
|
if steps == nil || steps.main == nil {
|
||||||
return fmt.Errorf("missing steps in composite action")
|
return errors.New("missing steps in composite action")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = WithCompositeLogger(ctx, &compositeRC.Masks)
|
ctx = WithCompositeLogger(ctx, &compositeRC.Masks)
|
||||||
@@ -147,7 +148,7 @@ func (rc *RunContext) compositeExecutor(action *model.Action) *compositeSteps {
|
|||||||
|
|
||||||
for i, step := range action.Runs.Steps {
|
for i, step := range action.Runs.Steps {
|
||||||
if step.ID == "" {
|
if step.ID == "" {
|
||||||
step.ID = fmt.Sprintf("%d", i)
|
step.ID = strconv.Itoa(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a copy of the step, since this composite action could
|
// create a copy of the step, since this composite action could
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type closerMock struct {
|
type closerMock struct {
|
||||||
@@ -99,7 +100,7 @@ runs:
|
|||||||
|
|
||||||
action, err := readActionImpl(context.Background(), tt.step, readFile, model.ActionConfig{})
|
action, err := readActionImpl(context.Background(), tt.step, readFile, model.ActionConfig{})
|
||||||
|
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, tt.expected, action)
|
assert.Equal(t, tt.expected, action)
|
||||||
|
|
||||||
closerMock.AssertExpectations(t)
|
closerMock.AssertExpectations(t)
|
||||||
@@ -218,7 +219,7 @@ func TestActionRunner(t *testing.T) {
|
|||||||
|
|
||||||
err := runActionImpl(tt.step)(ctx)
|
err := runActionImpl(tt.step)(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
cm.AssertExpectations(t)
|
cm.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -133,8 +133,8 @@ func (rc *RunContext) addPath(ctx context.Context, arg string) {
|
|||||||
|
|
||||||
func parseKeyValuePairs(kvPairs string, separator string) map[string]string {
|
func parseKeyValuePairs(kvPairs string, separator string) map[string]string {
|
||||||
rtn := make(map[string]string)
|
rtn := make(map[string]string)
|
||||||
kvPairList := strings.Split(kvPairs, separator)
|
kvPairList := strings.SplitSeq(kvPairs, separator)
|
||||||
for _, kvPair := range kvPairList {
|
for kvPair := range kvPairList {
|
||||||
kv := strings.Split(kvPair, "=")
|
kv := strings.Split(kvPair, "=")
|
||||||
if len(kv) == 2 {
|
if len(kv) == 2 {
|
||||||
rtn[kv[0]] = kv[1]
|
rtn[kv[0]] = kv[1]
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
"github.com/sirupsen/logrus/hooks/test"
|
"github.com/sirupsen/logrus/hooks/test"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetEnv(t *testing.T) {
|
func TestSetEnv(t *testing.T) {
|
||||||
@@ -164,7 +164,7 @@ func TestAddmaskUsemask(t *testing.T) {
|
|||||||
|
|
||||||
re := captureOutput(t, func() {
|
re := captureOutput(t, func() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = WithJobLogger(ctx, "0", "testjob", config, &rc.Masks, map[string]interface{}{})
|
ctx = WithJobLogger(ctx, "0", "testjob", config, &rc.Masks, map[string]any{})
|
||||||
|
|
||||||
handler := rc.commandHandler(ctx)
|
handler := rc.commandHandler(ctx)
|
||||||
handler("::add-mask::secret\n")
|
handler("::add-mask::secret\n")
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/container"
|
"gitea.com/gitea/act_runner/pkg/container"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package runner
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"maps"
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -12,16 +14,16 @@ import (
|
|||||||
|
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/container"
|
"gitea.com/gitea/act_runner/pkg/container"
|
||||||
"github.com/actions-oss/act-cli/pkg/exprparser"
|
"gitea.com/gitea/act_runner/pkg/exprparser"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExpressionEvaluator is the interface for evaluating expressions
|
// ExpressionEvaluator is the interface for evaluating expressions
|
||||||
type ExpressionEvaluator interface {
|
type ExpressionEvaluator interface {
|
||||||
evaluate(context.Context, string, exprparser.DefaultStatusCheck) (interface{}, error)
|
evaluate(context.Context, string, exprparser.DefaultStatusCheck) (any, error)
|
||||||
EvaluateYamlNode(context.Context, *yaml.Node) error
|
EvaluateYamlNode(context.Context, *yaml.Node) error
|
||||||
Interpolate(context.Context, string) string
|
Interpolate(context.Context, string) string
|
||||||
}
|
}
|
||||||
@@ -36,7 +38,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map
|
|||||||
|
|
||||||
// todo: cleanup EvaluationEnvironment creation
|
// todo: cleanup EvaluationEnvironment creation
|
||||||
using := make(map[string]exprparser.Needs)
|
using := make(map[string]exprparser.Needs)
|
||||||
strategy := make(map[string]interface{})
|
strategy := make(map[string]any)
|
||||||
if rc.Run != nil {
|
if rc.Run != nil {
|
||||||
job := rc.Run.Job()
|
job := rc.Run.Job()
|
||||||
if job != nil && job.Strategy != nil {
|
if job != nil && job.Strategy != nil {
|
||||||
@@ -64,9 +66,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map
|
|||||||
result := model.WorkflowCallResult{
|
result := model.WorkflowCallResult{
|
||||||
Outputs: map[string]string{},
|
Outputs: map[string]string{},
|
||||||
}
|
}
|
||||||
for k, v := range job.Outputs {
|
maps.Copy(result.Outputs, job.Outputs)
|
||||||
result.Outputs[k] = v
|
|
||||||
}
|
|
||||||
workflowCallResult[jobName] = &result
|
workflowCallResult[jobName] = &result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,10 +123,10 @@ func (rc *RunContext) NewStepExpressionEvaluatorExt(ctx context.Context, step st
|
|||||||
return rc.newStepExpressionEvaluator(ctx, step, ghc, getEvaluatorInputs(ctx, rc, step, ghc))
|
return rc.newStepExpressionEvaluator(ctx, step, ghc, getEvaluatorInputs(ctx, rc, step, ghc))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RunContext) newStepExpressionEvaluator(ctx context.Context, step step, _ *model.GithubContext, inputs map[string]interface{}) ExpressionEvaluator {
|
func (rc *RunContext) newStepExpressionEvaluator(ctx context.Context, step step, _ *model.GithubContext, inputs map[string]any) ExpressionEvaluator {
|
||||||
// todo: cleanup EvaluationEnvironment creation
|
// todo: cleanup EvaluationEnvironment creation
|
||||||
job := rc.Run.Job()
|
job := rc.Run.Job()
|
||||||
strategy := make(map[string]interface{})
|
strategy := make(map[string]any)
|
||||||
if job.Strategy != nil {
|
if job.Strategy != nil {
|
||||||
strategy["fail-fast"] = job.Strategy.FailFast
|
strategy["fail-fast"] = job.Strategy.FailFast
|
||||||
strategy["max-parallel"] = job.Strategy.MaxParallel
|
strategy["max-parallel"] = job.Strategy.MaxParallel
|
||||||
@@ -173,8 +173,8 @@ func (rc *RunContext) newStepExpressionEvaluator(ctx context.Context, step step,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.Value) (interface{}, error) {
|
func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.Value) (any, error) {
|
||||||
hashFiles := func(v []reflect.Value) (interface{}, error) {
|
hashFiles := func(v []reflect.Value) (any, error) {
|
||||||
if rc.JobContainer != nil {
|
if rc.JobContainer != nil {
|
||||||
timeed, cancel := context.WithTimeout(ctx, time.Minute)
|
timeed, cancel := context.WithTimeout(ctx, time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -198,9 +198,7 @@ func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.
|
|||||||
patterns = append(patterns, s)
|
patterns = append(patterns, s)
|
||||||
}
|
}
|
||||||
env := map[string]string{}
|
env := map[string]string{}
|
||||||
for k, v := range rc.Env {
|
maps.Copy(env, rc.Env)
|
||||||
env[k] = v
|
|
||||||
}
|
|
||||||
env["patterns"] = strings.Join(patterns, "\n")
|
env["patterns"] = strings.Join(patterns, "\n")
|
||||||
if followSymlink {
|
if followSymlink {
|
||||||
env["followSymbolicLinks"] = "true"
|
env["followSymbolicLinks"] = "true"
|
||||||
@@ -238,7 +236,7 @@ type expressionEvaluator struct {
|
|||||||
interpreter exprparser.Interpreter
|
interpreter exprparser.Interpreter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ee expressionEvaluator) evaluate(ctx context.Context, in string, defaultStatusCheck exprparser.DefaultStatusCheck) (interface{}, error) {
|
func (ee expressionEvaluator) evaluate(ctx context.Context, in string, defaultStatusCheck exprparser.DefaultStatusCheck) (any, error) {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
logger.Debugf("evaluating expression '%s'", in)
|
logger.Debugf("evaluating expression '%s'", in)
|
||||||
evaluated, err := ee.interpreter.Evaluate(in, defaultStatusCheck)
|
evaluated, err := ee.interpreter.Evaluate(in, defaultStatusCheck)
|
||||||
@@ -434,7 +432,7 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str
|
|||||||
if strStart > -1 {
|
if strStart > -1 {
|
||||||
matches := strPattern.FindStringIndex(in[pos:])
|
matches := strPattern.FindStringIndex(in[pos:])
|
||||||
if matches == nil {
|
if matches == nil {
|
||||||
panic("unclosed string.")
|
return "", errors.New("unclosed string.")
|
||||||
}
|
}
|
||||||
|
|
||||||
strStart = -1
|
strStart = -1
|
||||||
@@ -485,8 +483,8 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]interface{} {
|
func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]any {
|
||||||
inputs := map[string]interface{}{}
|
inputs := map[string]any{}
|
||||||
|
|
||||||
setupWorkflowInputs(ctx, &inputs, rc)
|
setupWorkflowInputs(ctx, &inputs, rc)
|
||||||
|
|
||||||
@@ -498,8 +496,8 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range env {
|
for k, v := range env {
|
||||||
if strings.HasPrefix(k, "INPUT_") {
|
if after, ok := strings.CutPrefix(k, "INPUT_"); ok {
|
||||||
inputs[strings.ToLower(strings.TrimPrefix(k, "INPUT_"))] = v
|
inputs[strings.ToLower(after)] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +521,7 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
|
|||||||
return inputs
|
return inputs
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupWorkflowInputs(ctx context.Context, inputs *map[string]interface{}, rc *RunContext) {
|
func setupWorkflowInputs(ctx context.Context, inputs *map[string]any, rc *RunContext) {
|
||||||
if rc.caller != nil {
|
if rc.caller != nil {
|
||||||
config := rc.Run.Workflow.WorkflowCallConfig()
|
config := rc.Run.Workflow.WorkflowCallConfig()
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,23 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/exprparser"
|
"gitea.com/gitea/act_runner/pkg/exprparser"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
assert "github.com/stretchr/testify/assert"
|
assert "github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
yaml "gopkg.in/yaml.v3"
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createRunContext(t *testing.T) *RunContext {
|
func createRunContext(t *testing.T) *RunContext {
|
||||||
var yml yaml.Node
|
var yml yaml.Node
|
||||||
err := yml.Encode(map[string][]interface{}{
|
err := yml.Encode(map[string][]any{
|
||||||
"os": {"Linux", "Windows"},
|
"os": {"Linux", "Windows"},
|
||||||
"foo": {"bar", "baz"},
|
"foo": {"bar", "baz"},
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return &RunContext{
|
return &RunContext{
|
||||||
Config: &Config{
|
Config: &Config{
|
||||||
@@ -48,7 +50,7 @@ func createRunContext(t *testing.T) *RunContext {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Matrix: map[string]interface{}{
|
Matrix: map[string]any{
|
||||||
"os": "Linux",
|
"os": "Linux",
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
@@ -84,7 +86,7 @@ func TestEvaluateRunContext(t *testing.T) {
|
|||||||
|
|
||||||
tables := []struct {
|
tables := []struct {
|
||||||
in string
|
in string
|
||||||
out interface{}
|
out any
|
||||||
errMesg string
|
errMesg string
|
||||||
}{
|
}{
|
||||||
{" 1 ", 1, ""},
|
{" 1 ", 1, ""},
|
||||||
@@ -142,7 +144,7 @@ func TestEvaluateRunContext(t *testing.T) {
|
|||||||
assertObject := assert.New(t)
|
assertObject := assert.New(t)
|
||||||
out, err := ee.evaluate(context.Background(), table.in, exprparser.DefaultStatusCheckNone)
|
out, err := ee.evaluate(context.Background(), table.in, exprparser.DefaultStatusCheckNone)
|
||||||
if table.errMesg == "" {
|
if table.errMesg == "" {
|
||||||
assertObject.NoError(err, table.in)
|
require.NoError(t, err, table.in)
|
||||||
if i, ok := table.out.(int); ok {
|
if i, ok := table.out.(int); ok {
|
||||||
table.out = float64(i)
|
table.out = float64(i)
|
||||||
}
|
}
|
||||||
@@ -165,7 +167,7 @@ func TestEvaluateStep(t *testing.T) {
|
|||||||
|
|
||||||
tables := []struct {
|
tables := []struct {
|
||||||
in string
|
in string
|
||||||
out interface{}
|
out any
|
||||||
errMesg string
|
errMesg string
|
||||||
}{
|
}{
|
||||||
{"steps.idwithnothing.conclusion", model.StepStatusSuccess.String(), ""},
|
{"steps.idwithnothing.conclusion", model.StepStatusSuccess.String(), ""},
|
||||||
@@ -184,10 +186,10 @@ func TestEvaluateStep(t *testing.T) {
|
|||||||
assertObject := assert.New(t)
|
assertObject := assert.New(t)
|
||||||
out, err := ee.evaluate(context.Background(), table.in, exprparser.DefaultStatusCheckNone)
|
out, err := ee.evaluate(context.Background(), table.in, exprparser.DefaultStatusCheckNone)
|
||||||
if table.errMesg == "" {
|
if table.errMesg == "" {
|
||||||
assertObject.NoError(err, table.in)
|
require.NoError(t, err, table.in)
|
||||||
assertObject.Equal(table.out, out, table.in)
|
assertObject.Equal(table.out, out, table.in)
|
||||||
} else {
|
} else {
|
||||||
assertObject.Error(err, table.in)
|
require.Error(t, err, table.in)
|
||||||
assertObject.Equal(table.errMesg, err.Error(), table.in)
|
assertObject.Equal(table.errMesg, err.Error(), table.in)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -281,9 +283,11 @@ func updateTestExpressionWorkflow(t *testing.T, tables []struct {
|
|||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
var envsSb284 strings.Builder
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
envs += fmt.Sprintf(" %s: %s\n", k, rc.Env[k])
|
fmt.Fprintf(&envsSb284, " %s: %s\n", k, rc.Env[k])
|
||||||
}
|
}
|
||||||
|
envs += envsSb284.String()
|
||||||
|
|
||||||
// editorconfig-checker-disable
|
// editorconfig-checker-disable
|
||||||
workflow := fmt.Sprintf(`
|
workflow := fmt.Sprintf(`
|
||||||
@@ -299,6 +303,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
`, envs)
|
`, envs)
|
||||||
// editorconfig-checker-enable
|
// editorconfig-checker-enable
|
||||||
|
var workflowSb302 strings.Builder
|
||||||
for _, table := range tables {
|
for _, table := range tables {
|
||||||
expressionPattern := regexp.MustCompile(`\${{\s*(.+?)\s*}}`)
|
expressionPattern := regexp.MustCompile(`\${{\s*(.+?)\s*}}`)
|
||||||
|
|
||||||
@@ -307,8 +312,9 @@ jobs:
|
|||||||
})
|
})
|
||||||
name := fmt.Sprintf(`%s -> %s should be equal to %s`, expr, table.in, table.out)
|
name := fmt.Sprintf(`%s -> %s should be equal to %s`, expr, table.in, table.out)
|
||||||
echo := `run: echo "Done "`
|
echo := `run: echo "Done "`
|
||||||
workflow += fmt.Sprintf("\n - name: %s\n %s\n", name, echo)
|
fmt.Fprintf(&workflowSb302, "\n - name: %s\n %s\n", name, echo)
|
||||||
}
|
}
|
||||||
|
workflow += workflowSb302.String()
|
||||||
|
|
||||||
file, err := os.Create("../../.github/workflows/test-expressions.yml")
|
file, err := os.Create("../../.github/workflows/test-expressions.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -3,14 +3,15 @@ package runner
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type jobInfo interface {
|
type jobInfo interface {
|
||||||
matrix() map[string]interface{}
|
matrix() map[string]any
|
||||||
steps() []*model.Step
|
steps() []*model.Step
|
||||||
startContainer() common.Executor
|
startContainer() common.Executor
|
||||||
stopContainer() common.Executor
|
stopContainer() common.Executor
|
||||||
@@ -70,7 +71,7 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if stepModel.ID == "" {
|
if stepModel.ID == "" {
|
||||||
stepModel.ID = fmt.Sprintf("%d", i)
|
stepModel.ID = strconv.Itoa(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
step, err := sf.newStep(stepModel, rc)
|
step, err := sf.newStep(stepModel, rc)
|
||||||
|
|||||||
@@ -2,15 +2,17 @@ package runner
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/container"
|
"gitea.com/gitea/act_runner/pkg/container"
|
||||||
"github.com/actions-oss/act-cli/pkg/model"
|
"gitea.com/gitea/act_runner/pkg/model"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestJobExecutor(t *testing.T) {
|
func TestJobExecutor(t *testing.T) {
|
||||||
@@ -38,9 +40,9 @@ type jobInfoMock struct {
|
|||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jim *jobInfoMock) matrix() map[string]interface{} {
|
func (jim *jobInfoMock) matrix() map[string]any {
|
||||||
args := jim.Called()
|
args := jim.Called()
|
||||||
return args.Get(0).(map[string]interface{})
|
return args.Get(0).(map[string]any)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jim *jobInfoMock) steps() []*model.Step {
|
func (jim *jobInfoMock) steps() []*model.Step {
|
||||||
@@ -232,17 +234,12 @@ func TestNewJobExecutor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contains := func(needle string, haystack []string) bool {
|
contains := func(needle string, haystack []string) bool {
|
||||||
for _, item := range haystack {
|
return slices.Contains(haystack, needle)
|
||||||
if item == needle {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range table {
|
for _, tt := range table {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
fmt.Printf("::group::%s\n", tt.name)
|
t.Log("::group::%s\n", tt.name)
|
||||||
|
|
||||||
ctx := common.WithJobErrorContainer(context.Background())
|
ctx := common.WithJobErrorContainer(context.Background())
|
||||||
jim := &jobInfoMock{}
|
jim := &jobInfoMock{}
|
||||||
@@ -287,7 +284,7 @@ func TestNewJobExecutor(t *testing.T) {
|
|||||||
sm.On("main").Return(func(_ context.Context) error {
|
sm.On("main").Return(func(_ context.Context) error {
|
||||||
executorOrder = append(executorOrder, "step"+stepModel.ID)
|
executorOrder = append(executorOrder, "step"+stepModel.ID)
|
||||||
if tt.hasError {
|
if tt.hasError {
|
||||||
return fmt.Errorf("error")
|
return errors.New("error")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -303,7 +300,7 @@ func TestNewJobExecutor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(tt.steps) > 0 {
|
if len(tt.steps) > 0 {
|
||||||
jim.On("matrix").Return(map[string]interface{}{})
|
jim.On("matrix").Return(map[string]any{})
|
||||||
|
|
||||||
jim.On("interpolateOutputs").Return(func(_ context.Context) error {
|
jim.On("interpolateOutputs").Return(func(_ context.Context) error {
|
||||||
executorOrder = append(executorOrder, "interpolateOutputs")
|
executorOrder = append(executorOrder, "interpolateOutputs")
|
||||||
@@ -327,13 +324,13 @@ func TestNewJobExecutor(t *testing.T) {
|
|||||||
|
|
||||||
executor := newJobExecutor(jim, sfm, rc)
|
executor := newJobExecutor(jim, sfm, rc)
|
||||||
err := executor(ctx)
|
err := executor(ctx)
|
||||||
assert.Nil(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, tt.executedSteps, executorOrder)
|
assert.Equal(t, tt.executedSteps, executorOrder)
|
||||||
|
|
||||||
jim.AssertExpectations(t)
|
jim.AssertExpectations(t)
|
||||||
sfm.AssertExpectations(t)
|
sfm.AssertExpectations(t)
|
||||||
|
|
||||||
fmt.Println("::endgroup::")
|
t.Log("::endgroup::")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
"github.com/actions-oss/act-cli/pkg/filecollector"
|
"gitea.com/gitea/act_runner/pkg/filecollector"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LocalRepositoryCache struct {
|
type LocalRepositoryCache struct {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/actions-oss/act-cli/pkg/common"
|
"gitea.com/gitea/act_runner/pkg/common"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
@@ -70,7 +70,7 @@ func WithJobLoggerFactory(ctx context.Context, factory JobLoggerFactory) context
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithJobLogger attaches a new logger to context that is aware of steps
|
// WithJobLogger attaches a new logger to context that is aware of steps
|
||||||
func WithJobLogger(ctx context.Context, jobID string, jobName string, config *Config, masks *[]string, matrix map[string]interface{}) context.Context {
|
func WithJobLogger(ctx context.Context, jobID string, jobName string, config *Config, masks *[]string, matrix map[string]any) context.Context {
|
||||||
ctx = WithMasks(ctx, masks)
|
ctx = WithMasks(ctx, masks)
|
||||||
|
|
||||||
var logger *logrus.Logger
|
var logger *logrus.Logger
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user