8 Commits

Author SHA1 Message Date
Christopher Homberger
09d18916bf more lint errors 2026-02-23 00:30:44 +01:00
Christopher Homberger
bffc600775 fixes 2026-02-22 21:12:25 +01:00
Christopher Homberger
a27473e6a8 fixes 2026-02-22 21:04:33 +01:00
Christopher Homberger
a77f10683d assert => require 2026-02-22 21:00:42 +01:00
Christopher Homberger
d187ac2fc1 auto adjust code 2026-02-22 20:58:46 +01:00
Christopher Homberger
949a40c7a5 Merge https://gitea.com/actions-oss/act-cli into act-runner-merged 2026-02-22 20:56:21 +01:00
Christopher Homberger
3413919161 update import path 2026-02-22 20:54:58 +01:00
Christopher Homberger
40ee0f3ef6 feat: add act runner compat code (#35)
* attempt to build an act_runner using this implementation of act with minimal changes on act side.

Reviewed-on: https://gitea.com/actions-oss/act-cli/pulls/35
Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
Co-committed-by: Christopher Homberger <christopher.homberger@web.de>
2026-02-20 20:06:04 +00:00
127 changed files with 1089 additions and 1013 deletions

View File

@@ -3,8 +3,8 @@ package cmd
import (
"os"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/model"
)
func drawGraph(plan *model.Plan) error {

View File

@@ -5,7 +5,7 @@ import (
"strconv"
"strings"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/model"
)
func printList(plan *model.Plan) error {

View File

@@ -5,12 +5,14 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"runtime"
"runtime/debug"
"strconv"
"strings"
"github.com/AlecAivazis/survey/v2"
@@ -25,14 +27,14 @@ import (
"github.com/spf13/pflag"
"gopkg.in/yaml.v3"
"github.com/actions-oss/act-cli/pkg/artifactcache"
"github.com/actions-oss/act-cli/pkg/artifacts"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/container"
"github.com/actions-oss/act-cli/pkg/gh"
"github.com/actions-oss/act-cli/pkg/model"
"github.com/actions-oss/act-cli/pkg/runner"
"github.com/actions-oss/act-cli/pkg/schema"
"gitea.com/gitea/act_runner/pkg/artifactcache"
"gitea.com/gitea/act_runner/pkg/artifacts"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/container"
"gitea.com/gitea/act_runner/pkg/gh"
"gitea.com/gitea/act_runner/pkg/model"
"gitea.com/gitea/act_runner/pkg/runner"
"gitea.com/gitea/act_runner/pkg/schema"
)
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("GOOS:", runtime.GOOS)
report += sprintf("GOARCH:", runtime.GOARCH)
report += sprintf("NumCPU:", fmt.Sprint(runtime.NumCPU()))
report += sprintf("NumCPU:", strconv.Itoa(runtime.NumCPU()))
var dockerHost string
var exists bool
@@ -199,15 +201,21 @@ func bugReport(ctx context.Context, version string) error {
}
report += sprintf("Config files:", "")
var reportSb202 strings.Builder
var reportSb205 strings.Builder
for _, c := range configLocations() {
args := readArgsFile(c, false)
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 {
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()
if ok && vcs != nil {
@@ -220,9 +228,11 @@ func bugReport(ctx context.Context, version string) error {
report += sprintf("\tMain checksum:", vcs.Main.Sum)
report += fmt.Sprintln("\tBuild settings:")
var reportSb223 strings.Builder
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)
@@ -245,13 +255,15 @@ func bugReport(ctx context.Context, version string) error {
report += sprintf("\tOS version:", info.OSVersion)
report += sprintf("\tOS arch:", info.Architecture)
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 += fmt.Sprintln("\tSecurity options:")
var reportSb252 strings.Builder
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)
return nil
@@ -261,7 +273,7 @@ func generateManPage(cmd *cobra.Command) error {
header := &doc.GenManHeader{
Title: "act",
Section: "1",
Source: fmt.Sprintf("act %s", cmd.Version),
Source: "act " + cmd.Version,
}
buf := new(bytes.Buffer)
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 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 {
@@ -611,7 +623,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
log.Warnf(deprecationWarning, "privileged", "--privileged")
}
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 {
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
if eventName == "workflow_call" {
// 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 {
var raw interface{}
var raw any
if err := yaml.Unmarshal([]byte(v), &raw); err != nil {
return fmt.Errorf("failed to unmarshal input %s: %w", k, err)
}

View File

@@ -7,6 +7,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestReadSecrets(t *testing.T) {
@@ -34,7 +35,7 @@ func TestListOptions(t *testing.T) {
err := newRunCommand(context.Background(), &Input{
listOptions: true,
})(rootCmd, []string{})
assert.NoError(t, err)
require.NoError(t, err)
}
func TestRun(t *testing.T) {
@@ -44,7 +45,7 @@ func TestRun(t *testing.T) {
workdir: "../pkg/runner/testdata/",
workflowsPath: "./basic/push.yml",
})(rootCmd, []string{})
assert.NoError(t, err)
require.NoError(t, err)
}
func TestRunPush(t *testing.T) {
@@ -54,7 +55,7 @@ func TestRunPush(t *testing.T) {
workdir: "../pkg/runner/testdata/",
workflowsPath: "./basic/push.yml",
})(rootCmd, []string{"push"})
assert.NoError(t, err)
require.NoError(t, err)
}
func TestRunPushJsonLogger(t *testing.T) {
@@ -65,7 +66,7 @@ func TestRunPushJsonLogger(t *testing.T) {
workflowsPath: "./basic/push.yml",
jsonLogger: true,
})(rootCmd, []string{"push"})
assert.NoError(t, err)
require.NoError(t, err)
}
func TestFlags(t *testing.T) {
@@ -73,13 +74,13 @@ func TestFlags(t *testing.T) {
t.Run("TestFlag-"+f, func(t *testing.T) {
rootCmd := createRootCommand(context.Background(), &Input{}, "")
err := rootCmd.Flags().Set(f, "true")
assert.NoError(t, err)
require.NoError(t, err)
err = newRunCommand(context.Background(), &Input{
platforms: []string{"ubuntu-latest=node:16-buster-slim"},
workdir: "../pkg/runner/testdata/",
workflowsPath: "./basic/push.yml",
})(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",
inputs: []string{"required=required input", "boolean=true"},
})(rootCmd, []string{"workflow_call"})
assert.NoError(t, err)
require.NoError(t, err)
}
func TestLocalRepositories(t *testing.T) {
@@ -105,5 +106,5 @@ func TestLocalRepositories(t *testing.T) {
workflowsPath: "./remote-action-composite-action-ref-partial-override/push.yml",
localRepository: []string{"needs/override@main=" + wd + "/actions-environment-and-context-tests"},
})(rootCmd, []string{"push"})
assert.NoError(t, err)
require.NoError(t, err)
}

60
go.mod
View File

@@ -21,71 +21,83 @@ require (
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 (
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/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/cespare/xxhash/v2 v2.3.0 // 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/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/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/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emirpasic/gods v1.18.1 // 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/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/stdr v1.2.2 // 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/google/go-cmp v0.7.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // 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/klauspost/compress v1.18.4 // 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/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/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // 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/pkg/errors v0.9.1 // 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/skeema/knownhosts v1.3.2 // indirect
github.com/spf13/pflag v1.0.10 // 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/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // 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/contrib/instrumentation/net/http/otelhttp v0.65.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/trace v1.40.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/sync v0.19.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
gopkg.in/warnings.v0 v0.1.2 // indirect
)

37
go.sum
View File

@@ -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=
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/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/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
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.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
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/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/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
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/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
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/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/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
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/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/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/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
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.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
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/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/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
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/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/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
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.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
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/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
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.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
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/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
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/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=
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-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.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
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/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
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/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-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-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-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
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/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-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/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-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-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-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-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-20220722155257-8c9f86f7a55f/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.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/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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
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.3/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/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
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-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.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/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -0,0 +1 @@
0.4.0

View 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)
}

View File

@@ -10,7 +10,7 @@ import (
"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"
"github.com/spf13/cobra"
)

View File

@@ -15,12 +15,12 @@ import (
"strings"
"gitea.com/gitea/act_runner/internal/app/run"
"github.com/actions-oss/act-cli/pkg/artifactcache"
"github.com/actions-oss/act-cli/pkg/artifacts"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/model"
"github.com/actions-oss/act-cli/pkg/runner"
"github.com/actions-oss/act-cli/pkg/schema"
"gitea.com/gitea/act_runner/pkg/artifactcache"
"gitea.com/gitea/act_runner/pkg/artifacts"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/model"
"gitea.com/gitea/act_runner/pkg/runner"
"gitea.com/gitea/act_runner/pkg/schema"
"github.com/docker/docker/api/types/container"
"github.com/joho/godotenv"
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 {
return func(cmd *cobra.Command, args []string) error {
return func(_ *cobra.Command, args []string) error {
planner, err := model.NewWorkflowPlanner(execArgs.WorkflowsPath(), model.PlannerConfig{
Recursive: !execArgs.noWorkflowRecurse,
Workflow: model.WorkflowConfig{

View File

@@ -6,7 +6,7 @@ package cmd
import (
"testing"
"gotest.tools/v3/assert"
"github.com/stretchr/testify/require"
)
func TestRegisterNonInteractiveReturnsLabelValidationError(t *testing.T) {
@@ -15,5 +15,5 @@ func TestRegisterNonInteractiveReturnsLabelValidationError(t *testing.T) {
Token: "token",
InstanceAddr: "http://localhost:3000",
})
assert.Error(t, err, "unsupported schema: invalid")
require.Error(t, err, "unsupported schema: invalid")
}

View File

@@ -9,15 +9,16 @@ import (
"fmt"
"maps"
"path/filepath"
"strconv"
"strings"
"sync"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"connectrpc.com/connect"
"github.com/actions-oss/act-cli/pkg/artifactcache"
"github.com/actions-oss/act-cli/pkg/model"
"github.com/actions-oss/act-cli/pkg/runner"
"github.com/actions-oss/act-cli/pkg/schema"
"gitea.com/gitea/act_runner/pkg/artifactcache"
"gitea.com/gitea/act_runner/pkg/model"
"gitea.com/gitea/act_runner/pkg/runner"
"gitea.com/gitea/act_runner/pkg/schema"
"github.com/docker/docker/api/types/container"
log "github.com/sirupsen/logrus"
@@ -145,7 +146,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
var stepIds []string
for i, v := range job.Steps {
if v.ID == "" {
v.ID = fmt.Sprint(i)
v.ID = strconv.Itoa(i)
}
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)
// }
actCtx := map[string]interface{}{}
actCtx := map[string]any{}
forgeCtx := task.Context.AsMap()
actCtx["github"] = forgeCtx
actCtx["gitea"] = forgeCtx

View File

@@ -10,8 +10,8 @@ import (
"strings"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"github.com/actions-oss/act-cli/pkg/model"
"github.com/actions-oss/act-cli/pkg/schema"
"gitea.com/gitea/act_runner/pkg/model"
"gitea.com/gitea/act_runner/pkg/schema"
"gopkg.in/yaml.v3"
)

View File

@@ -7,7 +7,7 @@ import (
"testing"
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"
"go.yaml.in/yaml/v4"
"gotest.tools/v3/assert"

View File

@@ -10,7 +10,7 @@ import (
// It behaves like the C# implementation in the repository
// it supports escaped braces and numeric argument indices.
// 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
i := 0
for i < len(formatStr) {
@@ -47,7 +47,7 @@ func Format(formatStr string, args ...interface{}) (string, error) {
}
// append argument (format specifier is ignored here)
arg := args[idx]
sb.WriteString(fmt.Sprintf("%v", arg))
fmt.Fprintf(&sb, "%v", arg)
if spec != "" {
// placeholder for future specifier handling
_ = spec

View File

@@ -1,14 +1,13 @@
package functions
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFormat(t *testing.T) {
s, err := Format("Hello {0}, you have {1} new messages", "Alice", 5)
assert.NoError(t, err)
fmt.Println(s) // Hello Alice, you have 5 new messages
_, err := Format("Hello {0}, you have {1} new messages", "Alice", 5)
require.NoError(t, err)
// fmt.Println(s) // Hello Alice, you have 5 new messages
}

View File

@@ -93,14 +93,14 @@ func (o CaseSensitiveObject[T]) GetEnumerator() map[string]T {
type EvaluationResult struct {
context *EvaluationContext
level int
value interface{}
value any
kind ValueKind
raw interface{}
raw any
omitTracing bool
}
// 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}
if !omitTracing {
er.traceValue()
@@ -112,10 +112,10 @@ func NewEvaluationResult(context *EvaluationContext, level int, val interface{},
func (er *EvaluationResult) Kind() ValueKind { return er.kind }
// 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.
func (er *EvaluationResult) Value() interface{} { return er.value }
func (er *EvaluationResult) Value() any { return er.value }
// IsFalsy implements the logic from the C# class.
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.
func (er *EvaluationResult) TryGetCollectionInterface() (interface{}, bool) {
func (er *EvaluationResult) TryGetCollectionInterface() (any, bool) {
switch v := er.value.(type) {
case ReadOnlyArray[any]:
return v, true
@@ -207,7 +207,7 @@ func (er *EvaluationResult) TryGetCollectionInterface() (interface{}, bool) {
}
// 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)
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.
func convertToCanonicalValue(obj interface{}) (interface{}, ValueKind, interface{}) {
func convertToCanonicalValue(obj any) (any, ValueKind, any) {
switch v := obj.(type) {
case nil:
return nil, ValueKindNull, nil
@@ -243,11 +243,11 @@ func convertToCanonicalValue(obj interface{}) (interface{}, ValueKind, interface
return f, ValueKindNumber, f
case string:
return v, ValueKindString, v
case []interface{}:
case []any:
return BasicArray[any](v), ValueKindArray, v
case ReadOnlyArray[any]:
return v, ValueKindArray, v
case map[string]interface{}:
case map[string]any:
return CaseInsensitiveObject[any](v), ValueKindObject, v
case ReadOnlyObject[any]:
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) {
case int:
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) {
case uint:
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) {
case float32:
return float64(f)
@@ -304,7 +304,7 @@ func toFloat64(v interface{}) float64 {
// coerceTypes implements the C# CoerceTypes logic.
// 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)
rightKind := getKind(right)
@@ -340,7 +340,7 @@ func coerceTypes(left, right interface{}) (interface{}, interface{}, ValueKind,
}
// abstractEqual uses coerceTypes before comparing.
func abstractEqual(left, right interface{}) bool {
func abstractEqual(left, right any) bool {
left, right, leftKind, rightKind := coerceTypes(left, right)
if leftKind != rightKind {
return false
@@ -367,7 +367,7 @@ func abstractEqual(left, right interface{}) bool {
}
// abstractGreaterThan uses coerceTypes before comparing.
func abstractGreaterThan(left, right interface{}) bool {
func abstractGreaterThan(left, right any) bool {
left, right, leftKind, rightKind := coerceTypes(left, right)
if leftKind != rightKind {
return false
@@ -389,7 +389,7 @@ func abstractGreaterThan(left, right interface{}) bool {
}
// abstractLessThan uses coerceTypes before comparing.
func abstractLessThan(left, right interface{}) bool {
func abstractLessThan(left, right any) bool {
left, right, leftKind, rightKind := coerceTypes(left, right)
if leftKind != rightKind {
return false
@@ -411,7 +411,7 @@ func abstractLessThan(left, right interface{}) bool {
}
// convertToNumber converts a value to a float64 following JavaScript rules.
func convertToNumber(v interface{}) float64 {
func convertToNumber(v any) float64 {
switch val := v.(type) {
case nil:
return 0
@@ -447,7 +447,7 @@ func convertToNumber(v interface{}) float64 {
}
// getKind returns the ValueKind for a Go value.
func getKind(v interface{}) ValueKind {
func getKind(v any) ValueKind {
switch v.(type) {
case nil:
return ValueKindNull
@@ -457,9 +457,9 @@ func getKind(v interface{}) ValueKind {
return ValueKindNumber
case string:
return ValueKindString
case []interface{}:
case []any:
return ValueKindArray
case map[string]interface{}:
case map[string]any:
return ValueKindObject
default:
return ValueKindObject

View File

@@ -4,7 +4,7 @@ import (
"errors"
"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.
@@ -56,11 +56,11 @@ func (e *Evaluator) EvaluateBoolean(expr string) (bool, error) {
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 {
switch node := col.(type) {
case ReadOnlyObject[any]:
rawMap := map[string]interface{}{}
rawMap := map[string]any{}
for k, v := range node.GetEnumerator() {
rawRes, err := e.ToRaw(CreateIntermediateResult(e.Context(), v))
if err != nil {
@@ -70,7 +70,7 @@ func (e *Evaluator) ToRaw(result *EvaluationResult) (interface{}, error) {
}
return rawMap, nil
case ReadOnlyArray[any]:
rawArray := []interface{}{}
rawArray := []any{}
for _, v := range node.GetEnumerator() {
rawRes, err := e.ToRaw(CreateIntermediateResult(e.Context(), v))
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.
func (e *Evaluator) EvaluateRaw(expr string) (interface{}, error) {
func (e *Evaluator) EvaluateRaw(expr string) (any, error) {
root, err := exprparser.Parse(expr)
if err != nil {
return false, fmt.Errorf("parse error: %w", err)
@@ -97,16 +97,16 @@ func (e *Evaluator) EvaluateRaw(expr string) (interface{}, error) {
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) {
return nil
}
return a[i]
}
func (a FilteredArray) GetEnumerator() []interface{} {
func (a FilteredArray) GetEnumerator() []any {
return a
}
@@ -187,7 +187,7 @@ func (e *Evaluator) evalBinaryNodeLeft(node *exprparser.BinaryNode, left *Evalua
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) {
@@ -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 {
key, ok := right.Value().(string)
if !ok {
@@ -264,7 +264,7 @@ func processIndex(col interface{}, right *EvaluationResult) interface{} {
return nil
}
func processStar(subcol interface{}, ret FilteredArray) FilteredArray {
func processStar(subcol any, ret FilteredArray) FilteredArray {
if array, ok := subcol.(ReadOnlyArray[any]); ok {
ret = append(ret, array.GetEnumerator()...)
} else if obj, ok := subcol.(ReadOnlyObject[any]); ok {

View File

@@ -6,7 +6,7 @@ import (
// Test boolean and comparison operations using the evaluator.
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)
tests := []struct {
@@ -44,7 +44,7 @@ func TestEvaluator_Raw(t *testing.T) {
tests := []struct {
expr string
want interface{}
want any
}{
{"a.b['x']", nil},
{"(a.b).c['x']", nil},

View File

@@ -5,8 +5,8 @@ import (
"errors"
"strings"
"github.com/actions-oss/act-cli/internal/eval/functions"
exprparser "github.com/actions-oss/act-cli/internal/expr"
"gitea.com/gitea/act_runner/internal/eval/functions"
exprparser "gitea.com/gitea/act_runner/internal/expr"
)
type FromJSON struct {
@@ -113,7 +113,7 @@ func (Format) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResu
return nil, err
}
sargs := []interface{}{}
sargs := []any{}
for _, arg := range args[1:] {
el, err := eval.Evaluate(arg)
if err != nil {

View File

@@ -20,7 +20,7 @@ type Node interface {
type ValueNode struct {
Kind TokenKind
Value interface{}
Value any
}
// FunctionNode represents a function call with arguments.

View File

@@ -51,7 +51,7 @@ const (
type Token struct {
Kind TokenKind
Raw string
Value interface{}
Value any
Index int
}
@@ -256,7 +256,7 @@ func (l *Lexer) readNumber() *Token {
}
}
// Try to parse as float64
var val interface{} = raw
var val any = raw
if f, err := strconv.ParseFloat(raw, 64); err == nil {
val = f
}

View File

@@ -12,7 +12,7 @@ func TestLexerMultiple(t *testing.T) {
cases := []struct {
expr string
expected []TokenKind
values []interface{} // optional, nil if not checking values
values []any // optional, nil if not checking values
}{
{
expr: "github.event_name == 'push'",
@@ -67,12 +67,12 @@ func TestLexerMultiple(t *testing.T) {
{
expr: "true",
expected: []TokenKind{TokenKindBoolean},
values: []interface{}{true},
values: []any{true},
},
{
expr: "123",
expected: []TokenKind{TokenKindNumber},
values: []interface{}{123.0},
values: []any{123.0},
},
{
expr: "(a && b)",
@@ -85,7 +85,7 @@ func TestLexerMultiple(t *testing.T) {
{
expr: "'Hello i''s escaped'",
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)
}
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 {
assert.Equal(t, kind, tokens[i].Kind, "expr %s token %d", tc.expr, i)
}

View File

@@ -22,13 +22,13 @@ func TestLexer(t *testing.T) {
for i, tok := range tokens {
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) {
table := []struct {
in string
out interface{}
out any
}{
{"-Infinity", math.Inf(-1)},
{"Infinity", math.Inf(1)},

View File

@@ -2,7 +2,7 @@ package model
import (
"errors"
"fmt"
"maps"
"strings"
"gopkg.in/yaml.v3"
@@ -11,7 +11,7 @@ import (
// TraceWriter is an interface for logging trace information.
// Implementations can write to console, file, or any other sink.
type TraceWriter interface {
Info(format string, args ...interface{})
Info(format string, args ...any)
}
// StrategyResult holds the result of expanding a strategy.
@@ -46,14 +46,14 @@ func (strategyContext *strategyContext) handleInclude() error {
if len(strategyContext.include) > 0 {
for _, incNode := range strategyContext.include {
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)
for i := 0; i < len(incNode.Content); i += 2 {
keyNode := incNode.Content[i]
valNode := incNode.Content[i+1]
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
}
@@ -94,7 +94,7 @@ func (strategyContext *strategyContext) handleExclude() error {
for _, exNode := range strategyContext.exclude {
// exNode is expected to be a mapping node
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
exMap := make(map[string]yaml.Node)
@@ -102,7 +102,7 @@ func (strategyContext *strategyContext) handleExclude() error {
keyNode := exNode.Content[i]
valNode := exNode.Content[i+1]
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
}
@@ -158,9 +158,7 @@ func ExpandStrategy(strategy *Strategy, jobTraceWriter TraceWriter) (*StrategyRe
for _, row := range strategyContext.flatMatrix {
for _, val := range values {
newRow := make(map[string]yaml.Node)
for k, v := range row {
newRow[k] = v
}
maps.Copy(newRow, row)
newRow[key] = val
next = append(next, newRow)
}

View File

@@ -10,7 +10,7 @@ import (
type EmptyTraceWriter struct {
}
func (e *EmptyTraceWriter) Info(_ string, _ ...interface{}) {
func (e *EmptyTraceWriter) Info(_ string, _ ...any) {
}
func TestStrategy(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package model
import (
"strings"
v2 "github.com/actions-oss/act-cli/internal/eval/v2"
v2 "gitea.com/gitea/act_runner/internal/eval/v2"
"gopkg.in/yaml.v3"
)

View File

@@ -96,7 +96,7 @@ func (a *On) UnmarshalYAML(node *yaml.Node) error {
return nil
}
func (a *On) MarshalYAML() (interface{}, error) {
func (a *On) MarshalYAML() (any, error) {
return a.Data, nil
}

View File

@@ -4,9 +4,9 @@ import (
"context"
"testing"
v2 "github.com/actions-oss/act-cli/internal/eval/v2"
"github.com/actions-oss/act-cli/internal/templateeval"
"github.com/actions-oss/act-cli/pkg/schema"
v2 "gitea.com/gitea/act_runner/internal/eval/v2"
"gitea.com/gitea/act_runner/internal/templateeval"
"gitea.com/gitea/act_runner/pkg/schema"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
@@ -95,7 +95,7 @@ jobs:
var raw any
err = node.Content[0].Decode(&raw)
assert.NoError(t, err)
require.NoError(t, err)
ee.RestrictEval = true
ee.EvaluationContext.Variables = v2.CaseInsensitiveObject[any]{
@@ -136,6 +136,6 @@ jobs:
}
}
out, err := yaml.Marshal(&myw)
assert.NoError(t, err)
require.NoError(t, err)
assert.NotEmpty(t, out)
}

View File

@@ -6,8 +6,8 @@ package labels
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)
func TestParse(t *testing.T) {
@@ -57,7 +57,7 @@ func TestParse(t *testing.T) {
return
}
require.NoError(t, err)
assert.DeepEqual(t, got, tt.want)
assert.Equal(t, tt.want, got)
})
}
}

View File

@@ -5,9 +5,9 @@ import (
"fmt"
"regexp"
v2 "github.com/actions-oss/act-cli/internal/eval/v2"
exprparser "github.com/actions-oss/act-cli/internal/expr"
"github.com/actions-oss/act-cli/pkg/schema"
v2 "gitea.com/gitea/act_runner/internal/eval/v2"
exprparser "gitea.com/gitea/act_runner/internal/expr"
"gitea.com/gitea/act_runner/pkg/schema"
"gopkg.in/yaml.v3"
)

View File

@@ -4,8 +4,8 @@ import (
"context"
"testing"
v2 "github.com/actions-oss/act-cli/internal/eval/v2"
"github.com/actions-oss/act-cli/pkg/schema"
v2 "gitea.com/gitea/act_runner/internal/eval/v2"
"gitea.com/gitea/act_runner/pkg/schema"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)

View File

@@ -4,12 +4,13 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRewriteSubExpression_NoExpression(t *testing.T) {
in := "Hello world"
out, ok, err := rewriteSubExpression(in, false)
assert.NoError(t, err)
require.NoError(t, err)
if ok {
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) {
in := "Hello ${{ 'world' }}"
out, ok, err := rewriteSubExpression(in, false)
assert.NoError(t, err)
require.NoError(t, err)
if !ok {
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) {
in := "Hello ${{ 'world' }}, you are ${{ 'awesome' }}"
out, ok, err := rewriteSubExpression(in, false)
assert.NoError(t, err)
require.NoError(t, err)
if !ok {
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) {
in := "Hello ${{ 'world' }}"
out, ok, err := rewriteSubExpression(in, true)
assert.NoError(t, err)
require.NoError(t, err)
if !ok {
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) {
in := "Hello ${{ 'world' }}, you are ${{ 'awesome' }}"
out, ok, err := rewriteSubExpression(in, true)
assert.NoError(t, err)
require.NoError(t, err)
if !ok {
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) {
in := "Hello ${{ 'world' " // missing closing }}
_, _, err := rewriteSubExpression(in, false)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "unclosed expression")
}
func TestRewriteSubExpression_UnclosedString(t *testing.T) {
in := "Hello ${{ 'world }}, you are ${{ 'awesome' }}"
_, _, err := rewriteSubExpression(in, false)
assert.Error(t, err)
require.Error(t, err)
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
in := "Hello ${{ 'It''s a test' }}"
out, ok, err := rewriteSubExpression(in, false)
assert.NoError(t, err)
require.NoError(t, err)
assert.True(t, ok)
expected := "format('Hello {0}', 'It''s a test')"
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
in := "Hello ${{ 'world' }}"
out, ok, err := rewriteSubExpression(in, false)
assert.NoError(t, err)
require.NoError(t, err)
assert.True(t, ok)
expected := "format('Hello {0}', 'world')"
assert.Equal(t, expected, out)
@@ -108,7 +109,7 @@ func TestRewriteSubExpression_ExpressionNotAtEnd(t *testing.T) {
// Expression followed by additional text should still be valid
in := "Hello ${{ 'world' }}, how are you?"
out, ok, err := rewriteSubExpression(in, false)
assert.NoError(t, err)
require.NoError(t, err)
assert.True(t, ok)
expected := "format('Hello {0}, how are you?', 'world')"
assert.Equal(t, expected, out)

View File

@@ -20,7 +20,7 @@ import (
"github.com/timshannon/bolthold"
"go.etcd.io/bbolt"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
)
const (
@@ -75,7 +75,7 @@ func StartHandler(dir, outboundIP string, port uint16, logger logrus.FieldLogger
if outboundIP != "" {
h.outboundIP = outboundIP
} 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 {
h.outboundIP = ip.String()
}
@@ -144,7 +144,7 @@ func CreateHandler(dir, externalAddress string, logger logrus.FieldLogger) (*Han
if externalAddress != "" {
h.externalAddress = externalAddress
} 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 {
h.outboundIP = ip.String()
}
@@ -420,7 +420,7 @@ func findCache(db *bolthold.Store, keys []string, version string) (*Cache, error
}
return cache, nil
}
prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix))
prefixPattern := "^" + regexp.QuoteMeta(prefix)
re, err := regexp.Compile(prefixPattern)
if err != nil {
continue

View File

@@ -42,7 +42,7 @@ func TestHandler(t *testing.T) {
assert.Nil(t, handler.server)
assert.Nil(t, handler.listener)
_, 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) {
resp, err := http.Post(fmt.Sprintf("%s/clean", base), "", nil)
resp, err := http.Post(base+"/clean", "", nil)
require.NoError(t, err)
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) {
body := []byte(`invalid json`)
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)
assert.Equal(t, 400, resp.StatusCode)
})
@@ -90,7 +90,7 @@ func TestHandler(t *testing.T) {
Size: 100,
})
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)
assert.Equal(t, 200, resp.StatusCode)
@@ -104,7 +104,7 @@ func TestHandler(t *testing.T) {
Size: 100,
})
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)
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) {
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)
req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("Content-Range", "bytes 0-99/*")
@@ -151,7 +151,7 @@ func TestHandler(t *testing.T) {
Size: 100,
})
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)
assert.Equal(t, 200, resp.StatusCode)
@@ -202,7 +202,7 @@ func TestHandler(t *testing.T) {
Size: 100,
})
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)
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) {
{
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)
assert.Equal(t, 400, resp.StatusCode)
}
@@ -254,7 +254,7 @@ func TestHandler(t *testing.T) {
Size: 100,
})
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)
assert.Equal(t, 200, resp.StatusCode)
@@ -300,7 +300,7 @@ func TestHandler(t *testing.T) {
Size: 100,
})
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)
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) {
resp, err := http.Get(fmt.Sprintf("%s/artifacts/invalid_id", base))
resp, err := http.Get(base + "/artifacts/invalid_id")
require.NoError(t, err)
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)),
})
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)
assert.Equal(t, 200, resp.StatusCode)
@@ -687,7 +687,7 @@ func TestHandler_gcCache(t *testing.T) {
cache := &Cache{}
err = db.Get(v.Cache.ID, cache)
if v.Kept {
assert.NoError(t, err)
require.NoError(t, err)
} else {
assert.ErrorIs(t, err, bolthold.ErrNotFound)
}

View File

@@ -6,6 +6,7 @@ import (
"net/http"
"os"
"path/filepath"
"strconv"
)
type Storage struct {
@@ -103,11 +104,11 @@ func (s *Storage) Remove(id uint64) {
}
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 {
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 {

View File

@@ -126,22 +126,22 @@ func artifactNameToID(s string) int64 {
return int64(h.Sum32())
}
func (c ArtifactContext) Error(status int, _ ...interface{}) {
func (c ArtifactContext) Error(status int, _ ...any) {
c.Resp.WriteHeader(status)
}
func (c ArtifactContext) JSON(status int, _ ...interface{}) {
func (c ArtifactContext) JSON(status int, _ ...any) {
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)
if err != nil /* || task.Job.RunID != runID*/ {
log.Error("Error runID 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) {
@@ -210,7 +210,7 @@ func (r artifactV4Routes) buildSignature(endp, expires, artifactName string, tas
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")
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
}
@@ -271,14 +271,14 @@ func (r *artifactV4Routes) createArtifact(ctx *ArtifactContext) {
if ok := r.parseProtbufBody(ctx, &req); !ok {
return
}
_, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
if !ok {
return
}
artifactName := req.Name
safeRunPath := safeResolve(r.baseDir, fmt.Sprint(runID))
safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10))
safePath := safeResolve(safeRunPath, artifactName)
safePath = safeResolve(safePath, artifactName+".zip")
file, err := r.fs.OpenWritable(safePath)
@@ -305,7 +305,7 @@ func (r *artifactV4Routes) uploadArtifact(ctx *ArtifactContext) {
switch comp {
case "block", "appendBlock":
safeRunPath := safeResolve(r.baseDir, fmt.Sprint(task))
safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(task, 10))
safePath := safeResolve(safeRunPath, artifactName)
safePath = safeResolve(safePath, artifactName+".zip")
@@ -342,7 +342,7 @@ func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
if ok := r.parseProtbufBody(ctx, &req); !ok {
return
}
_, _, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
_, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
if !ok {
return
}
@@ -360,12 +360,12 @@ func (r *artifactV4Routes) listArtifacts(ctx *ArtifactContext) {
if ok := r.parseProtbufBody(ctx, &req); !ok {
return
}
_, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
if !ok {
return
}
safePath := safeResolve(r.baseDir, fmt.Sprint(runID))
safePath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10))
entries, err := fs.ReadDir(r.rfs, safePath)
if err != nil {
@@ -405,7 +405,7 @@ func (r *artifactV4Routes) getSignedArtifactURL(ctx *ArtifactContext) {
if ok := r.parseProtbufBody(ctx, &req); !ok {
return
}
_, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
if !ok {
return
}
@@ -424,7 +424,7 @@ func (r *artifactV4Routes) downloadArtifact(ctx *ArtifactContext) {
return
}
safeRunPath := safeResolve(r.baseDir, fmt.Sprint(task))
safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(task, 10))
safePath := safeResolve(safeRunPath, artifactName)
safePath = safeResolve(safePath, artifactName+".zip")
@@ -439,11 +439,11 @@ func (r *artifactV4Routes) deleteArtifact(ctx *ArtifactContext) {
if ok := r.parseProtbufBody(ctx, &req); !ok {
return
}
_, runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
runID, ok := validateRunIDV4(ctx, req.WorkflowRunBackendId)
if !ok {
return
}
safeRunPath := safeResolve(r.baseDir, fmt.Sprint(runID))
safeRunPath := safeResolve(r.baseDir, strconv.FormatInt(runID, 10))
safePath := safeResolve(safeRunPath, req.Name)
_ = os.RemoveAll(safePath)

View File

@@ -15,7 +15,7 @@ import (
"github.com/julienschmidt/httprouter"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
)
type FileContainerResourceURL struct {

View File

@@ -16,9 +16,10 @@ import (
"github.com/julienschmidt/httprouter"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/actions-oss/act-cli/pkg/model"
"github.com/actions-oss/act-cli/pkg/runner"
"gitea.com/gitea/act_runner/pkg/model"
"gitea.com/gitea/act_runner/pkg/runner"
)
type writableMapFile struct {
@@ -68,7 +69,7 @@ func TestNewArtifactUploadPrepare(t *testing.T) {
router := httprouter.New()
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()
router.ServeHTTP(rr, req)
@@ -94,7 +95,7 @@ func TestArtifactUploadBlob(t *testing.T) {
router := httprouter.New()
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()
router.ServeHTTP(rr, req)
@@ -121,7 +122,7 @@ func TestFinalizeArtifactUpload(t *testing.T) {
router := httprouter.New()
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()
router.ServeHTTP(rr, req)
@@ -151,7 +152,7 @@ func TestListArtifacts(t *testing.T) {
router := httprouter.New()
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()
router.ServeHTTP(rr, req)
@@ -183,7 +184,7 @@ func TestListArtifactContainer(t *testing.T) {
router := httprouter.New()
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()
router.ServeHTTP(rr, req)
@@ -198,7 +199,7 @@ func TestListArtifactContainer(t *testing.T) {
panic(err)
}
assert.Equal(1, len(response.Value))
assert.Len(response.Value, 1)
assert.Equal("some/file", response.Value[0].Path)
assert.Equal("file", response.Value[0].ItemType)
assert.Equal("http://localhost/artifact/1/some/file/.", response.Value[0].ContentLocation)
@@ -216,7 +217,7 @@ func TestDownloadArtifactFile(t *testing.T) {
router := httprouter.New()
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()
router.ServeHTTP(rr, req)
@@ -276,14 +277,14 @@ func TestArtifactFlow(t *testing.T) {
func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
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 {
panic(err)
}
workdir, err := filepath.Abs(tjfi.workdir)
assert.Nil(t, err, workdir)
require.NoError(t, err, workdir)
fullWorkflowPath := filepath.Join(workdir, tjfi.workflowPath)
runnerConfig := &runner.Config{
Workdir: workdir,
@@ -299,24 +300,24 @@ func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
}
runner, err := runner.New(runnerConfig)
assert.Nil(t, err, tjfi.workflowPath)
require.NoError(t, err, tjfi.workflowPath)
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, model.PlannerConfig{})
assert.Nil(t, err, fullWorkflowPath)
require.NoError(t, err, fullWorkflowPath)
plan, err := planner.PlanEvent(tjfi.eventName)
if err == nil {
err = runner.NewPlanExecutor(plan)(ctx)
if tjfi.errorMessage == "" {
assert.Nil(t, err, fullWorkflowPath)
require.NoError(t, err, fullWorkflowPath)
} else {
assert.Error(t, err, tjfi.errorMessage)
require.Error(t, err, tjfi.errorMessage)
}
} else {
assert.Nil(t, plan)
}
fmt.Println("::endgroup::")
t.Log("::endgroup::")
})
}
@@ -356,7 +357,7 @@ func TestDownloadArtifactFileUnsafePath(t *testing.T) {
router := httprouter.New()
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()
router.ServeHTTP(rr, req)
@@ -378,7 +379,7 @@ func TestArtifactUploadBlobUnsafePath(t *testing.T) {
router := httprouter.New()
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()
router.ServeHTTP(rr, req)

View File

@@ -5,6 +5,7 @@ package common
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"
@@ -78,7 +79,7 @@ func ParseAuthorizationToken(req *http.Request) (int64, error) {
parts := strings.SplitN(h, " ", 2)
if len(parts) != 2 {
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) {
@@ -93,7 +94,7 @@ func ParseAuthorizationToken(req *http.Request) (int64, error) {
c, ok := token.Claims.(*actionsClaims)
if !token.Valid || !ok {
return 0, fmt.Errorf("invalid token claim")
return 0, errors.New("invalid token claim")
}
return c.TaskID, nil

View File

@@ -10,18 +10,19 @@ import (
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCreateAuthorizationToken(t *testing.T) {
var taskID int64 = 23
token, err := CreateAuthorizationToken(taskID, 1, 2)
assert.Nil(t, err)
assert.NotEqual(t, "", token)
require.NoError(t, err)
assert.NotEmpty(t, token)
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
})
assert.Nil(t, err)
require.NoError(t, err)
scp, ok := claims["scp"]
assert.True(t, ok, "Has scp claim in jwt token")
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")
scopes := []actionsCacheScope{}
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")
}
func TestParseAuthorizationToken(t *testing.T) {
var taskID int64 = 23
token, err := CreateAuthorizationToken(taskID, 1, 2)
assert.Nil(t, err)
assert.NotEqual(t, "", token)
require.NoError(t, err)
assert.NotEmpty(t, token)
headers := http.Header{}
headers.Set("Authorization", "Bearer "+token)
rTaskID, err := ParseAuthorizationToken(&http.Request{
Header: headers,
})
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, taskID, rTaskID)
}
@@ -57,6 +58,6 @@ func TestParseAuthorizationTokenNoAuthHeader(t *testing.T) {
rTaskID, err := ParseAuthorizationToken(&http.Request{
Header: headers,
})
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, int64(0), rTaskID)
}

View File

@@ -1,9 +1,9 @@
package common
// 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)
lists := make([][]interface{}, 0)
lists := make([][]any, 0)
for k, v := range mapOfLists {
listNames = append(listNames, k)
lists = append(lists, v)
@@ -11,9 +11,9 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac
listCart := cartN(lists...)
rtn := make([]map[string]interface{}, 0)
rtn := make([]map[string]any, 0)
for _, list := range listCart {
vMap := make(map[string]interface{})
vMap := make(map[string]any)
for i, v := range list {
vMap[listNames[i]] = v
}
@@ -22,7 +22,7 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac
return rtn
}
func cartN(a ...[]interface{}) [][]interface{} {
func cartN(a ...[]any) [][]any {
c := 1
for _, a := range a {
c *= len(a)
@@ -30,8 +30,8 @@ func cartN(a ...[]interface{}) [][]interface{} {
if c == 0 || len(a) == 0 {
return nil
}
p := make([][]interface{}, c)
b := make([]interface{}, c*len(a))
p := make([][]any, c)
b := make([]any, c*len(a))
n := make([]int, len(a))
s := 0
for i := range p {

View File

@@ -8,7 +8,7 @@ import (
func TestCartesianProduct(t *testing.T) {
assert := assert.New(t)
input := map[string][]interface{}{
input := map[string][]any{
"foo": {1, 2, 3, 4},
"bar": {"a", "b", "c"},
"baz": {false, true},
@@ -25,15 +25,15 @@ func TestCartesianProduct(t *testing.T) {
assert.Contains(v, "baz")
}
input = map[string][]interface{}{
input = map[string][]any{
"foo": {1, 2, 3, 4},
"bar": {},
"baz": {false, true},
}
output = CartesianProduct(input)
assert.Len(output, 0)
assert.Empty(output)
input = map[string][]interface{}{}
input = map[string][]any{}
output = CartesianProduct(input)
assert.Len(output, 0)
assert.Empty(output)
}

View File

@@ -8,6 +8,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGracefulJobCancellationViaSigint(t *testing.T) {
@@ -18,8 +19,8 @@ func TestGracefulJobCancellationViaSigint(t *testing.T) {
assert.NotNil(t, channel)
cancelCtx := JobCancelContext(ctx)
assert.NotNil(t, cancelCtx)
assert.NoError(t, ctx.Err())
assert.NoError(t, cancelCtx.Err())
require.NoError(t, ctx.Err())
require.NoError(t, cancelCtx.Err())
channel <- os.Interrupt
select {
case <-time.After(1 * time.Second):
@@ -30,7 +31,7 @@ func TestGracefulJobCancellationViaSigint(t *testing.T) {
if assert.Error(t, cancelCtx.Err(), "context canceled") {
assert.Equal(t, context.Canceled, cancelCtx.Err())
}
assert.NoError(t, ctx.Err())
require.NoError(t, ctx.Err())
channel <- os.Interrupt
select {
case <-time.After(1 * time.Second):
@@ -50,8 +51,8 @@ func TestForceCancellationViaSigterm(t *testing.T) {
assert.NotNil(t, channel)
cancelCtx := JobCancelContext(ctx)
assert.NotNil(t, cancelCtx)
assert.NoError(t, ctx.Err())
assert.NoError(t, cancelCtx.Err())
require.NoError(t, ctx.Err())
require.NoError(t, cancelCtx.Err())
channel <- syscall.SIGTERM
select {
case <-time.After(1 * time.Second):
@@ -78,7 +79,7 @@ func TestCreateGracefulJobCancellationContext(t *testing.T) {
assert.NotNil(t, cancel)
cancelCtx := JobCancelContext(ctx)
assert.NotNil(t, cancelCtx)
assert.NoError(t, cancelCtx.Err())
require.NoError(t, cancelCtx.Err())
}
func TestCreateGracefulJobCancellationContextCancelFunc(t *testing.T) {
@@ -87,7 +88,7 @@ func TestCreateGracefulJobCancellationContextCancelFunc(t *testing.T) {
assert.NotNil(t, cancel)
cancelCtx := JobCancelContext(ctx)
assert.NotNil(t, cancelCtx)
assert.NoError(t, cancelCtx.Err())
require.NoError(t, cancelCtx.Err())
cancel()
if assert.Error(t, ctx.Err(), "context canceled") {
assert.Equal(t, context.Canceled, ctx.Err())

View File

@@ -125,11 +125,8 @@ func (p *Pen) DrawBoxes(labels ...string) *Drawing {
// Draw to writer
func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) {
padSize := (centerOnWidth - d.GetWidth()) / 2
if padSize < 0 {
padSize = 0
}
for _, l := range strings.Split(d.buf.String(), "\n") {
padSize := max((centerOnWidth-d.GetWidth())/2, 0)
for l := range strings.SplitSeq(d.buf.String(), "\n") {
if len(l) > 0 {
padding := strings.Repeat(" ", padSize)
fmt.Fprintf(writer, "%s%s\n", padding, l)

View File

@@ -19,7 +19,7 @@ func (w Warning) Error() string {
}
// Warningf create a warning
func Warningf(format string, args ...interface{}) Warning {
func Warningf(format string, args ...any) Warning {
w := Warning{
Message: fmt.Sprintf(format, args...),
}
@@ -33,7 +33,7 @@ type Executor func(ctx context.Context) error
type Conditional func(ctx context.Context) bool
// 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 {
logger := Logger(ctx)
logger.Infof(format, args...)
@@ -42,7 +42,7 @@ func NewInfoExecutor(format string, args ...interface{}) Executor {
}
// 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 {
logger := Logger(ctx)
logger.Debugf(format, args...)
@@ -110,14 +110,14 @@ func NewParallelExecutor(parallel int, executors ...Executor) Executor {
}(work, errs)
}
for i := 0; i < len(executors); i++ {
for i := range executors {
work <- executors[i]
}
close(work)
// Executor waits all executors to cleanup these resources.
var firstErr error
for i := 0; i < len(executors); i++ {
for range executors {
err := <-errs
if firstErr == nil {
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 exec(WithLogger(ctx, Logger(ctx).WithField(name, value)))
}

View File

@@ -2,11 +2,12 @@ package common
import (
"context"
"fmt"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewWorkflow(t *testing.T) {
@@ -16,11 +17,11 @@ func TestNewWorkflow(t *testing.T) {
// empty
emptyWorkflow := NewPipelineExecutor()
assert.Nil(emptyWorkflow(ctx))
require.NoError(t, emptyWorkflow(ctx))
// error case
errorWorkflow := NewErrorExecutor(fmt.Errorf("test error"))
assert.NotNil(errorWorkflow(ctx))
errorWorkflow := NewErrorExecutor(errors.New("test error"))
require.Error(t, errorWorkflow(ctx))
// multiple success case
runcount := 0
@@ -33,7 +34,7 @@ func TestNewWorkflow(t *testing.T) {
runcount++
return nil
})
assert.Nil(successWorkflow(ctx))
require.NoError(t, successWorkflow(ctx))
assert.Equal(2, runcount)
}
@@ -55,7 +56,7 @@ func TestNewConditionalExecutor(t *testing.T) {
return nil
})(ctx)
assert.Nil(err)
require.NoError(t, err)
assert.Equal(0, trueCount)
assert.Equal(1, falseCount)
@@ -69,7 +70,7 @@ func TestNewConditionalExecutor(t *testing.T) {
return nil
})(ctx)
assert.Nil(err)
require.NoError(t, err)
assert.Equal(1, trueCount)
assert.Equal(1, falseCount)
}
@@ -99,7 +100,7 @@ func TestNewParallelExecutor(t *testing.T) {
assert.Equal(3, count, "should run all 3 executors")
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
count = 0
@@ -110,7 +111,7 @@ func TestNewParallelExecutor(t *testing.T) {
assert.Equal(3, count, "should run all 3 executors")
assert.Equal(1, maxCount, "should run at most 1 executors in parallel")
assert.Nil(errSingle)
require.NoError(t, errSingle)
}
func TestNewParallelExecutorFailed(t *testing.T) {
@@ -122,7 +123,7 @@ func TestNewParallelExecutorFailed(t *testing.T) {
count := 0
errorWorkflow := NewPipelineExecutor(func(_ context.Context) error {
count++
return fmt.Errorf("fake error")
return errors.New("fake error")
})
err := NewParallelExecutor(1, errorWorkflow)(ctx)
assert.Equal(1, count)
@@ -135,7 +136,7 @@ func TestNewParallelExecutorCanceled(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
errExpected := fmt.Errorf("fake error")
errExpected := errors.New("fake error")
count := 0
successWorkflow := NewPipelineExecutor(func(_ context.Context) error {
@@ -148,5 +149,5 @@ func TestNewParallelExecutorCanceled(t *testing.T) {
})
err := NewParallelExecutor(3, errorWorkflow, successWorkflow, successWorkflow)(ctx)
assert.Equal(3, count)
assert.Error(errExpected, err)
assert.ErrorIs(errExpected, err)
}

View File

@@ -19,7 +19,7 @@ import (
"github.com/mattn/go-isatty"
log "github.com/sirupsen/logrus"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
)
var (
@@ -74,7 +74,7 @@ func FindGitRevision(ctx context.Context, file string) (shortSha string, sha str
}
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()
@@ -319,7 +319,7 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor {
cloneLock.Lock()
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)
if err != nil {
return err

View File

@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/assert"
"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) {
@@ -40,7 +40,7 @@ func TestFindGitSlug(t *testing.T) {
for _, tt := range slugTests {
provider, slug, err := findGitSlug(tt.url, "github.com")
assert.NoError(err)
require.NoError(t, err)
assert.Equal(tt.provider, provider)
assert.Equal(tt.slug, slug)
}
@@ -80,23 +80,23 @@ func TestFindGitRemoteURL(t *testing.T) {
basedir := testDir(t)
gitConfig()
err := gitCmd("init", basedir)
assert.NoError(err)
require.NoError(t, err)
err = cleanGitHooks(basedir)
assert.NoError(err)
require.NoError(t, err)
remoteURL := "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name"
err = gitCmd("-C", basedir, "remote", "add", "origin", remoteURL)
assert.NoError(err)
require.NoError(t, err)
u, err := findGitRemoteURL(context.Background(), basedir, "origin")
assert.NoError(err)
require.NoError(t, err)
assert.Equal(remoteURL, u)
remoteURL = "git@github.com/AwesomeOwner/MyAwesomeRepo.git"
err = gitCmd("-C", basedir, "remote", "add", "upstream", remoteURL)
assert.NoError(err)
require.NoError(t, err)
u, err = findGitRemoteURL(context.Background(), basedir, "upstream")
assert.NoError(err)
require.NoError(t, err)
assert.Equal(remoteURL, u)
}
@@ -213,10 +213,10 @@ func TestGitCloneExecutor(t *testing.T) {
err := clone(context.Background())
if tt.Err != nil {
assert.Error(t, err)
require.Error(t, err)
assert.Equal(t, tt.Err, err)
} else {
assert.Empty(t, err)
require.NoError(t, err)
}
})
}
@@ -258,7 +258,7 @@ func TestCloneIfRequired(t *testing.T) {
URL: "https://github.com/actions/checkout",
Dir: tempDir,
}, common.Logger(ctx))
assert.NoError(t, err)
require.NoError(t, err)
assert.NotNil(t, repo)
})

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestLineWriter(t *testing.T) {
@@ -18,7 +19,7 @@ func TestLineWriter(t *testing.T) {
assert := assert.New(t)
write := func(s string) {
n, err := lineWriter.Write([]byte(s))
assert.NoError(err)
require.NoError(t, err)
assert.Equal(len(s), n, s)
}

View File

@@ -5,7 +5,7 @@ import (
"io"
"os"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
"github.com/docker/go-connections/nat"
"golang.org/x/term"
)

View File

@@ -6,7 +6,7 @@ import (
"context"
"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/credentials"
"github.com/docker/docker/api/types/registry"

View File

@@ -15,7 +15,7 @@ import (
"github.com/moby/patternmatcher"
"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

View File

@@ -19,6 +19,7 @@ import (
"path/filepath"
"reflect"
"regexp"
"slices"
"strconv"
"strings"
"time"
@@ -559,7 +560,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
return nil, errors.Errorf("--health-retries cannot be negative")
}
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{
@@ -836,7 +837,7 @@ func convertToStandardNotation(ports []string) ([]string, error) {
for _, publish := range ports {
if strings.Contains(publish, "=") {
params := map[string]string{"protocol": "tcp"}
for _, param := range strings.Split(publish, ",") {
for param := range strings.SplitSeq(publish, ",") {
opt := strings.Split(param, "=")
if len(opt) < 2 {
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.
func validateAttach(val string) (string, error) {
s := strings.ToLower(val)
for _, str := range []string{"stdin", "stdout", "stderr"} {
if s == str {
return s, nil
}
if slices.Contains([]string{"stdin", "stdout", "stderr"}, s) {
return s, nil
}
return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR")
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/skip"
@@ -185,7 +186,7 @@ func TestParseRunWithInvalidArgs(t *testing.T) {
flags, _ := setupRunFlags()
for _, tc := range tests {
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)
}
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
}
@@ -339,7 +340,7 @@ func TestParseHostname(t *testing.T) {
hostnameWithDomain := "--hostname=hostname.domainname"
hostnameWithDomainTld := "--hostname=hostname.domainname.tld"
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)
}
}
@@ -606,7 +607,7 @@ func TestParseNetworkConfig(t *testing.T) {
_, hConfig, nwConfig, err := parseRun(tc.flags)
if tc.expectedErr != "" {
assert.Error(t, err, tc.expectedErr)
require.Error(t, err, tc.expectedErr)
return
}
@@ -677,7 +678,7 @@ func TestParseRestartPolicy(t *testing.T) {
},
}
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)
}
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/docker/docker/client"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func init() {
@@ -26,17 +27,17 @@ func TestImageExistsLocally(t *testing.T) {
// Test if image exists with specific tag
invalidImageTag, err := ImageExistsLocally(ctx, "library/alpine:this-random-tag-will-never-exist", "linux/amd64")
assert.Nil(t, err)
assert.Equal(t, false, invalidImageTag)
require.NoError(t, err)
assert.False(t, invalidImageTag)
// Test if image exists with specific architecture (image platform)
invalidImagePlatform, err := ImageExistsLocally(ctx, "alpine:latest", "windows/amd64")
assert.Nil(t, err)
assert.Equal(t, false, invalidImagePlatform)
require.NoError(t, err)
assert.False(t, invalidImagePlatform)
// pull an image
cli, err := client.NewClientWithOpts(client.FromEnv)
assert.Nil(t, err)
require.NoError(t, err)
cli.NegotiateAPIVersion(context.Background())
// 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{
Platform: "linux/amd64",
})
assert.Nil(t, err)
require.NoError(t, err)
defer readerDefault.Close()
_, err = io.ReadAll(readerDefault)
assert.Nil(t, err)
require.NoError(t, err)
imageDefaultArchExists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/amd64")
assert.Nil(t, err)
assert.Equal(t, true, imageDefaultArchExists)
require.NoError(t, err)
assert.True(t, imageDefaultArchExists)
}
func TestImageExistsLocallyQemu(t *testing.T) {
@@ -66,19 +67,19 @@ func TestImageExistsLocallyQemu(t *testing.T) {
// pull an image
cli, err := client.NewClientWithOpts(client.FromEnv)
assert.Nil(t, err)
require.NoError(t, err)
cli.NegotiateAPIVersion(context.Background())
// Validate if another architecture platform can be pulled
readerArm64, err := cli.ImagePull(ctx, "node:16-buster-slim", image.PullOptions{
Platform: "linux/arm64",
})
assert.Nil(t, err)
require.NoError(t, err)
defer readerArm64.Close()
_, err = io.ReadAll(readerArm64)
assert.Nil(t, err)
require.NoError(t, err)
imageArm64Exists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/arm64")
assert.Nil(t, err)
assert.Equal(t, true, imageArm64Exists)
require.NoError(t, err)
assert.True(t, imageArm64Exists)
}

View File

@@ -74,7 +74,7 @@ func logDockerResponse(logger logrus.FieldLogger, dockerResponse io.ReadCloser,
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 {
logger.Errorf(format, args...)
} else {

View File

@@ -5,7 +5,7 @@ package container
import (
"context"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
"github.com/docker/docker/api/types/network"
)

View File

@@ -13,7 +13,7 @@ import (
"github.com/docker/docker/api/types/image"
"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

View File

@@ -8,6 +8,7 @@ import (
log "github.com/sirupsen/logrus"
assert "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func init() {
@@ -40,15 +41,15 @@ func TestGetImagePullOptions(t *testing.T) {
config.SetDir("/non-existent/docker")
options, err := getImagePullOptions(ctx, NewDockerPullExecutorInput{})
assert.Nil(t, err, "Failed to create ImagePullOptions")
assert.Equal(t, "", options.RegistryAuth, "RegistryAuth should be empty if no username or password is set")
require.NoError(t, err, "Failed to create ImagePullOptions")
assert.Empty(t, options.RegistryAuth, "RegistryAuth should be empty if no username or password is set")
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
Image: "",
Username: "username",
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")
config.SetDir("testdata/docker-pull-options")
@@ -56,6 +57,6 @@ func TestGetImagePullOptions(t *testing.T) {
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
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")
}

View File

@@ -35,8 +35,8 @@ import (
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/pflag"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/filecollector"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/filecollector"
)
// 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) {
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)
return a, err

View File

@@ -4,7 +4,7 @@ import (
"bufio"
"bytes"
"context"
"fmt"
"errors"
"io"
"net"
"strings"
@@ -16,12 +16,13 @@ import (
"github.com/docker/docker/client"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
func TestDocker(t *testing.T) {
ctx := context.Background()
client, err := GetDockerClient(ctx)
assert.NoError(t, err)
require.NoError(t, err)
defer client.Close()
dockerBuild := NewDockerBuildExecutor(NewDockerBuildExecutorInput{
@@ -30,7 +31,7 @@ func TestDocker(t *testing.T) {
})
err = dockerBuild(ctx)
assert.NoError(t, err)
require.NoError(t, err)
cr := &containerReference{
cli: client,
@@ -47,7 +48,7 @@ func TestDocker(t *testing.T) {
envExecutor := cr.extractFromImageEnv(&env)
err = envExecutor(ctx)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, map[string]string{
"PATH": "/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:/this/path/does/not/exists/anywhere:/this/either",
"RANDOM_VAR": "WITH_VALUE",
@@ -153,7 +154,7 @@ func TestDockerExecAbort(t *testing.T) {
cancel()
err := <-channel
assert.ErrorIs(t, err, context.Canceled)
require.ErrorIs(t, err, context.Canceled)
conn.AssertExpectations(t)
client.AssertExpectations(t)
@@ -183,7 +184,7 @@ func TestDockerExecFailure(t *testing.T) {
}
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)
client.AssertExpectations(t)
@@ -216,7 +217,7 @@ func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) {
conn := &mockConn{}
merr := fmt.Errorf("failure")
merr := errors.New("failure")
client := &mockDockerClient{}
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{})
assert.ErrorIs(t, err, merr)
require.ErrorIs(t, err, merr)
conn.AssertExpectations(t)
client.AssertExpectations(t)
@@ -241,7 +242,7 @@ func TestDockerCopyTarStreamErrorInMkdir(t *testing.T) {
conn := &mockConn{}
merr := fmt.Errorf("failure")
merr := errors.New("failure")
client := &mockDockerClient{}
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{})
assert.ErrorIs(t, err, merr)
require.ErrorIs(t, err, merr)
conn.AssertExpectations(t)
client.AssertExpectations(t)

View File

@@ -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
// is not found in the `daemonPath`, the function returns false.
func isDockerHostURI(daemonPath string) bool {
if protoIndex := strings.Index(daemonPath, "://"); protoIndex != -1 {
scheme := daemonPath[:protoIndex]
if before, _, ok := strings.Cut(daemonPath, "://"); ok {
scheme := before
if strings.IndexFunc(scheme, func(r rune) bool {
return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z')
}) == -1 {

View File

@@ -6,6 +6,7 @@ import (
log "github.com/sirupsen/logrus"
assert "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func init() {
@@ -19,26 +20,26 @@ func TestGetSocketAndHostWithSocket(t *testing.T) {
CommonSocketLocations = originalCommonSocketLocations
dockerHost := "unix:///my/docker/host.sock"
socketURI := "/path/to/my.socket"
os.Setenv("DOCKER_HOST", dockerHost)
t.Setenv("DOCKER_HOST", dockerHost)
// Act
ret, err := GetSocketAndHost(socketURI)
// Assert
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, SocketAndHost{socketURI, dockerHost}, ret)
}
func TestGetSocketAndHostNoSocket(t *testing.T) {
// Arrange
dockerHost := "unix:///my/docker/host.sock"
os.Setenv("DOCKER_HOST", dockerHost)
t.Setenv("DOCKER_HOST", dockerHost)
// Act
ret, err := GetSocketAndHost("")
// Assert
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, SocketAndHost{dockerHost, dockerHost}, ret)
}
@@ -53,8 +54,8 @@ func TestGetSocketAndHostOnlySocket(t *testing.T) {
ret, err := GetSocketAndHost(socketURI)
// Assert
assert.NoError(t, err, "Expected no error from GetSocketAndHost")
assert.Equal(t, true, defaultSocketFound, "Expected to find default socket")
require.NoError(t, err, "Expected no error from GetSocketAndHost")
assert.True(t, defaultSocketFound, "Expected to find default socket")
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")
}
@@ -63,13 +64,13 @@ func TestGetSocketAndHostDontMount(t *testing.T) {
// Arrange
CommonSocketLocations = originalCommonSocketLocations
dockerHost := "unix:///my/docker/host.sock"
os.Setenv("DOCKER_HOST", dockerHost)
t.Setenv("DOCKER_HOST", dockerHost)
// Act
ret, err := GetSocketAndHost("-")
// Assert
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, SocketAndHost{"-", dockerHost}, ret)
}
@@ -83,8 +84,8 @@ func TestGetSocketAndHostNoHostNoSocket(t *testing.T) {
ret, err := GetSocketAndHost("")
// Assert
assert.Equal(t, true, found, "Expected a default socket to be found")
assert.Nil(t, err, "Expected no error from GetSocketAndHost")
assert.True(t, found, "Expected a default socket to be found")
require.NoError(t, err, "Expected no error from GetSocketAndHost")
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
func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
// Arrange
mySocketFile, tmpErr := os.CreateTemp("", "act-*.sock")
mySocketFile, tmpErr := os.CreateTemp(t.TempDir(), "act-*.sock")
mySocket := mySocketFile.Name()
unixSocket := "unix://" + mySocket
defer os.RemoveAll(mySocket)
assert.NoError(t, tmpErr)
require.NoError(t, tmpErr)
os.Unsetenv("DOCKER_HOST")
CommonSocketLocations = []string{mySocket}
@@ -108,8 +109,8 @@ func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
// Assert
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.Nil(t, err, "Expected no error from GetSocketAndHost")
assert.True(t, found, "Expected default socket to be found")
require.NoError(t, err, "Expected no error from GetSocketAndHost")
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)
// Assert
assert.Equal(t, false, found, "Expected no default socket to be found")
assert.Equal(t, "", defaultSocket, "Expected no default socket to be found")
assert.False(t, found, "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.Error(t, err, "Expected an error in invalid state")
require.Error(t, err, "Expected an error in invalid state")
}
func TestGetSocketAndHostOnlySocketValidButUnusualLocation(t *testing.T) {
@@ -142,9 +143,9 @@ func TestGetSocketAndHostOnlySocketValidButUnusualLocation(t *testing.T) {
// Assert
// Default socket locations
assert.Equal(t, "", defaultSocket, "Expect default socket location to be empty")
assert.Equal(t, false, found, "Expected no default socket to be found")
assert.Empty(t, defaultSocket, "Expect default socket location to be empty")
assert.False(t, found, "Expected no default socket to be found")
// 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")
}

View File

@@ -6,8 +6,8 @@ import (
"context"
"runtime"
"gitea.com/gitea/act_runner/pkg/common"
"github.com/docker/docker/api/types/system"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/pkg/errors"
)

View File

@@ -5,7 +5,7 @@ package container
import (
"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/volume"
)

View File

@@ -9,7 +9,7 @@ type ExecutionsEnvironment interface {
GetPathVariableName() string
DefaultPathVariable() 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
IsEnvironmentCaseInsensitive() bool
}

View File

@@ -20,9 +20,9 @@ import (
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
"golang.org/x/term"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/filecollector"
"github.com/actions-oss/act-cli/pkg/lookpath"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/filecollector"
"gitea.com/gitea/act_runner/pkg/lookpath"
)
type HostEnvironment struct {
@@ -83,7 +83,7 @@ func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, ta
continue
}
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 {
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) {
f, err := lookpath.LookPath2(cmd, &localEnv{env: env})
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 {
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 {
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")
}
}
@@ -451,8 +451,8 @@ func goOsToActionOs(os string) string {
return os
}
func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]interface{} {
return map[string]interface{}{
func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]any {
return map[string]any{
"os": goOsToActionOs(runtime.GOOS),
"arch": goArchToActionArch(runtime.GOARCH),
"temp": e.TmpDir,

View File

@@ -10,6 +10,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Type assert HostEnvironment implements ExecutionsEnvironment
@@ -17,7 +18,7 @@ var _ ExecutionsEnvironment = &HostEnvironment{}
func TestCopyDir(t *testing.T) {
dir, err := os.MkdirTemp("", "test-host-env-*")
assert.NoError(t, err)
require.NoError(t, err)
defer os.RemoveAll(dir)
ctx := context.Background()
e := &HostEnvironment{
@@ -33,12 +34,11 @@ func TestCopyDir(t *testing.T) {
_ = os.MkdirAll(e.ToolCache, 0700)
_ = os.MkdirAll(e.ActPath, 0700)
err = e.CopyDir(e.Workdir, e.Path, true)(ctx)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestGetContainerArchive(t *testing.T) {
dir, err := os.MkdirTemp("", "test-host-env-*")
assert.NoError(t, err)
dir := t.TempDir()
defer os.RemoveAll(dir)
ctx := context.Background()
e := &HostEnvironment{
@@ -54,17 +54,17 @@ func TestGetContainerArchive(t *testing.T) {
_ = os.MkdirAll(e.ToolCache, 0700)
_ = os.MkdirAll(e.ActPath, 0700)
expectedContent := []byte("sdde/7sh")
err = os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0600)
assert.NoError(t, err)
err := os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0600)
require.NoError(t, err)
archive, err := e.GetContainerArchive(ctx, e.Path)
assert.NoError(t, err)
require.NoError(t, err)
defer archive.Close()
reader := tar.NewReader(archive)
h, err := reader.Next()
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, "action.yml", h.Name)
content, err := io.ReadAll(reader)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, expectedContent, content)
_, err = reader.Next()
assert.ErrorIs(t, err, io.EOF)

View File

@@ -63,8 +63,8 @@ func (*LinuxContainerEnvironmentExtensions) JoinPathVariable(paths ...string) st
return strings.Join(paths, ":")
}
func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]interface{} {
return map[string]interface{}{
func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]any {
return map[string]any{
"os": "Linux",
"arch": RunnerArch(ctx),
"temp": "/tmp",

View File

@@ -31,22 +31,17 @@ func TestContainerPath(t *testing.T) {
for _, v := range []containerPathJob{
{"/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/c/windows/to/unix", "windows\\to\\unix", fmt.Sprintf("%s\\", rootDrive)},
{fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", fmt.Sprintf("%s\\", rootDrive)},
{"/mnt/c/windows/to/unix", "windows\\to\\unix", rootDrive + "\\"},
{fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", rootDrive + "\\"},
} {
if v.workDir != "" {
if err := os.Chdir(v.workDir); err != nil {
log.Error(err)
t.Fail()
}
t.Chdir(v.workDir)
}
assert.Equal(t, v.destinationPath, linuxcontainerext.ToContainerPath(v.sourcePath))
}
if err := os.Chdir(cwd); err != nil {
log.Error(err)
}
t.Chdir(cwd)
} else {
cwd, err := os.Getwd()
if err != nil {

View File

@@ -8,7 +8,7 @@ import (
"io"
"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 {

View File

@@ -1,6 +1,6 @@
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 {
needs := job.Needs()
@@ -13,11 +13,11 @@ func (impl *interperterImpl) getNeedsTransitive(job *model.Job) []string {
return needs
}
func (impl *interperterImpl) always() (interface{}, error) {
func (impl *interperterImpl) always() (any, error) {
return true, nil
}
func (impl *interperterImpl) jobSuccess() (interface{}, error) {
func (impl *interperterImpl) jobSuccess() (any, error) {
jobs := impl.config.Run.Workflow.Jobs
jobNeeds := impl.getNeedsTransitive(impl.config.Run.Job())
@@ -30,11 +30,11 @@ func (impl *interperterImpl) jobSuccess() (interface{}, error) {
return true, nil
}
func (impl *interperterImpl) stepSuccess() (interface{}, error) {
func (impl *interperterImpl) stepSuccess() (any, error) {
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
jobNeeds := impl.getNeedsTransitive(impl.config.Run.Job())
@@ -47,10 +47,10 @@ func (impl *interperterImpl) jobFailure() (interface{}, error) {
return false, nil
}
func (impl *interperterImpl) stepFailure() (interface{}, error) {
func (impl *interperterImpl) stepFailure() (any, error) {
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
}

View File

@@ -7,9 +7,9 @@ import (
"reflect"
"strings"
eval "github.com/actions-oss/act-cli/internal/eval/v2"
exprparser "github.com/actions-oss/act-cli/internal/expr"
"github.com/actions-oss/act-cli/pkg/model"
eval "gitea.com/gitea/act_runner/internal/eval/v2"
exprparser "gitea.com/gitea/act_runner/internal/expr"
"gitea.com/gitea/act_runner/pkg/model"
)
type EvaluationEnvironment struct {
@@ -18,16 +18,16 @@ type EvaluationEnvironment struct {
Job *model.JobContext
Jobs *map[string]*model.WorkflowCallResult
Steps map[string]*model.StepResult
Runner map[string]interface{}
Runner map[string]any
Secrets map[string]string
Vars map[string]string
Strategy map[string]interface{}
Matrix map[string]interface{}
Strategy map[string]any
Matrix map[string]any
Needs map[string]Needs
Inputs map[string]interface{}
HashFiles func([]reflect.Value) (interface{}, error)
Inputs map[string]any
HashFiles func([]reflect.Value) (any, error)
EnvCS bool
CtxData map[string]interface{}
CtxData map[string]any
}
type CaseSensitiveDict map[string]string
@@ -69,7 +69,7 @@ func (dsc DefaultStatusCheck) String() string {
}
type Interpreter interface {
Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (interface{}, error)
Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (any, error)
}
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
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) {
@@ -170,7 +170,7 @@ func (e externalFunc) Evaluate(ev *eval.Evaluator, args []exprparser.Node) (*eva
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.TrimSuffix(input, "}}")
if defaultStatusCheck != DefaultStatusCheckNone && input == "" {
@@ -226,10 +226,10 @@ func (impl *interperterImpl) GetFunctions() eval.CaseInsensitiveObject[eval.Func
if impl.env.HashFiles != nil {
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()
}}
functions["success"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) {
functions["success"] = &externalFunc{func(_ []reflect.Value) (any, error) {
if impl.config.Context == "job" {
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)
}}
functions["failure"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) {
functions["failure"] = &externalFunc{func(_ []reflect.Value) (any, error) {
if impl.config.Context == "job" {
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)
}}
functions["cancelled"] = &externalFunc{func(_ []reflect.Value) (interface{}, error) {
functions["cancelled"] = &externalFunc{func(_ []reflect.Value) (any, error) {
return impl.cancelled()
}}
return functions
@@ -287,7 +287,7 @@ func (impl *interperterImpl) GetVariables() eval.ReadOnlyObject[any] {
res := eval.CreateIntermediateResult(eval.NewEvaluationContext(), rawOtherCtx)
if rOtherCd, ok := res.TryGetCollectionInterface(); 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 {
// skip empty values, because github.workspace was set by Gitea Actions to an empty string
if mk, _ := otherCd.GetKv(k); v != "" && v != nil {
@@ -304,7 +304,7 @@ func (impl *interperterImpl) GetVariables() eval.ReadOnlyObject[any] {
return vars
}
func IsTruthy(input interface{}) bool {
func IsTruthy(input any) bool {
value := reflect.ValueOf(input)
switch value.Kind() {
case reflect.Bool:

View File

@@ -4,14 +4,15 @@ import (
"math"
"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/require"
)
func TestLiterals(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"true", true, "true"},
@@ -30,7 +31,7 @@ func TestLiterals(t *testing.T) {
for _, tt := range table {
t.Run(tt.name, func(t *testing.T) {
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, tt.expected, output)
})
@@ -40,7 +41,7 @@ func TestLiterals(t *testing.T) {
func TestOperators(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
error string
}{
@@ -69,7 +70,7 @@ func TestOperators(t *testing.T) {
{`true && false`, false, "and", ""},
{`true || false`, true, "or", ""},
{`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.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", ""},
@@ -81,15 +82,15 @@ func TestOperators(t *testing.T) {
env := &EvaluationEnvironment{
Github: &model.GithubContext{
Action: "push",
Event: map[string]interface{}{
"commits": []interface{}{
map[string]interface{}{
"author": map[string]interface{}{
Event: map[string]any{
"commits": []any{
map[string]any{
"author": map[string]any{
"username": "someone",
},
},
map[string]interface{}{
"author": map[string]interface{}{
map[string]any{
"author": map[string]any{
"username": "someone-else",
},
},
@@ -102,10 +103,10 @@ func TestOperators(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
if tt.error != "" {
assert.NotNil(t, err)
require.Error(t, err)
assert.Equal(t, tt.error, err.Error())
} else {
assert.Nil(t, err)
require.NoError(t, err)
}
assert.Equal(t, tt.expected, output)
@@ -116,7 +117,7 @@ func TestOperators(t *testing.T) {
func TestOperatorsCompare(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"!null", true, "not-null"},
@@ -154,7 +155,7 @@ func TestOperatorsCompare(t *testing.T) {
for _, tt := range table {
t.Run(tt.name, func(t *testing.T) {
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, tt.expected, output)
})
@@ -164,7 +165,7 @@ func TestOperatorsCompare(t *testing.T) {
func TestOperatorsBooleanEvaluation(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
// true &&
@@ -517,7 +518,7 @@ func TestOperatorsBooleanEvaluation(t *testing.T) {
for _, tt := range table {
t.Run(tt.name, func(t *testing.T) {
output, err := NewInterpeter(env, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
assert.Nil(t, err)
require.NoError(t, err)
// Normalize int => float64
if i, ok := tt.expected.(int); ok {
@@ -536,15 +537,15 @@ func TestOperatorsBooleanEvaluation(t *testing.T) {
func TestContexts(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
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", 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]interface{}{"github": map[string]interface{}{"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.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]any{"github": map[string]any{"ref": "refs/heads/test-data"}}},
{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: "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"},
@@ -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, 'failure')", expected: false, name: "needs-wildcard-context-contains-failure"},
{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]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]any{"vars": map[string]any{"my_var": "refs/heads/test-data"}}},
}
env := EvaluationEnvironment{
@@ -606,7 +607,7 @@ func TestContexts(t *testing.T) {
Conclusion: model.StepStatusSkipped,
},
},
Runner: map[string]interface{}{
Runner: map[string]any{
"os": "Linux",
"temp": "/tmp",
"tool_cache": "/opt/hostedtoolcache",
@@ -617,10 +618,10 @@ func TestContexts(t *testing.T) {
Vars: map[string]string{
"name": "value",
},
Strategy: map[string]interface{}{
Strategy: map[string]any{
"fail-fast": true,
},
Matrix: map[string]interface{}{
Matrix: map[string]any{
"os": "Linux",
},
Needs: map[string]Needs{
@@ -637,7 +638,7 @@ func TestContexts(t *testing.T) {
Result: "success",
},
},
Inputs: map[string]interface{}{
Inputs: map[string]any{
"name": "value",
},
}
@@ -648,7 +649,7 @@ func TestContexts(t *testing.T) {
tenv.EnvCS = tt.caseSensitiveEnv
tenv.CtxData = tt.ctxdata
output, err := NewInterpeter(&tenv, Config{}).Evaluate(tt.input, DefaultStatusCheckNone)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, tt.expected, output)
})

View File

@@ -3,6 +3,7 @@ package filecollector
import (
"archive/tar"
"context"
"errors"
"fmt"
"io"
"io/fs"
@@ -134,7 +135,7 @@ func (fc *FileCollector) CollectFiles(ctx context.Context, submodulePath []strin
if ctx != nil {
select {
case <-ctx.Done():
return fmt.Errorf("copy cancelled")
return errors.New("copy cancelled")
default:
}
}

View File

@@ -16,6 +16,7 @@ import (
"github.com/go-git/go-git/v5/plumbing/format/index"
"github.com/go-git/go-git/v5/storage/filesystem"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type memoryFs struct {
@@ -27,7 +28,7 @@ func (mfs *memoryFs) walk(root string, fn filepath.WalkFunc) error {
if err != nil {
return err
}
for i := 0; i < len(dir); i++ {
for i := range dir {
filename := filepath.Join(root, dir[i].Name())
err = fn(filename, dir[i], nil)
if dir[i].IsDir() {
@@ -105,12 +106,12 @@ func TestIgnoredTrackedfile(t *testing.T) {
},
}
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()
_, _ = tmpTar.Seek(0, io.SeekStart)
tr := tar.NewReader(tmpTar)
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)
_, err = tr.Next()
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)
// This file shouldn't be in the tar
f, err := worktree.Create(".env")
assert.NoError(t, err)
require.NoError(t, err)
_, err = f.Write([]byte("test=val1\n"))
assert.NoError(t, err)
require.NoError(t, err)
f.Close()
err = worktree.Symlink(".env", "test.env")
assert.NoError(t, err)
require.NoError(t, err)
w, err := repo.Worktree()
assert.NoError(t, err)
require.NoError(t, err)
// .gitignore is in the tar after adding it to the index
_, err = w.Add(".env")
assert.NoError(t, err)
require.NoError(t, err)
_, err = w.Add("test.env")
assert.NoError(t, err)
require.NoError(t, err)
tmpTar, _ := fs.Create("temp.tar")
tw := tar.NewWriter(tmpTar)
@@ -154,7 +155,7 @@ func TestSymlinks(t *testing.T) {
},
}
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()
_, _ = tmpTar.Seek(0, io.SeekStart)
tr := tar.NewReader(tmpTar)

View File

@@ -5,14 +5,14 @@ import (
"io"
"strings"
"github.com/actions-oss/act-cli/pkg/schema"
"gitea.com/gitea/act_runner/pkg/schema"
"gopkg.in/yaml.v3"
)
// ActionRunsUsing is the type of runner for the action
type ActionRunsUsing string
func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(interface{}) error) error {
func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(any) error) error {
var using string
if err := unmarshal(&using); err != nil {
return err

View File

@@ -3,7 +3,7 @@ package model
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)
@@ -17,9 +17,9 @@ test:
*node.Content[0].Content[1].Content[1] = yaml.Node{
Kind: yaml.AliasNode,
}
assert.NoError(t, err)
require.NoError(t, err)
err = resolveAliases(&node)
assert.Error(t, err)
require.Error(t, err)
}
func TestVerifyNoRecursion(t *testing.T) {
@@ -99,15 +99,15 @@ c: *a
var node yaml.Node
err := yaml.Unmarshal([]byte(tt.yaml), &node)
if tt.yamlErr {
assert.Error(t, err)
require.Error(t, err)
return
}
assert.NoError(t, err)
require.NoError(t, err)
err = resolveAliases(&node)
if tt.anchorErr {
assert.Error(t, err)
require.Error(t, err)
} else {
assert.NoError(t, err)
require.NoError(t, err)
}
})
}

View File

@@ -5,44 +5,44 @@ import (
"fmt"
"strings"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/common/git"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/common/git"
)
type GithubContext struct {
Event map[string]interface{} `json:"event"`
EventPath string `json:"event_path"`
Workflow string `json:"workflow"`
RunAttempt string `json:"run_attempt"`
RunID string `json:"run_id"`
RunNumber string `json:"run_number"`
Actor string `json:"actor"`
Repository string `json:"repository"`
EventName string `json:"event_name"`
Sha string `json:"sha"`
Ref string `json:"ref"`
RefName string `json:"ref_name"`
RefType string `json:"ref_type"`
HeadRef string `json:"head_ref"`
BaseRef string `json:"base_ref"`
Token string `json:"token"`
Workspace string `json:"workspace"`
Action string `json:"action"`
ActionPath string `json:"action_path"`
ActionRef string `json:"action_ref"`
ActionRepository string `json:"action_repository"`
Job string `json:"job"`
JobName string `json:"job_name"`
RepositoryOwner string `json:"repository_owner"`
RetentionDays string `json:"retention_days"`
RunnerPerflog string `json:"runner_perflog"`
RunnerTrackingID string `json:"runner_tracking_id"`
ServerURL string `json:"server_url"`
APIURL string `json:"api_url"`
GraphQLURL string `json:"graphql_url"`
Event map[string]any `json:"event"`
EventPath string `json:"event_path"`
Workflow string `json:"workflow"`
RunAttempt string `json:"run_attempt"`
RunID string `json:"run_id"`
RunNumber string `json:"run_number"`
Actor string `json:"actor"`
Repository string `json:"repository"`
EventName string `json:"event_name"`
Sha string `json:"sha"`
Ref string `json:"ref"`
RefName string `json:"ref_name"`
RefType string `json:"ref_type"`
HeadRef string `json:"head_ref"`
BaseRef string `json:"base_ref"`
Token string `json:"token"`
Workspace string `json:"workspace"`
Action string `json:"action"`
ActionPath string `json:"action_path"`
ActionRef string `json:"action_ref"`
ActionRepository string `json:"action_repository"`
Job string `json:"job"`
JobName string `json:"job_name"`
RepositoryOwner string `json:"repository_owner"`
RetentionDays string `json:"retention_days"`
RunnerPerflog string `json:"runner_perflog"`
RunnerTrackingID string `json:"runner_tracking_id"`
ServerURL string `json:"server_url"`
APIURL string `json:"api_url"`
GraphQLURL string `json:"graphql_url"`
}
func asString(v interface{}) string {
func asString(v any) string {
if v == nil {
return ""
} else if s, ok := v.(string); ok {
@@ -51,7 +51,7 @@ func asString(v interface{}) string {
return ""
}
func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) {
func nestedMapLookup(m map[string]any, ks ...string) (rval any) {
var ok bool
if len(ks) == 0 { // degenerate input
@@ -61,20 +61,20 @@ func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{})
return nil
} else if len(ks) == 1 { // we've reached the final key
return rval
} else if m, ok = rval.(map[string]interface{}); !ok {
} else if m, ok = rval.(map[string]any); !ok {
return nil
}
// 1+ more keys
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"]
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 {
common.Logger(ctx).Warnf("unable to set default branch to %v", b)
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
switch ghc.EventName {
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":
ghc.Ref = fmt.Sprintf("refs/pull/%.0f/merge", ghc.Event["number"])
case "deployment", "deployment_status":
ghc.Ref = asString(nestedMapLookup(ghc.Event, "deployment", "ref"))
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":
ghc.Ref = asString(ghc.Event["ref"])
default:
defaultBranch := asString(nestedMapLookup(ghc.Event, "repository", "default_branch"))
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 == "" {
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"))
}
}
}

View File

@@ -2,7 +2,7 @@ package model
import (
"context"
"fmt"
"errors"
"testing"
log "github.com/sirupsen/logrus"
@@ -27,19 +27,19 @@ func TestSetRef(t *testing.T) {
tables := []struct {
eventName string
event map[string]interface{}
event map[string]any
ref string
refName string
}{
{
eventName: "pull_request_target",
event: map[string]interface{}{},
event: map[string]any{},
ref: "refs/heads/master",
refName: "master",
},
{
eventName: "pull_request",
event: map[string]interface{}{
event: map[string]any{
"number": 1234.,
},
ref: "refs/pull/1234/merge",
@@ -47,8 +47,8 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "deployment",
event: map[string]interface{}{
"deployment": map[string]interface{}{
event: map[string]any{
"deployment": map[string]any{
"ref": "refs/heads/somebranch",
},
},
@@ -57,8 +57,8 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "release",
event: map[string]interface{}{
"release": map[string]interface{}{
event: map[string]any{
"release": map[string]any{
"tag_name": "v1.0.0",
},
},
@@ -67,7 +67,7 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "push",
event: map[string]interface{}{
event: map[string]any{
"ref": "refs/heads/somebranch",
},
ref: "refs/heads/somebranch",
@@ -75,8 +75,8 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "unknown",
event: map[string]interface{}{
"repository": map[string]interface{}{
event: map[string]any{
"repository": map[string]any{
"default_branch": "main",
},
},
@@ -85,7 +85,7 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "no-event",
event: map[string]interface{}{},
event: map[string]any{},
ref: "refs/heads/master",
refName: "master",
},
@@ -109,12 +109,12 @@ func TestSetRef(t *testing.T) {
t.Run("no-default-branch", func(t *testing.T) {
findGitRef = func(_ context.Context, _ string) (string, error) {
return "", fmt.Errorf("no default branch")
return "", errors.New("no default branch")
}
ghc := &GithubContext{
EventName: "no-default-branch",
Event: map[string]interface{}{},
Event: map[string]any{},
}
ghc.SetRef(context.Background(), "", "/some/dir")
@@ -141,14 +141,14 @@ func TestSetSha(t *testing.T) {
tables := []struct {
eventName string
event map[string]interface{}
event map[string]any
sha string
}{
{
eventName: "pull_request_target",
event: map[string]interface{}{
"pull_request": map[string]interface{}{
"base": map[string]interface{}{
event: map[string]any{
"pull_request": map[string]any{
"base": map[string]any{
"sha": "pr-base-sha",
},
},
@@ -157,15 +157,15 @@ func TestSetSha(t *testing.T) {
},
{
eventName: "pull_request",
event: map[string]interface{}{
event: map[string]any{
"number": 1234.,
},
sha: "1234fakesha",
},
{
eventName: "deployment",
event: map[string]interface{}{
"deployment": map[string]interface{}{
event: map[string]any{
"deployment": map[string]any{
"sha": "deployment-sha",
},
},
@@ -173,12 +173,12 @@ func TestSetSha(t *testing.T) {
},
{
eventName: "release",
event: map[string]interface{}{},
event: map[string]any{},
sha: "1234fakesha",
},
{
eventName: "push",
event: map[string]interface{}{
event: map[string]any{
"after": "push-sha",
"deleted": false,
},
@@ -186,12 +186,12 @@ func TestSetSha(t *testing.T) {
},
{
eventName: "unknown",
event: map[string]interface{}{},
event: map[string]any{},
sha: "1234fakesha",
},
{
eventName: "no-event",
event: map[string]interface{}{},
event: map[string]any{},
sha: "1234fakesha",
},
}

View File

@@ -8,7 +8,7 @@ import (
"os"
"path/filepath"
"regexp"
"sort"
"slices"
log "github.com/sirupsen/logrus"
)
@@ -60,6 +60,13 @@ type PlannerConfig struct {
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
func NewWorkflowPlanner(path string, config PlannerConfig) (WorkflowPlanner, error) {
path, err := filepath.Abs(path)
@@ -281,11 +288,8 @@ func (wp *workflowPlanner) GetEvents() []string {
for _, w := range wp.workflows {
found := false
for _, e := range events {
for _, we := range w.On() {
if e == we {
found = true
break
}
if slices.Contains(w.On(), e) {
found = true
}
if found {
break
@@ -298,9 +302,7 @@ func (wp *workflowPlanner) GetEvents() []string {
}
// sort the list based on depth of dependencies
sort.Slice(events, func(i, j int) bool {
return events[i] < events[j]
})
slices.Sort(events)
return events
}
@@ -331,7 +333,7 @@ func (s *Stage) GetJobIDs() []string {
// Merge stages with existing stages in plan
func (p *Plan) mergeStages(stages []*Stage) {
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)
if i >= len(p.Stages) {
newStages[i].Runs = append(newStages[i].Runs, stages[i].Runs...)

View File

@@ -6,6 +6,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type WorkflowPlanTest struct {
@@ -28,14 +29,14 @@ func TestPlanner(t *testing.T) {
}
workdir, err := filepath.Abs("testdata")
assert.NoError(t, err, workdir)
require.NoError(t, err, workdir)
for _, table := range tables {
fullWorkflowPath := filepath.Join(workdir, table.workflowPath)
_, err = NewWorkflowPlanner(fullWorkflowPath, PlannerConfig{
Recursive: !table.noWorkflowRecurse,
})
if table.errorMessage == "" {
assert.NoError(t, err, "WorkflowPlanner should exit without any error")
require.NoError(t, err, "WorkflowPlanner should exit without any error")
} else {
assert.EqualError(t, err, table.errorMessage)
}
@@ -55,6 +56,6 @@ func TestWorkflow(t *testing.T) {
// Check that a valid job id returns non-error
result, err := createStages(&workflow, "valid_job")
assert.Nil(t, err)
require.NoError(t, err)
assert.NotNil(t, result)
}

View File

@@ -4,13 +4,15 @@ import (
"errors"
"fmt"
"io"
"maps"
"reflect"
"regexp"
"slices"
"strconv"
"strings"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/schema"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/schema"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
)
@@ -61,7 +63,7 @@ func (w *Workflow) On() []string {
}
return val
case yaml.MappingNode:
var val map[string]interface{}
var val map[string]any
err := w.RawOn.Decode(&val)
if err != nil {
log.Fatal(err)
@@ -75,9 +77,9 @@ func (w *Workflow) On() []string {
return nil
}
func (w *Workflow) OnEvent(event string) interface{} {
func (w *Workflow) OnEvent(event string) any {
if w.RawOn.Kind == yaml.MappingNode {
var val map[string]interface{}
var val map[string]any
if !decodeNode(w.RawOn, &val) {
return nil
}
@@ -128,10 +130,8 @@ func (w *Workflow) WorkflowDispatchConfig() *WorkflowDispatch {
if !decodeNode(w.RawOn, &val) {
return nil
}
for _, v := range val {
if v == "workflow_dispatch" {
return &WorkflowDispatch{}
}
if slices.Contains(val, "workflow_dispatch") {
return &WorkflowDispatch{}
}
case yaml.MappingNode:
var val map[string]yaml.Node
@@ -206,7 +206,7 @@ type Job struct {
Defaults Defaults `yaml:"defaults"`
Outputs map[string]string `yaml:"outputs"`
Uses string `yaml:"uses"`
With map[string]interface{} `yaml:"with"`
With map[string]any `yaml:"with"`
RawSecrets yaml.Node `yaml:"secrets"`
Result string
}
@@ -384,9 +384,9 @@ func (j *Job) Environment() map[string]string {
}
// 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 {
var val map[string][]interface{}
var val map[string][]any
if !decodeNode(j.Strategy.RawMatrix, &val) {
return nil
}
@@ -397,32 +397,32 @@ func (j *Job) Matrix() map[string][]interface{} {
// GetMatrixes returns the matrix cross product
// It skips includes and hard fails excludes for non-existing keys
func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
matrixes := make([]map[string]interface{}, 0)
func (j *Job) GetMatrixes() ([]map[string]any, error) {
matrixes := make([]map[string]any, 0)
if j.Strategy != nil {
j.Strategy.FailFast = j.Strategy.GetFailFast()
j.Strategy.MaxParallel = j.Strategy.GetMaxParallel()
if m := j.Matrix(); m != nil {
includes := make([]map[string]interface{}, 0)
extraIncludes := make([]map[string]interface{}, 0)
includes := make([]map[string]any, 0)
extraIncludes := make([]map[string]any, 0)
for _, v := range m["include"] {
switch t := v.(type) {
case []interface{}:
case []any:
for _, i := range t {
i := i.(map[string]interface{})
i := i.(map[string]any)
includes = append(includes, i)
}
case interface{}:
v := v.(map[string]interface{})
case any:
v := v.(map[string]any)
includes = append(includes, v)
}
}
delete(m, "include")
excludes := make([]map[string]interface{}, 0)
excludes := make([]map[string]any, 0)
for _, e := range m["exclude"] {
e := e.(map[string]interface{})
e := e.(map[string]any)
for k := range e {
if _, ok := m[k]; ok {
excludes = append(excludes, e)
@@ -451,9 +451,7 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
if commonKeysMatch2(matrix, include, m) {
matched = true
log.Debugf("Adding include values '%v' to existing entry", include)
for k, v := range include {
matrix[k] = v
}
maps.Copy(matrix, include)
}
}
if !matched {
@@ -465,19 +463,19 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
matrixes = append(matrixes, include)
}
if len(matrixes) == 0 {
matrixes = append(matrixes, make(map[string]interface{}))
matrixes = append(matrixes, make(map[string]any))
}
} else {
matrixes = append(matrixes, make(map[string]interface{}))
matrixes = append(matrixes, make(map[string]any))
}
} else {
matrixes = append(matrixes, make(map[string]interface{}))
matrixes = append(matrixes, make(map[string]any))
log.Debugf("Empty Strategy, matrixes=%v", matrixes)
}
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 {
if bVal, ok := b[aKey]; ok && !reflect.DeepEqual(aVal, bVal) {
return false
@@ -486,7 +484,7 @@ func commonKeysMatch(a map[string]interface{}, b map[string]interface{}) bool {
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 {
_, useKey := m[aKey]
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 {
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
}
return env
@@ -752,11 +750,11 @@ func (w *Workflow) GetJobIDs() []string {
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)
}
func decodeNode(node yaml.Node, out interface{}) bool {
func decodeNode(node yaml.Node, out any) bool {
if err := node.Decode(out); err != nil {
if OnDecodeNodeError != nil {
OnDecodeNodeError(node, out, err)

View File

@@ -22,7 +22,7 @@ jobs:
`
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.Contains(t, workflow.On(), "push")
@@ -41,7 +41,7 @@ jobs:
`
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.Contains(t, workflow.On(), "push")
@@ -67,7 +67,7 @@ jobs:
`
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.Contains(t, workflow.On(), "push")
assert.Contains(t, workflow.On(), "pull_request")
@@ -86,8 +86,8 @@ jobs:
- uses: ./actions/docker-url`
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
assert.NoError(t, err, "read workflow should succeed")
assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest"})
require.NoError(t, err, "read workflow should succeed")
assert.Equal(t, []string{"ubuntu-latest"}, workflow.Jobs["test"].RunsOn())
}
func TestReadWorkflow_RunsOnLabelsWithGroup(t *testing.T) {
@@ -104,8 +104,8 @@ jobs:
- uses: ./actions/docker-url`
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
assert.NoError(t, err, "read workflow should succeed")
assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest", "linux"})
require.NoError(t, err, "read workflow should succeed")
assert.Equal(t, []string{"ubuntu-latest", "linux"}, workflow.Jobs["test"].RunsOn())
}
func TestReadWorkflow_StringContainer(t *testing.T) {
@@ -129,7 +129,7 @@ jobs:
`
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.Contains(t, workflow.Jobs["test"].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{})
assert.NoError(t, err, "read workflow should succeed")
require.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.Jobs, 1)
container := workflow.GetJob("test").Container()
@@ -197,31 +197,31 @@ jobs:
`
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)
jobType, err := workflow.Jobs["default-job"].Type()
assert.Equal(t, nil, err)
require.NoError(t, err)
assert.Equal(t, JobTypeDefault, jobType)
jobType, err = workflow.Jobs["remote-reusable-workflow-yml"].Type()
assert.Equal(t, nil, err)
require.NoError(t, err)
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
jobType, err = workflow.Jobs["remote-reusable-workflow-yaml"].Type()
assert.Equal(t, nil, err)
require.NoError(t, err)
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
jobType, err = workflow.Jobs["remote-reusable-workflow-custom-path"].Type()
assert.Equal(t, nil, err)
require.NoError(t, err)
assert.Equal(t, JobTypeReusableWorkflowRemote, jobType)
jobType, err = workflow.Jobs["local-reusable-workflow-yml"].Type()
assert.Equal(t, nil, err)
require.NoError(t, err)
assert.Equal(t, JobTypeReusableWorkflowLocal, jobType)
jobType, err = workflow.Jobs["local-reusable-workflow-yaml"].Type()
assert.Equal(t, nil, err)
require.NoError(t, err)
assert.Equal(t, JobTypeReusableWorkflowLocal, jobType)
}
@@ -241,24 +241,24 @@ jobs:
`
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)
jobType, err := workflow.Jobs["remote-reusable-workflow-missing-version"].Type()
assert.Equal(t, JobTypeInvalid, jobType)
assert.NotEqual(t, nil, err)
require.Error(t, err)
jobType, err = workflow.Jobs["remote-reusable-workflow-bad-extension"].Type()
assert.Equal(t, JobTypeInvalid, jobType)
assert.NotEqual(t, nil, err)
require.Error(t, err)
jobType, err = workflow.Jobs["local-reusable-workflow-bad-extension"].Type()
assert.Equal(t, JobTypeInvalid, jobType)
assert.NotEqual(t, nil, err)
require.Error(t, err)
jobType, err = workflow.Jobs["local-reusable-workflow-bad-path"].Type()
assert.Equal(t, JobTypeInvalid, jobType)
assert.NotEqual(t, nil, err)
require.Error(t, err)
}
func TestReadWorkflow_StepsTypes(t *testing.T) {
@@ -283,7 +283,7 @@ jobs:
`
_, 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
@@ -315,7 +315,7 @@ jobs:
`
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["test1"].Steps, 1)
@@ -330,76 +330,74 @@ jobs:
func TestReadWorkflow_Strategy(t *testing.T) {
w, err := NewWorkflowPlanner("testdata/strategy/push.yml", PlannerConfig{})
assert.NoError(t, err)
require.NoError(t, err)
p, err := w.PlanJob("strategy-only-max-parallel")
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, len(p.Stages), 1)
assert.Equal(t, len(p.Stages[0].Runs), 1)
assert.Len(t, p.Stages, 1)
assert.Len(t, p.Stages[0].Runs, 1)
wf := p.Stages[0].Runs[0].Workflow
job := wf.Jobs["strategy-only-max-parallel"]
matrixes, err := job.GetMatrixes()
assert.NoError(t, err)
assert.Equal(t, matrixes, []map[string]interface{}{{}})
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
assert.Equal(t, job.Strategy.MaxParallel, 2)
assert.Equal(t, job.Strategy.FailFast, true)
require.NoError(t, err)
assert.Equal(t, []map[string]any{{}}, matrixes)
assert.Equal(t, job.Matrix(), map[string][]any(nil))
assert.Equal(t, 2, job.Strategy.MaxParallel)
assert.True(t, job.Strategy.FailFast)
job = wf.Jobs["strategy-only-fail-fast"]
matrixes, err = job.GetMatrixes()
assert.NoError(t, err)
assert.Equal(t, matrixes, []map[string]interface{}{{}})
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
assert.Equal(t, job.Strategy.MaxParallel, 4)
assert.Equal(t, job.Strategy.FailFast, false)
require.NoError(t, err)
assert.Equal(t, []map[string]any{{}}, matrixes)
assert.Equal(t, job.Matrix(), map[string][]any(nil))
assert.Equal(t, 4, job.Strategy.MaxParallel)
assert.False(t, job.Strategy.FailFast)
job = wf.Jobs["strategy-no-matrix"]
matrixes, err = job.GetMatrixes()
assert.NoError(t, err)
assert.Equal(t, matrixes, []map[string]interface{}{{}})
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
assert.Equal(t, job.Strategy.MaxParallel, 2)
assert.Equal(t, job.Strategy.FailFast, false)
require.NoError(t, err)
assert.Equal(t, []map[string]any{{}}, matrixes)
assert.Equal(t, job.Matrix(), map[string][]any(nil))
assert.Equal(t, 2, job.Strategy.MaxParallel)
assert.False(t, job.Strategy.FailFast)
job = wf.Jobs["strategy-all"]
matrixes, err = job.GetMatrixes()
assert.NoError(t, err)
assert.Equal(t, matrixes,
[]map[string]interface{}{
{"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-d", "node-version": "16.x", "site": "staging", "php-version": 5.4},
{"datacenter": "site-a", "node-version": "10.x", "site": "prod"},
{"datacenter": "site-b", "node-version": "12.x", "site": "dev"},
},
require.NoError(t, err)
assert.Equal(t, []map[string]any{
{"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-d", "node-version": "16.x", "site": "staging", "php-version": 5.4},
{"datacenter": "site-a", "node-version": "10.x", "site": "prod"},
{"datacenter": "site-b", "node-version": "12.x", "site": "dev"},
}, matrixes,
)
assert.Equal(t, job.Matrix(),
map[string][]interface{}{
"datacenter": {"site-c", "site-d"},
"exclude": {
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"},
assert.Equal(t, map[string][]any{
"datacenter": {"site-c", "site-d"},
"exclude": {
map[string]any{"datacenter": "site-d", "node-version": "14.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, job.Strategy.FailFast, false)
assert.Equal(t, 2, job.Strategy.MaxParallel)
assert.False(t, job.Strategy.FailFast)
}
func TestMatrixOnlyIncludes(t *testing.T) {
matrix := map[string][]interface{}{
"include": []interface{}{
map[string]interface{}{"a": "1", "b": "2"},
map[string]interface{}{"a": "3", "b": "4"},
matrix := map[string][]any{
"include": []any{
map[string]any{"a": "1", "b": "2"},
map[string]any{"a": "3", "b": "4"},
},
}
rN := yaml.Node{}
@@ -413,11 +411,10 @@ func TestMatrixOnlyIncludes(t *testing.T) {
assert.Equal(t, job.Matrix(), matrix)
matrixes, err := job.GetMatrixes()
require.NoError(t, err)
assert.Equal(t, matrixes,
[]map[string]interface{}{
{"a": "1", "b": "2"},
{"a": "3", "b": "4"},
},
assert.Equal(t, []map[string]any{
{"a": "1", "b": "2"},
{"a": "3", "b": "4"},
}, matrixes,
)
}
@@ -436,7 +433,7 @@ func TestStep_ShellCommand(t *testing.T) {
for _, tt := range tests {
t.Run(tt.shell, func(t *testing.T) {
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
`
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()
assert.Nil(t, workflowDispatch)
@@ -466,7 +463,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
- run: echo Test
`
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()
assert.NotNil(t, workflowDispatch)
assert.Nil(t, workflowDispatch.Inputs)
@@ -481,7 +478,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
- run: echo Test
`
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()
assert.Nil(t, workflowDispatch)
@@ -495,7 +492,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
- run: echo Test
`
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()
assert.NotNil(t, workflowDispatch)
assert.Nil(t, workflowDispatch.Inputs)
@@ -512,7 +509,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
- run: echo Test
`
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()
assert.NotNil(t, workflowDispatch)
assert.Nil(t, workflowDispatch.Inputs)
@@ -529,7 +526,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
- run: echo Test
`
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()
assert.Nil(t, workflowDispatch)
@@ -556,7 +553,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
- run: echo Test
`
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()
assert.NotNil(t, workflowDispatch)
assert.Equal(t, WorkflowDispatchInput{
@@ -585,7 +582,7 @@ jobs:
`
_, 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) {
@@ -604,7 +601,7 @@ jobs:
`
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 {
assert.Equal(t, []string{"ubuntu-latest"}, job.RunsOn())
@@ -632,7 +629,7 @@ on: push #*trigger
`
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 {
assert.Equal(t, []string{"ubuntu-latest"}, job.RunsOn())

View File

@@ -13,9 +13,9 @@ import (
"github.com/kballard/go-shellquote"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/container"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/container"
"gitea.com/gitea/act_runner/pkg/model"
)
type actionStep interface {
@@ -154,14 +154,14 @@ func execAsDocker(ctx context.Context, step actionStep, actionName, subpath stri
var prepImage common.Executor
var image string
forcePull := false
if strings.HasPrefix(action.Runs.Image, "docker://") {
image = strings.TrimPrefix(action.Runs.Image, "docker://")
if after, ok := strings.CutPrefix(action.Runs.Image, "docker://"); ok {
image = after
// Apply forcePull only for prebuild docker images
forcePull = rc.Config.ForcePull
} else {
// "-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("act-%s", strings.TrimLeft(image, "-"))
image = "act-" + strings.TrimLeft(image, "-")
image = strings.ToLower(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"))
binds, mounts := rc.GetBindsAndMounts()
networkMode := fmt.Sprintf("container:%s", rc.jobContainerName())
networkMode := "container:" + rc.jobContainerName()
var workdir string
if rc.IsHostEnv(ctx) {
networkMode = "default"
@@ -333,7 +333,7 @@ func populateEnvsFromSavedState(env *map[string]string, step actionStep, rc *Run
state, ok := rc.IntraActionState[step.getStepModel().ID]
if ok {
for name, value := range state {
envName := fmt.Sprintf("STATE_%s", name)
envName := "STATE_" + name
(*env)[envName] = value
}
}
@@ -343,7 +343,7 @@ func populateEnvsFromInput(ctx context.Context, env *map[string]string, action *
eval := rc.NewExpressionEvaluator(ctx)
for inputID, input := range action.Inputs {
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_")
envKey = fmt.Sprintf("INPUT_%s", envKey)
envKey = "INPUT_" + envKey
if _, ok := (*env)[envKey]; !ok {
(*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 {
return steps.pre(ctx)
}
return fmt.Errorf("missing steps in composite action")
return errors.New("missing steps in composite action")
default:
return nil
@@ -512,7 +512,7 @@ func runPostStep(step actionStep) common.Executor {
if steps := step.getCompositeSteps(); steps != nil && steps.post != nil {
return steps.post(ctx)
}
return fmt.Errorf("missing steps in composite action")
return errors.New("missing steps in composite action")
default:
return nil

View File

@@ -13,7 +13,7 @@ import (
"strings"
"time"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
git "github.com/go-git/go-git/v5"
config "github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"

View File

@@ -5,7 +5,7 @@ import (
"io"
"path"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
git "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
)

View File

@@ -9,6 +9,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
//nolint:gosec
@@ -69,7 +70,7 @@ func TestActionCache(t *testing.T) {
buf := &bytes.Buffer{}
// G110: Potential DoS vulnerability via decompression bomb (gosec)
_, err = io.Copy(buf, mytar)
a.NoError(err)
require.NoError(t, err)
str := buf.String()
a.NotEmpty(str)
})

View File

@@ -2,12 +2,13 @@ package runner
import (
"context"
"fmt"
"errors"
"regexp"
"strconv"
"strings"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/model"
)
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 {
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
// evaluated value from the environment
@@ -77,7 +78,7 @@ func newCompositeRunContext(ctx context.Context, parent *RunContext, step action
nodeToolFullPath: parent.nodeToolFullPath,
}
if parent.ContextData != nil {
compositerc.ContextData = map[string]interface{}{}
compositerc.ContextData = map[string]any{}
for k, v := range parent.ContextData {
if !strings.EqualFold("inputs", k) {
compositerc.ContextData[k] = v
@@ -99,7 +100,7 @@ func execAsComposite(step actionStep) common.Executor {
steps := step.getCompositeSteps()
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)
@@ -147,7 +148,7 @@ func (rc *RunContext) compositeExecutor(action *model.Action) *compositeSteps {
for i, step := range action.Runs.Steps {
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

View File

@@ -7,9 +7,10 @@ import (
"strings"
"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/mock"
"github.com/stretchr/testify/require"
)
type closerMock struct {
@@ -99,7 +100,7 @@ runs:
action, err := readActionImpl(context.Background(), tt.step, readFile, model.ActionConfig{})
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, tt.expected, action)
closerMock.AssertExpectations(t)
@@ -218,7 +219,7 @@ func TestActionRunner(t *testing.T) {
err := runActionImpl(tt.step)(ctx)
assert.Nil(t, err)
require.NoError(t, err)
cm.AssertExpectations(t)
})
}

View File

@@ -5,7 +5,7 @@ import (
"regexp"
"strings"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
"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 {
rtn := make(map[string]string)
kvPairList := strings.Split(kvPairs, separator)
for _, kvPair := range kvPairList {
kvPairList := strings.SplitSeq(kvPairs, separator)
for kvPair := range kvPairList {
kv := strings.Split(kvPair, "=")
if len(kv) == 2 {
rtn[kv[0]] = kv[1]

View File

@@ -10,8 +10,8 @@ import (
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/model"
)
func TestSetEnv(t *testing.T) {
@@ -164,7 +164,7 @@ func TestAddmaskUsemask(t *testing.T) {
re := captureOutput(t, func() {
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("::add-mask::secret\n")

View File

@@ -4,8 +4,8 @@ import (
"context"
"io"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/container"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/container"
"github.com/stretchr/testify/mock"
)

View File

@@ -3,7 +3,9 @@ package runner
import (
"bytes"
"context"
"errors"
"fmt"
"maps"
"path"
"reflect"
"regexp"
@@ -12,16 +14,16 @@ import (
_ "embed"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/container"
"github.com/actions-oss/act-cli/pkg/exprparser"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/container"
"gitea.com/gitea/act_runner/pkg/exprparser"
"gitea.com/gitea/act_runner/pkg/model"
"gopkg.in/yaml.v3"
)
// ExpressionEvaluator is the interface for evaluating expressions
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
Interpolate(context.Context, string) string
}
@@ -36,7 +38,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map
// todo: cleanup EvaluationEnvironment creation
using := make(map[string]exprparser.Needs)
strategy := make(map[string]interface{})
strategy := make(map[string]any)
if rc.Run != nil {
job := rc.Run.Job()
if job != nil && job.Strategy != nil {
@@ -64,9 +66,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map
result := model.WorkflowCallResult{
Outputs: map[string]string{},
}
for k, v := range job.Outputs {
result.Outputs[k] = v
}
maps.Copy(result.Outputs, job.Outputs)
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))
}
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
job := rc.Run.Job()
strategy := make(map[string]interface{})
strategy := make(map[string]any)
if job.Strategy != nil {
strategy["fail-fast"] = job.Strategy.FailFast
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) {
hashFiles := func(v []reflect.Value) (interface{}, error) {
func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.Value) (any, error) {
hashFiles := func(v []reflect.Value) (any, error) {
if rc.JobContainer != nil {
timeed, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
@@ -198,9 +198,7 @@ func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.
patterns = append(patterns, s)
}
env := map[string]string{}
for k, v := range rc.Env {
env[k] = v
}
maps.Copy(env, rc.Env)
env["patterns"] = strings.Join(patterns, "\n")
if followSymlink {
env["followSymbolicLinks"] = "true"
@@ -238,7 +236,7 @@ type expressionEvaluator struct {
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.Debugf("evaluating expression '%s'", in)
evaluated, err := ee.interpreter.Evaluate(in, defaultStatusCheck)
@@ -434,7 +432,7 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str
if strStart > -1 {
matches := strPattern.FindStringIndex(in[pos:])
if matches == nil {
panic("unclosed string.")
return "", errors.New("unclosed string.")
}
strStart = -1
@@ -485,8 +483,8 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str
return out, nil
}
func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]interface{} {
inputs := map[string]interface{}{}
func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]any {
inputs := map[string]any{}
setupWorkflowInputs(ctx, &inputs, rc)
@@ -498,8 +496,8 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
}
for k, v := range env {
if strings.HasPrefix(k, "INPUT_") {
inputs[strings.ToLower(strings.TrimPrefix(k, "INPUT_"))] = v
if after, ok := strings.CutPrefix(k, "INPUT_"); ok {
inputs[strings.ToLower(after)] = v
}
}
@@ -523,7 +521,7 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
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 {
config := rc.Run.Workflow.WorkflowCallConfig()

View File

@@ -6,21 +6,23 @@ import (
"os"
"regexp"
"sort"
"strings"
"testing"
"github.com/actions-oss/act-cli/pkg/exprparser"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/exprparser"
"gitea.com/gitea/act_runner/pkg/model"
assert "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
yaml "gopkg.in/yaml.v3"
)
func createRunContext(t *testing.T) *RunContext {
var yml yaml.Node
err := yml.Encode(map[string][]interface{}{
err := yml.Encode(map[string][]any{
"os": {"Linux", "Windows"},
"foo": {"bar", "baz"},
})
assert.NoError(t, err)
require.NoError(t, err)
return &RunContext{
Config: &Config{
@@ -48,7 +50,7 @@ func createRunContext(t *testing.T) *RunContext {
},
},
},
Matrix: map[string]interface{}{
Matrix: map[string]any{
"os": "Linux",
"foo": "bar",
},
@@ -84,7 +86,7 @@ func TestEvaluateRunContext(t *testing.T) {
tables := []struct {
in string
out interface{}
out any
errMesg string
}{
{" 1 ", 1, ""},
@@ -142,7 +144,7 @@ func TestEvaluateRunContext(t *testing.T) {
assertObject := assert.New(t)
out, err := ee.evaluate(context.Background(), table.in, exprparser.DefaultStatusCheckNone)
if table.errMesg == "" {
assertObject.NoError(err, table.in)
require.NoError(t, err, table.in)
if i, ok := table.out.(int); ok {
table.out = float64(i)
}
@@ -165,7 +167,7 @@ func TestEvaluateStep(t *testing.T) {
tables := []struct {
in string
out interface{}
out any
errMesg string
}{
{"steps.idwithnothing.conclusion", model.StepStatusSuccess.String(), ""},
@@ -184,10 +186,10 @@ func TestEvaluateStep(t *testing.T) {
assertObject := assert.New(t)
out, err := ee.evaluate(context.Background(), table.in, exprparser.DefaultStatusCheckNone)
if table.errMesg == "" {
assertObject.NoError(err, table.in)
require.NoError(t, err, table.in)
assertObject.Equal(table.out, out, table.in)
} else {
assertObject.Error(err, table.in)
require.Error(t, err, 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)
}
sort.Strings(keys)
var envsSb284 strings.Builder
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
workflow := fmt.Sprintf(`
@@ -299,6 +303,7 @@ jobs:
steps:
`, envs)
// editorconfig-checker-enable
var workflowSb302 strings.Builder
for _, table := range tables {
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)
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")
if err != nil {

View File

@@ -3,14 +3,15 @@ package runner
import (
"context"
"fmt"
"strconv"
"time"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/model"
)
type jobInfo interface {
matrix() map[string]interface{}
matrix() map[string]any
steps() []*model.Step
startContainer() common.Executor
stopContainer() common.Executor
@@ -70,7 +71,7 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo
}
}
if stepModel.ID == "" {
stepModel.ID = fmt.Sprintf("%d", i)
stepModel.ID = strconv.Itoa(i)
}
step, err := sf.newStep(stepModel, rc)

View File

@@ -2,15 +2,17 @@ package runner
import (
"context"
"fmt"
"errors"
"io"
"slices"
"testing"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/container"
"github.com/actions-oss/act-cli/pkg/model"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/container"
"gitea.com/gitea/act_runner/pkg/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
func TestJobExecutor(t *testing.T) {
@@ -38,9 +40,9 @@ type jobInfoMock struct {
mock.Mock
}
func (jim *jobInfoMock) matrix() map[string]interface{} {
func (jim *jobInfoMock) matrix() map[string]any {
args := jim.Called()
return args.Get(0).(map[string]interface{})
return args.Get(0).(map[string]any)
}
func (jim *jobInfoMock) steps() []*model.Step {
@@ -232,17 +234,12 @@ func TestNewJobExecutor(t *testing.T) {
}
contains := func(needle string, haystack []string) bool {
for _, item := range haystack {
if item == needle {
return true
}
}
return false
return slices.Contains(haystack, needle)
}
for _, tt := range table {
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())
jim := &jobInfoMock{}
@@ -287,7 +284,7 @@ func TestNewJobExecutor(t *testing.T) {
sm.On("main").Return(func(_ context.Context) error {
executorOrder = append(executorOrder, "step"+stepModel.ID)
if tt.hasError {
return fmt.Errorf("error")
return errors.New("error")
}
return nil
})
@@ -303,7 +300,7 @@ func TestNewJobExecutor(t *testing.T) {
}
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 {
executorOrder = append(executorOrder, "interpolateOutputs")
@@ -327,13 +324,13 @@ func TestNewJobExecutor(t *testing.T) {
executor := newJobExecutor(jim, sfm, rc)
err := executor(ctx)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, tt.executedSteps, executorOrder)
jim.AssertExpectations(t)
sfm.AssertExpectations(t)
fmt.Println("::endgroup::")
t.Log("::endgroup::")
})
}
}

View File

@@ -12,8 +12,8 @@ import (
"path/filepath"
"strings"
"github.com/actions-oss/act-cli/pkg/common"
"github.com/actions-oss/act-cli/pkg/filecollector"
"gitea.com/gitea/act_runner/pkg/common"
"gitea.com/gitea/act_runner/pkg/filecollector"
)
type LocalRepositoryCache struct {

View File

@@ -9,7 +9,7 @@ import (
"strings"
"sync"
"github.com/actions-oss/act-cli/pkg/common"
"gitea.com/gitea/act_runner/pkg/common"
"github.com/sirupsen/logrus"
"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
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)
var logger *logrus.Logger

Some files were not shown because too many files have changed in this diff Show More