mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-03-21 22:35:02 +01:00
Compare commits
27 Commits
9fd95d203f
...
act-runner
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5a66bda89 | ||
|
|
07a81d616e | ||
|
|
08c3ea28ca | ||
|
|
8d67364e67 | ||
|
|
059d6b88f6 | ||
|
|
58855dfc6b | ||
|
|
4fed07ffc4 | ||
|
|
f300931212 | ||
|
|
44da20bd14 | ||
|
|
4756f09c5d | ||
|
|
94f719fc40 | ||
|
|
c1ad194f19 | ||
|
|
fa6450d033 | ||
|
|
b0ec3fa4fc | ||
|
|
4fdf9ab904 | ||
|
|
8d702e75e7 | ||
|
|
c192d65d18 | ||
|
|
b53c54f73d | ||
|
|
1670945af3 | ||
|
|
09d18916bf | ||
|
|
bffc600775 | ||
|
|
a27473e6a8 | ||
|
|
a77f10683d | ||
|
|
d187ac2fc1 | ||
|
|
949a40c7a5 | ||
|
|
3413919161 | ||
|
|
40ee0f3ef6 |
@@ -25,16 +25,7 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: golangci/golangci-lint-action@v8.0.0
|
||||
with:
|
||||
version: v2.1.6
|
||||
- uses: megalinter/megalinter/flavors/go@v9.1.0
|
||||
env:
|
||||
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
VALIDATE_ALL_CODEBASE: false
|
||||
GITHUB_STATUS_REPORTER: ${{ !env.ACT }}
|
||||
GITHUB_COMMENT_REPORTER: ${{ !env.ACT }}
|
||||
- run: make lint-go
|
||||
|
||||
test-linux:
|
||||
name: test-linux
|
||||
@@ -43,18 +34,6 @@ jobs:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: Cleanup Docker Engine
|
||||
run: |
|
||||
docker ps -a --format '{{ if eq (truncate .Names 4) "act-" }}
|
||||
{{ .ID }}
|
||||
{{end}}' | xargs -r docker rm -f || :
|
||||
docker volume ls --format '{{ if eq (truncate .Name 4) "act-" }}
|
||||
{{ .Name }}
|
||||
{{ end }}' | xargs -r docker volume rm -f || :
|
||||
docker images --format '{{ if eq (truncate .Repository 4) "act-" }}
|
||||
{{ .ID }}
|
||||
{{ end }}' | xargs -r docker rmi -f || :
|
||||
docker images -q | xargs -r docker rmi || :
|
||||
- name: Set up QEMU
|
||||
if: '!env.NO_QEMU'
|
||||
uses: docker/setup-qemu-action@v3
|
||||
@@ -87,9 +66,9 @@ jobs:
|
||||
env:
|
||||
SERVER_URL: ${{ github.server_url }}
|
||||
- name: Run act from cli
|
||||
run: go run main.go -P ubuntu-latest=node:16-buster-slim -C ./pkg/runner/testdata/ -W ./basic/push.yml
|
||||
run: go run ./internal/app/act-cli -P ubuntu-latest=node:16-buster-slim -C ./pkg/runner/testdata/ -W ./basic/push.yml
|
||||
- name: Run act from cli without docker support
|
||||
run: go run -tags WITHOUT_DOCKER main.go -P ubuntu-latest=-self-hosted -C ./pkg/runner/testdata/ -W ./local-action-js/push.yml
|
||||
run: go run -tags WITHOUT_DOCKER ./internal/app/act-cli -P ubuntu-latest=-self-hosted -C ./pkg/runner/testdata/ -W ./local-action-js/push.yml
|
||||
|
||||
snapshot:
|
||||
name: snapshot
|
||||
@@ -112,7 +91,7 @@ jobs:
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
version: v2
|
||||
args: release --snapshot --clean
|
||||
args: release --snapshot --clean -f ./.goreleaser.act-cli.yml
|
||||
- name: Setup Node
|
||||
continue-on-error: true
|
||||
uses: actions/setup-node@v6
|
||||
|
||||
@@ -15,6 +15,7 @@ env:
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
if: (!vars.PUBLISH_ACT_CLI)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -39,6 +40,7 @@ jobs:
|
||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
release-image:
|
||||
if: (!vars.PUBLISH_ACT_CLI)
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
if: (!vars.PUBLISH_ACT_CLI)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -38,6 +39,7 @@ jobs:
|
||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
|
||||
release-image:
|
||||
if: (!vars.PUBLISH_ACT_CLI)
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
version: latest
|
||||
args: release --clean -f ./.goreleaser.yml -f ./.goreleaser.gitea.yml
|
||||
args: release --clean -f ./.goreleaser.act-cli.yml -f ./.goreleaser.act-cli.gitea.yml
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN || github.token }}
|
||||
- name: Winget
|
||||
|
||||
@@ -3,6 +3,11 @@ on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
env:
|
||||
DOOD: 1
|
||||
NO_QEMU: 1
|
||||
NO_EXTERNAL_IP: 1
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: check and test
|
||||
@@ -17,4 +22,13 @@ jobs:
|
||||
- name: build
|
||||
run: make build
|
||||
- name: test
|
||||
run: make test
|
||||
run: |
|
||||
unset ACTIONS_RUNTIME_URL
|
||||
unset ACTIONS_RESULTS_URL
|
||||
unset ACTIONS_RUNTIME_TOKEN
|
||||
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY#${SERVER_URL%/}/}"
|
||||
export ACT_REPOSITORY="${GITHUB_REPOSITORY}"
|
||||
export ACT_OWNER="${ACT_REPOSITORY%%/*}"
|
||||
make test
|
||||
env:
|
||||
SERVER_URL: ${{ github.server_url }}
|
||||
|
||||
2
.github/workflows/checks.yml
vendored
2
.github/workflows/checks.yml
vendored
@@ -112,7 +112,7 @@ jobs:
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
version: v2
|
||||
args: release --snapshot --clean
|
||||
args: release --snapshot --clean -f ./.goreleaser.act-cli.yml
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
|
||||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: vars.PUBLISH_ACT_CLI
|
||||
# TODO use environment to scope secrets
|
||||
name: release
|
||||
runs-on: ubuntu-latest
|
||||
@@ -28,7 +29,7 @@ jobs:
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
version: latest
|
||||
args: release --clean
|
||||
args: release --clean -f ./.goreleaser.act-cli.yml
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN || github.token }}
|
||||
- name: Winget
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
/act_runner
|
||||
/act
|
||||
.env
|
||||
.runner
|
||||
coverage.txt
|
||||
|
||||
@@ -59,6 +59,9 @@ linters:
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
rules:
|
||||
- linters: [revive]
|
||||
text: avoid meaningless package names
|
||||
paths:
|
||||
- report
|
||||
- third_party$
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
version: 2
|
||||
project_name: act-cli
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
@@ -20,7 +21,7 @@ builds:
|
||||
- '7'
|
||||
ignore:
|
||||
- goos: windows
|
||||
goarm: '6'
|
||||
goarch: arm
|
||||
binary: act
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
10
Makefile
10
Makefile
@@ -1,5 +1,6 @@
|
||||
DIST := dist
|
||||
EXECUTABLE := act_runner
|
||||
ACT_EXECUTABLE := act
|
||||
GOFMT ?= gofumpt -l
|
||||
DIST_DIRS := $(DIST)/binaries $(DIST)/release
|
||||
GO ?= go
|
||||
@@ -68,7 +69,7 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
GO_PACKAGES_TO_VET ?= $(filter-out gitea.com/gitea/act_runner/internal/pkg/client/mocks,$(shell $(GO) list ./...))
|
||||
GO_PACKAGES_TO_VET ?= $(filter-out gitea.com/gitea/act_runner/cmd gitea.com/gitea/act_runner/internal/app/act-cli gitea.com/gitea/act_runner/internal/eval/functions gitea.com/gitea/act_runner/internal/eval/v2 gitea.com/gitea/act_runner/internal/expr gitea.com/gitea/act_runner/internal/model gitea.com/gitea/act_runner/internal/templateeval 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/common/git gitea.com/gitea/act_runner/pkg/container gitea.com/gitea/act_runner/pkg/exprparser gitea.com/gitea/act_runner/pkg/filecollector 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 gitea.com/gitea/act_runner/pkg/tart gitea.com/gitea/act_runner/pkg/workflowpattern gitea.com/gitea/act_runner/pkg/lookpath gitea.com/gitea/act_runner/internal/pkg/client/mocks,$(shell $(GO) list ./...))
|
||||
|
||||
|
||||
TAGS ?=
|
||||
@@ -137,7 +138,7 @@ tidy-check: tidy
|
||||
fi
|
||||
|
||||
test: fmt-check security-check
|
||||
@$(GO) test -race -v -cover -coverprofile coverage.txt ./... && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
||||
@$(GO) test -test.short -v -cover -coverprofile coverage.txt ./... && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
@@ -148,11 +149,14 @@ vet:
|
||||
install: $(GOFILES)
|
||||
$(GO) install -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)'
|
||||
|
||||
build: go-check $(EXECUTABLE)
|
||||
build: go-check $(EXECUTABLE) $(ACT_EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(GOFILES)
|
||||
$(GO) build -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o $@
|
||||
|
||||
$(ACT_EXECUTABLE): $(GOFILES)
|
||||
$(GO) build -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o $@ ./internal/app/act-cli
|
||||
|
||||
.PHONY: deps-backend
|
||||
deps-backend:
|
||||
$(GO) mod download
|
||||
|
||||
@@ -3,11 +3,11 @@ 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 {
|
||||
func drawGraph(plan *model.Plan) {
|
||||
drawings := make([]*common.Drawing, 0)
|
||||
|
||||
jobPen := common.NewPen(common.StyleSingleLine, 96)
|
||||
@@ -34,5 +34,4 @@ func drawGraph(plan *model.Plan) error {
|
||||
for _, d := range drawings {
|
||||
d.Draw(os.Stdout, maxWidth)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
12
cmd/list.go
12
cmd/list.go
@@ -2,13 +2,14 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/actions-oss/act-cli/pkg/model"
|
||||
"gitea.com/gitea/act_runner/pkg/model"
|
||||
)
|
||||
|
||||
func printList(plan *model.Plan) error {
|
||||
func printList(plan *model.Plan) {
|
||||
type lineInfoDef struct {
|
||||
jobID string
|
||||
jobName string
|
||||
@@ -82,7 +83,7 @@ func printList(plan *model.Plan) error {
|
||||
wfNameMaxWidth += 2
|
||||
wfFileMaxWidth += 2
|
||||
|
||||
fmt.Printf("%*s%*s%*s%*s%*s%*s\n",
|
||||
fmt.Fprintf(os.Stdout, "%*s%*s%*s%*s%*s%*s\n",
|
||||
-stageMaxWidth, header.stage,
|
||||
-jobIDMaxWidth, header.jobID,
|
||||
-jobNameMaxWidth, header.jobName,
|
||||
@@ -91,7 +92,7 @@ func printList(plan *model.Plan) error {
|
||||
-eventsMaxWidth, header.events,
|
||||
)
|
||||
for _, line := range lineInfos {
|
||||
fmt.Printf("%*s%*s%*s%*s%*s%*s\n",
|
||||
fmt.Fprintf(os.Stdout, "%*s%*s%*s%*s%*s%*s\n",
|
||||
-stageMaxWidth, line.stage,
|
||||
-jobIDMaxWidth, line.jobID,
|
||||
-jobNameMaxWidth, line.jobName,
|
||||
@@ -101,7 +102,6 @@ func printList(plan *model.Plan) error {
|
||||
)
|
||||
}
|
||||
if duplicateJobIDs {
|
||||
fmt.Print("\nDetected multiple jobs with the same job name, use `-W` to specify the path to the specific workflow.\n")
|
||||
fmt.Fprint(os.Stdout, "\nDetected multiple jobs with the same job name, use `-W` to specify the path to the specific workflow.\n")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
74
cmd/root.go
74
cmd/root.go
@@ -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,14 +228,16 @@ 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)
|
||||
if err != nil {
|
||||
fmt.Println(report)
|
||||
fmt.Fprintln(os.Stdout, report)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -245,28 +255,29 @@ 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)
|
||||
fmt.Fprintln(os.Stdout, report)
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateManPage(cmd *cobra.Command) error {
|
||||
func generateManPage(cmd *cobra.Command) {
|
||||
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))
|
||||
fmt.Print(buf.String())
|
||||
return nil
|
||||
fmt.Fprint(os.Stdout, buf.String())
|
||||
}
|
||||
|
||||
func listOptions(cmd *cobra.Command) error {
|
||||
@@ -275,7 +286,7 @@ func listOptions(cmd *cobra.Command) error {
|
||||
flags = append(flags, Flag{Name: f.Name, Default: f.DefValue, Description: f.Usage, Type: f.Value.Type()})
|
||||
})
|
||||
a, err := json.Marshal(flags)
|
||||
fmt.Println(string(a))
|
||||
fmt.Fprintln(os.Stdout, string(a))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -397,7 +408,8 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
||||
return bugReport(ctx, cmd.Version)
|
||||
}
|
||||
if ok, _ := cmd.Flags().GetBool("man-page"); ok {
|
||||
return generateManPage(cmd)
|
||||
generateManPage(cmd)
|
||||
return nil
|
||||
}
|
||||
if input.listOptions {
|
||||
return listOptions(cmd)
|
||||
@@ -528,18 +540,12 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
||||
}
|
||||
|
||||
if list {
|
||||
err = printList(filterPlan)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(filterPlan)
|
||||
return plannerErr
|
||||
}
|
||||
|
||||
if graph {
|
||||
err = drawGraph(filterPlan)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
drawGraph(filterPlan)
|
||||
return plannerErr
|
||||
}
|
||||
|
||||
@@ -575,7 +581,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 +617,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 +705,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)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestReadSecrets(t *testing.T) {
|
||||
@@ -34,30 +35,40 @@ 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) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
rootCmd := createRootCommand(context.Background(), &Input{}, "")
|
||||
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)
|
||||
}
|
||||
|
||||
func TestRunPush(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
rootCmd := createRootCommand(context.Background(), &Input{}, "")
|
||||
err := newRunCommand(context.Background(), &Input{
|
||||
platforms: []string{"ubuntu-latest=node:16-buster-slim"},
|
||||
workdir: "../pkg/runner/testdata/",
|
||||
workflowsPath: "./basic/push.yml",
|
||||
})(rootCmd, []string{"push"})
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRunPushJsonLogger(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
rootCmd := createRootCommand(context.Background(), &Input{}, "")
|
||||
err := newRunCommand(context.Background(), &Input{
|
||||
platforms: []string{"ubuntu-latest=node:16-buster-slim"},
|
||||
@@ -65,26 +76,32 @@ 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) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
for _, f := range []string{"graph", "list", "bug-report", "man-page"} {
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkflowCall(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
rootCmd := createRootCommand(context.Background(), &Input{}, "")
|
||||
err := newRunCommand(context.Background(), &Input{
|
||||
platforms: []string{"ubuntu-latest=node:16-buster-slim"},
|
||||
@@ -92,10 +109,13 @@ 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) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
wd, _ := filepath.Abs("../pkg/runner/testdata/")
|
||||
rootCmd := createRootCommand(context.Background(), &Input{}, "")
|
||||
err := newRunCommand(context.Background(), &Input{
|
||||
@@ -105,5 +125,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)
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ func newSecrets(secretList []string) secrets {
|
||||
} else if env, ok := os.LookupEnv(secretPairParts[0]); ok && env != "" {
|
||||
s[secretPairParts[0]] = env
|
||||
} else {
|
||||
fmt.Printf("Provide value for '%s': ", secretPairParts[0])
|
||||
fmt.Fprintf(os.Stdout, "Provide value for '%s': ", secretPairParts[0])
|
||||
val, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||||
fmt.Println()
|
||||
fmt.Fprintln(os.Stdout)
|
||||
if err != nil {
|
||||
log.Errorf("failed to read input: %v", err)
|
||||
os.Exit(1)
|
||||
|
||||
69
go.mod
69
go.mod
@@ -6,7 +6,6 @@ require (
|
||||
code.gitea.io/actions-proto-go v0.4.1
|
||||
code.gitea.io/gitea-vet v0.2.3
|
||||
connectrpc.com/connect v1.19.1
|
||||
github.com/actions-oss/act-cli v0.0.0 // will be replaced
|
||||
github.com/avast/retry-go/v4 v4.7.0
|
||||
github.com/docker/docker v28.5.1+incompatible
|
||||
github.com/joho/godotenv v1.5.1
|
||||
@@ -21,83 +20,97 @@ 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/atomicwriter v0.1.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/morikuni/aec v1.0.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opencontainers/selinux v1.13.1 // indirect
|
||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||
github.com/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
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 // indirect
|
||||
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/exp v0.0.0-20240909161429-701f63a606c0 // 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
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
||||
|
||||
56
go.sum
56
go.sum
@@ -8,10 +8,10 @@ cyphar.com/go-pathrs v0.2.3 h1:0pH8gep37wB0BgaXrEaN1OtZhUMeS7VvaejSr6i822o=
|
||||
cyphar.com/go-pathrs v0.2.3/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
gitea.com/actions-oss/act-cli v0.4.2-0.20260220200604-40ee0f3ef6fc h1:KXg17X1FZhnUM4J0bVG3gVS6jQCtkR6U5aV2ch0tJYA=
|
||||
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 +19,14 @@ 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 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
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=
|
||||
@@ -29,8 +35,8 @@ github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHS
|
||||
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
github.com/avast/retry-go/v4 v4.7.0 h1:yjDs35SlGvKwRNSykujfjdMxMhMQQM0TnIjJaHB+Zio=
|
||||
github.com/avast/retry-go/v4 v4.7.0/go.mod h1:ZMPDa3sY2bKgpLtap9JRUgk2yTAba7cgiFhqxY2Sg6Q=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
@@ -41,7 +47,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=
|
||||
@@ -94,8 +102,10 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
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/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
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,10 @@ 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/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 +196,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 +214,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=
|
||||
@@ -203,8 +225,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
|
||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk=
|
||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
||||
@@ -215,49 +237,62 @@ go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4A
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
||||
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.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||
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 +300,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=
|
||||
|
||||
1
internal/app/act-cli/VERSION
Normal file
1
internal/app/act-cli/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
0.4.0
|
||||
19
internal/app/act-cli/main.go
Normal file
19
internal/app/act-cli/main.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"gitea.com/gitea/act_runner/cmd"
|
||||
"gitea.com/gitea/act_runner/pkg/common"
|
||||
)
|
||||
|
||||
//go:embed VERSION
|
||||
var version string
|
||||
|
||||
func main() {
|
||||
ctx, cancel := common.CreateGracefulJobCancellationContext()
|
||||
defer cancel()
|
||||
|
||||
// run the command
|
||||
cmd.Execute(ctx, version)
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||
|
||||
"github.com/actions-oss/act-cli/pkg/artifactcache"
|
||||
"gitea.com/gitea/act_runner/pkg/artifactcache"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -22,7 +22,7 @@ type cacheServerArgs struct {
|
||||
}
|
||||
|
||||
func runCacheServer(configFile *string, cacheArgs *cacheServerArgs) func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
return func(_ *cobra.Command, _ []string) error {
|
||||
cfg, err := config.LoadDefault(*configFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid configuration: %w", err)
|
||||
|
||||
@@ -62,7 +62,7 @@ func Execute(ctx context.Context) {
|
||||
Short: "Generate an example config file",
|
||||
Args: cobra.MaximumNArgs(0),
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
fmt.Printf("%s", config.Example)
|
||||
fmt.Fprintf(os.Stdout, "%s", config.Example)
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
)
|
||||
|
||||
func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
return func(_ *cobra.Command, _ []string) error {
|
||||
cfg, err := config.LoadDefault(*configFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid configuration: %w", err)
|
||||
@@ -144,10 +144,9 @@ func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) fu
|
||||
} else if err != nil {
|
||||
log.WithError(err).Error("fail to invoke Declare")
|
||||
return err
|
||||
} else {
|
||||
log.Infof("runner: %s, with version: %s, with labels: %v, declare successfully",
|
||||
resp.Msg.Runner.Name, resp.Msg.Runner.Version, resp.Msg.Runner.Labels)
|
||||
}
|
||||
log.Infof("runner: %s, with version: %s, with labels: %v, declare successfully",
|
||||
resp.Msg.Runner.Name, resp.Msg.Runner.Version, resp.Msg.Runner.Labels)
|
||||
|
||||
poller := poll.New(cfg, cli, runner)
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -88,9 +88,9 @@ func (i *executeArgs) LoadSecrets() map[string]string {
|
||||
} else if env, ok := os.LookupEnv(secretPairParts[0]); ok && env != "" {
|
||||
s[secretPairParts[0]] = env
|
||||
} else {
|
||||
fmt.Printf("Provide value for '%s': ", secretPairParts[0])
|
||||
fmt.Fprintf(os.Stdout, "Provide value for '%s': ", secretPairParts[0])
|
||||
val, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||||
fmt.Println()
|
||||
fmt.Fprintln(os.Stdout)
|
||||
if err != nil {
|
||||
log.Errorf("failed to read input: %v", err)
|
||||
os.Exit(1)
|
||||
@@ -241,7 +241,7 @@ func printList(plan *model.Plan) {
|
||||
wfNameMaxWidth += 2
|
||||
wfFileMaxWidth += 2
|
||||
|
||||
fmt.Printf("%*s%*s%*s%*s%*s%*s\n",
|
||||
fmt.Fprintf(os.Stdout, "%*s%*s%*s%*s%*s%*s\n",
|
||||
-stageMaxWidth, header.stage,
|
||||
-jobIDMaxWidth, header.jobID,
|
||||
-jobNameMaxWidth, header.jobName,
|
||||
@@ -250,7 +250,7 @@ func printList(plan *model.Plan) {
|
||||
-eventsMaxWidth, header.events,
|
||||
)
|
||||
for _, line := range lineInfos {
|
||||
fmt.Printf("%*s%*s%*s%*s%*s%*s\n",
|
||||
fmt.Fprintf(os.Stdout, "%*s%*s%*s%*s%*s%*s\n",
|
||||
-stageMaxWidth, line.stage,
|
||||
-jobIDMaxWidth, line.jobID,
|
||||
-jobNameMaxWidth, line.jobName,
|
||||
@@ -260,7 +260,7 @@ func printList(plan *model.Plan) {
|
||||
)
|
||||
}
|
||||
if duplicateJobIDs {
|
||||
fmt.Print("\nDetected multiple jobs with the same job name, use `-W` to specify the path to the specific workflow.\n")
|
||||
fmt.Fprint(os.Stdout, "\nDetected multiple jobs with the same job name, use `-W` to specify the path to the specific workflow.\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, _ []string) error {
|
||||
planner, err := model.NewWorkflowPlanner(execArgs.WorkflowsPath(), model.PlannerConfig{
|
||||
Recursive: !execArgs.noWorkflowRecurse,
|
||||
Workflow: model.WorkflowConfig{
|
||||
@@ -392,7 +392,7 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command
|
||||
if len(execArgs.artifactServerPath) == 0 {
|
||||
tempDir, err := os.MkdirTemp("", "gitea-act-")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
@@ -460,7 +460,7 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command
|
||||
log.Debugf("artifacts server started at %s:%s", execArgs.artifactServerPath, execArgs.artifactServerPort)
|
||||
|
||||
ctx = common.WithDryrun(ctx, execArgs.dryrun)
|
||||
executor := r.NewPlanExecutor(plan).Finally(func(ctx context.Context) error {
|
||||
executor := r.NewPlanExecutor(plan).Finally(func(_ context.Context) error {
|
||||
artifactCancel()
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
|
||||
// runRegister registers a runner to the server
|
||||
func runRegister(ctx context.Context, regArgs *registerArgs, configFile *string) func(*cobra.Command, []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
return func(_ *cobra.Command, _ []string) error {
|
||||
log.SetReportCaller(false)
|
||||
isTerm := isatty.IsTerminal(os.Stdout.Fd())
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
@@ -251,7 +251,7 @@ func registerInteractive(ctx context.Context, configFile string, regArgs *regist
|
||||
if stage == StageWaitingForRegistration {
|
||||
log.Infof("Registering runner, name=%s, instance=%s, labels=%v.", inputs.RunnerName, inputs.InstanceAddr, inputs.Labels)
|
||||
if err := doRegister(ctx, cfg, inputs); err != nil {
|
||||
return fmt.Errorf("Failed to register runner: %w", err)
|
||||
return fmt.Errorf("failed to register runner: %w", err)
|
||||
}
|
||||
log.Infof("Runner registered successfully.")
|
||||
return nil
|
||||
@@ -312,7 +312,7 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi
|
||||
return err
|
||||
}
|
||||
if err := doRegister(ctx, cfg, inputs); err != nil {
|
||||
return fmt.Errorf("Failed to register runner: %w", err)
|
||||
return fmt.Errorf("failed to register runner: %w", err)
|
||||
}
|
||||
log.Infof("Runner registered successfully.")
|
||||
return nil
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -142,14 +143,14 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
||||
return err
|
||||
}
|
||||
job := workflow.GetJob(jobID)
|
||||
var stepIds []string
|
||||
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)
|
||||
stepIDs = append(stepIDs, v.ID)
|
||||
}
|
||||
reporter.SetStepIdMapping(stepIds...)
|
||||
reporter.SetStepIdMapping(stepIDs...)
|
||||
|
||||
taskContext := task.Context.Fields
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -62,7 +62,7 @@ func generateWorkflow(task *runnerv1.Task) (*model.Workflow, string, error) {
|
||||
|
||||
// TODO GITEA
|
||||
workflow.Jobs[jobID].RawNeeds = rawNeeds
|
||||
workflow.Jobs[jobID].RawRunsOn.Encode("dummy")
|
||||
_ = workflow.Jobs[jobID].RawRunsOn.Encode("dummy")
|
||||
|
||||
return workflow, jobID, nil
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ 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/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.yaml.in/yaml/v4"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func Test_generateWorkflow(t *testing.T) {
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
},
|
||||
},
|
||||
assert: func(t *testing.T, wf *model.Workflow) {
|
||||
assert.DeepEqual(t, wf.GetJob("job9").Needs(), []string{"job1", "job2"})
|
||||
assert.Equal(t, []string{"job1", "job2"}, wf.GetJob("job9").Needs())
|
||||
},
|
||||
want1: "job9",
|
||||
wantErr: false,
|
||||
@@ -83,8 +83,8 @@ jobs:
|
||||
},
|
||||
assert: func(t *testing.T, wf *model.Workflow) {
|
||||
job := wf.GetJob("test")
|
||||
assert.DeepEqual(t, job.Needs(), []string{})
|
||||
assert.Equal(t, len(job.Steps), 2)
|
||||
assert.Equal(t, []string{}, job.Needs())
|
||||
assert.Len(t, job.Steps, 2)
|
||||
},
|
||||
want1: "test",
|
||||
wantErr: false,
|
||||
@@ -125,9 +125,9 @@ jobs:
|
||||
assert: func(t *testing.T, wf *model.Workflow) {
|
||||
job := wf.GetJob("deploy")
|
||||
needs := job.Needs()
|
||||
assert.DeepEqual(t, needs, []string{"build", "lint", "test"})
|
||||
assert.Equal(t, wf.Jobs["test"].Outputs["coverage"], "80%")
|
||||
assert.Equal(t, wf.Jobs["lint"].Result, "failure")
|
||||
assert.Equal(t, []string{"build", "lint", "test"}, needs)
|
||||
assert.Equal(t, "80%", wf.Jobs["test"].Outputs["coverage"])
|
||||
assert.Equal(t, "failure", wf.Jobs["lint"].Result)
|
||||
},
|
||||
want1: "deploy",
|
||||
wantErr: false,
|
||||
@@ -165,11 +165,11 @@ jobs:
|
||||
},
|
||||
},
|
||||
assert: func(t *testing.T, wf *model.Workflow) {
|
||||
assert.Equal(t, wf.Name, "Complex workflow")
|
||||
assert.Equal(t, wf.Env["NODE_ENV"], "production")
|
||||
assert.Equal(t, wf.Env["CI"], "true")
|
||||
assert.Equal(t, "Complex workflow", wf.Name)
|
||||
assert.Equal(t, "production", wf.Env["NODE_ENV"])
|
||||
assert.Equal(t, "true", wf.Env["CI"])
|
||||
job := wf.GetJob("build")
|
||||
assert.Equal(t, len(job.Steps), 4)
|
||||
assert.Len(t, job.Steps, 4)
|
||||
},
|
||||
want1: "build",
|
||||
wantErr: false,
|
||||
@@ -200,8 +200,8 @@ jobs:
|
||||
assert: func(t *testing.T, wf *model.Workflow) {
|
||||
job := wf.GetJob("integration")
|
||||
container := job.Container()
|
||||
assert.Equal(t, container.Image, "node:18")
|
||||
assert.Equal(t, job.Services["postgres"].Image, "postgres:15")
|
||||
assert.Equal(t, "node:18", container.Image)
|
||||
assert.Equal(t, "postgres:15", job.Services["postgres"].Image)
|
||||
},
|
||||
want1: "integration",
|
||||
wantErr: false,
|
||||
@@ -231,7 +231,7 @@ jobs:
|
||||
job := wf.GetJob("test")
|
||||
matrixes, err := job.GetMatrixes()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(matrixes), 2)
|
||||
assert.Len(t, matrixes, 2)
|
||||
},
|
||||
want1: "test",
|
||||
wantErr: false,
|
||||
@@ -245,9 +245,9 @@ jobs:
|
||||
},
|
||||
},
|
||||
assert: func(t *testing.T, wf *model.Workflow) {
|
||||
assert.Equal(t, wf.Name, "Special: characters & test")
|
||||
assert.Equal(t, "Special: characters & test", wf.Name)
|
||||
job := wf.GetJob("test")
|
||||
assert.Equal(t, len(job.Steps), 3)
|
||||
assert.Len(t, job.Steps, 3)
|
||||
},
|
||||
want1: "test",
|
||||
wantErr: false,
|
||||
@@ -283,7 +283,7 @@ jobs:
|
||||
}
|
||||
require.NoError(t, err)
|
||||
tt.assert(t, got)
|
||||
assert.Equal(t, got1, tt.want1)
|
||||
assert.Equal(t, tt.want1, got1)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -301,7 +301,7 @@ func Test_yamlV4NodeRoundTrip(t *testing.T) {
|
||||
|
||||
out, err := yaml.Marshal(&node)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, string(out), "- a\n- b\n- c\n")
|
||||
assert.Equal(t, "- a\n- b\n- c\n", string(out))
|
||||
})
|
||||
|
||||
t.Run("unmarshal and re-marshal workflow", func(t *testing.T) {
|
||||
@@ -310,7 +310,7 @@ func Test_yamlV4NodeRoundTrip(t *testing.T) {
|
||||
var wf map[string]any
|
||||
err := yaml.Unmarshal(input, &wf)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, wf["name"], "test")
|
||||
assert.Equal(t, "test", wf["name"])
|
||||
|
||||
out, err := yaml.Marshal(wf)
|
||||
require.NoError(t, err)
|
||||
@@ -318,7 +318,7 @@ func Test_yamlV4NodeRoundTrip(t *testing.T) {
|
||||
var wf2 map[string]any
|
||||
err = yaml.Unmarshal(out, &wf2)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, wf2["name"], "test")
|
||||
assert.Equal(t, "test", wf2["name"])
|
||||
})
|
||||
|
||||
t.Run("node kind constants", func(t *testing.T) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ func (e *Evaluator) evalBinaryNode(node *exprparser.BinaryNode) (*EvaluationResu
|
||||
return e.evalBinaryNodeRight(node, left, right)
|
||||
}
|
||||
|
||||
func (e *Evaluator) evalBinaryNodeLeft(node *exprparser.BinaryNode, left *EvaluationResult) (*EvaluationResult, error) {
|
||||
func (e *Evaluator) evalBinaryNodeLeft(node *exprparser.BinaryNode, left *EvaluationResult) (*EvaluationResult, error) { //nolint:unparam
|
||||
switch node.Op {
|
||||
case "&&":
|
||||
if left.IsFalsy() {
|
||||
@@ -187,7 +187,7 @@ func (e *Evaluator) evalBinaryNodeLeft(node *exprparser.BinaryNode, left *Evalua
|
||||
return CreateIntermediateResult(e.Context(), ret), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -5,12 +5,11 @@ 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 {
|
||||
}
|
||||
type FromJSON struct{}
|
||||
|
||||
func (FromJSON) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
|
||||
r, err := eval.Evaluate(args[0])
|
||||
@@ -25,8 +24,7 @@ func (FromJSON) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationRe
|
||||
return CreateIntermediateResult(eval.Context(), res), nil
|
||||
}
|
||||
|
||||
type ToJSON struct {
|
||||
}
|
||||
type ToJSON struct{}
|
||||
|
||||
func (ToJSON) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
|
||||
r, err := eval.Evaluate(args[0])
|
||||
@@ -44,8 +42,7 @@ func (ToJSON) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResu
|
||||
return CreateIntermediateResult(eval.Context(), string(data)), nil
|
||||
}
|
||||
|
||||
type Contains struct {
|
||||
}
|
||||
type Contains struct{}
|
||||
|
||||
func (Contains) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
|
||||
collection, err := eval.Evaluate(args[0])
|
||||
@@ -72,8 +69,7 @@ func (Contains) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationRe
|
||||
return CreateIntermediateResult(eval.Context(), strings.Contains(strings.ToLower(collection.ConvertToString()), strings.ToLower(el.ConvertToString()))), nil
|
||||
}
|
||||
|
||||
type StartsWith struct {
|
||||
}
|
||||
type StartsWith struct{}
|
||||
|
||||
func (StartsWith) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
|
||||
collection, err := eval.Evaluate(args[0])
|
||||
@@ -88,8 +84,7 @@ func (StartsWith) Evaluate(eval *Evaluator, args []exprparser.Node) (*Evaluation
|
||||
return CreateIntermediateResult(eval.Context(), strings.HasPrefix(strings.ToLower(collection.ConvertToString()), strings.ToLower(el.ConvertToString()))), nil
|
||||
}
|
||||
|
||||
type EndsWith struct {
|
||||
}
|
||||
type EndsWith struct{}
|
||||
|
||||
func (EndsWith) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
|
||||
collection, err := eval.Evaluate(args[0])
|
||||
@@ -104,8 +99,7 @@ func (EndsWith) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationRe
|
||||
return CreateIntermediateResult(eval.Context(), strings.HasSuffix(strings.ToLower(collection.ConvertToString()), strings.ToLower(el.ConvertToString()))), nil
|
||||
}
|
||||
|
||||
type Format struct {
|
||||
}
|
||||
type Format struct{}
|
||||
|
||||
func (Format) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
|
||||
collection, err := eval.Evaluate(args[0])
|
||||
@@ -113,7 +107,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 {
|
||||
@@ -126,8 +120,7 @@ func (Format) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResu
|
||||
return CreateIntermediateResult(eval.Context(), ret), err
|
||||
}
|
||||
|
||||
type Join struct {
|
||||
}
|
||||
type Join struct{}
|
||||
|
||||
func (Join) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
|
||||
collection, err := eval.Evaluate(args[0])
|
||||
@@ -164,8 +157,7 @@ func (Join) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult
|
||||
return CreateIntermediateResult(eval.Context(), ""), nil
|
||||
}
|
||||
|
||||
type Case struct {
|
||||
}
|
||||
type Case struct{}
|
||||
|
||||
func (Case) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
|
||||
if len(args)%2 == 0 {
|
||||
|
||||
@@ -20,7 +20,7 @@ type Node interface {
|
||||
|
||||
type ValueNode struct {
|
||||
Kind TokenKind
|
||||
Value interface{}
|
||||
Value any
|
||||
}
|
||||
|
||||
// FunctionNode represents a function call with arguments.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)},
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -7,10 +7,9 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type EmptyTraceWriter struct {
|
||||
}
|
||||
type EmptyTraceWriter struct{}
|
||||
|
||||
func (e *EmptyTraceWriter) Info(_ string, _ ...interface{}) {
|
||||
func (e *EmptyTraceWriter) Info(_ string, _ ...any) {
|
||||
}
|
||||
|
||||
func TestStrategy(t *testing.T) {
|
||||
@@ -28,7 +27,8 @@ matrix:
|
||||
- a
|
||||
- b
|
||||
`, 4, 0},
|
||||
{`
|
||||
{
|
||||
`
|
||||
matrix:
|
||||
label:
|
||||
- a
|
||||
@@ -37,7 +37,8 @@ matrix:
|
||||
- label: a
|
||||
x: self`, 2, 0,
|
||||
},
|
||||
{`
|
||||
{
|
||||
`
|
||||
matrix:
|
||||
label:
|
||||
- a
|
||||
@@ -46,7 +47,8 @@ matrix:
|
||||
- label: c
|
||||
x: self`, 2, 1,
|
||||
},
|
||||
{`
|
||||
{
|
||||
`
|
||||
matrix:
|
||||
label:
|
||||
- a
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -179,7 +179,7 @@ func (ee ExpressionEvaluator) evaluateYamlNodeInternal(ctx context.Context, node
|
||||
case yaml.SequenceNode:
|
||||
return ee.evaluateSequenceYamlNode(ctx, node, snode)
|
||||
default:
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -437,7 +437,7 @@ func findCache(db *bolthold.Store, keys []string, version string) (*Cache, error
|
||||
}
|
||||
return cache, nil
|
||||
}
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
|
||||
func insertCache(db *bolthold.Store, cache *Cache) error {
|
||||
|
||||
@@ -41,8 +41,11 @@ func TestHandler(t *testing.T) {
|
||||
require.NoError(t, handler.Close())
|
||||
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)
|
||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, 1), "", nil)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
require.Error(t, err)
|
||||
})
|
||||
}()
|
||||
|
||||
@@ -51,6 +54,7 @@ func TestHandler(t *testing.T) {
|
||||
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20"
|
||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 204, resp.StatusCode)
|
||||
})
|
||||
|
||||
@@ -64,16 +68,18 @@ 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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
})
|
||||
|
||||
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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
})
|
||||
|
||||
@@ -90,8 +96,9 @@ 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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(&first))
|
||||
@@ -104,8 +111,9 @@ 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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(&second))
|
||||
@@ -117,12 +125,13 @@ 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/*")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
})
|
||||
|
||||
@@ -134,6 +143,7 @@ func TestHandler(t *testing.T) {
|
||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
})
|
||||
|
||||
@@ -151,8 +161,9 @@ 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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
got := struct {
|
||||
@@ -169,11 +180,13 @@ func TestHandler(t *testing.T) {
|
||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
}
|
||||
{
|
||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
}
|
||||
{
|
||||
@@ -184,6 +197,7 @@ func TestHandler(t *testing.T) {
|
||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
}
|
||||
})
|
||||
@@ -202,8 +216,9 @@ 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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
got := struct {
|
||||
@@ -220,14 +235,16 @@ func TestHandler(t *testing.T) {
|
||||
req.Header.Set("Content-Range", "bytes xx-99/*")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
}
|
||||
})
|
||||
@@ -236,6 +253,7 @@ func TestHandler(t *testing.T) {
|
||||
{
|
||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, 100), "", nil)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
}
|
||||
})
|
||||
@@ -254,8 +272,9 @@ 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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
got := struct {
|
||||
@@ -272,16 +291,19 @@ func TestHandler(t *testing.T) {
|
||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
}
|
||||
{
|
||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
}
|
||||
{
|
||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
}
|
||||
})
|
||||
@@ -300,8 +322,9 @@ 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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
got := struct {
|
||||
@@ -318,30 +341,35 @@ func TestHandler(t *testing.T) {
|
||||
req.Header.Set("Content-Range", "bytes 0-59/*")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
}
|
||||
{
|
||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 500, resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
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)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 400, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("get with not exist id", func(t *testing.T) {
|
||||
resp, err := http.Get(fmt.Sprintf("%s/artifacts/%d", base, 100))
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 404, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("get with not exist id", func(t *testing.T) {
|
||||
resp, err := http.Get(fmt.Sprintf("%s/artifacts/%d", base, 100))
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 404, resp.StatusCode)
|
||||
})
|
||||
|
||||
@@ -373,6 +401,7 @@ func TestHandler(t *testing.T) {
|
||||
|
||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version))
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
/*
|
||||
@@ -393,6 +422,7 @@ func TestHandler(t *testing.T) {
|
||||
|
||||
contentResp, err := http.Get(got.ArchiveLocation)
|
||||
require.NoError(t, err)
|
||||
defer contentResp.Body.Close()
|
||||
require.Equal(t, 200, contentResp.StatusCode)
|
||||
content, err := io.ReadAll(contentResp.Body)
|
||||
require.NoError(t, err)
|
||||
@@ -411,6 +441,7 @@ func TestHandler(t *testing.T) {
|
||||
reqKey := key + "_aBc"
|
||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKey, version))
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
got := struct {
|
||||
Result string `json:"result"`
|
||||
@@ -450,6 +481,7 @@ func TestHandler(t *testing.T) {
|
||||
|
||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version))
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
/*
|
||||
@@ -468,6 +500,7 @@ func TestHandler(t *testing.T) {
|
||||
|
||||
contentResp, err := http.Get(got.ArchiveLocation)
|
||||
require.NoError(t, err)
|
||||
defer contentResp.Body.Close()
|
||||
require.Equal(t, 200, contentResp.StatusCode)
|
||||
content, err := io.ReadAll(contentResp.Body)
|
||||
require.NoError(t, err)
|
||||
@@ -502,6 +535,7 @@ func TestHandler(t *testing.T) {
|
||||
|
||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version))
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
/*
|
||||
@@ -521,6 +555,7 @@ func TestHandler(t *testing.T) {
|
||||
|
||||
contentResp, err := http.Get(got.ArchiveLocation)
|
||||
require.NoError(t, err)
|
||||
defer contentResp.Body.Close()
|
||||
require.Equal(t, 200, contentResp.StatusCode)
|
||||
content, err := io.ReadAll(contentResp.Body)
|
||||
require.NoError(t, err)
|
||||
@@ -528,7 +563,7 @@ func TestHandler(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func uploadCacheNormally(t *testing.T, base, key, version string, content []byte) {
|
||||
func uploadCacheNormally(t *testing.T, base, key, version string, content []byte) { //nolint:unparam
|
||||
var id uint64
|
||||
{
|
||||
body, err := json.Marshal(&Request{
|
||||
@@ -537,8 +572,9 @@ 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)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
got := struct {
|
||||
@@ -555,17 +591,20 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte
|
||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
}
|
||||
{
|
||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
}
|
||||
var archiveLocation string
|
||||
{
|
||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
got := struct {
|
||||
Result string `json:"result"`
|
||||
@@ -580,6 +619,7 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte
|
||||
{
|
||||
resp, err := http.Get(archiveLocation) //nolint:gosec
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
got, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
@@ -687,7 +727,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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,18 +271,17 @@ 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)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -305,12 +304,11 @@ 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")
|
||||
|
||||
file, err := r.fs.OpenAppendable(safePath)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -342,7 +340,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 +358,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 +403,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 +422,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 +437,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)
|
||||
|
||||
@@ -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 {
|
||||
@@ -55,8 +55,7 @@ type WriteFS interface {
|
||||
OpenAppendable(name string) (WritableFile, error)
|
||||
}
|
||||
|
||||
type readWriteFSImpl struct {
|
||||
}
|
||||
type readWriteFSImpl struct{}
|
||||
|
||||
func (fwfs readWriteFSImpl) Open(name string) (fs.File, error) {
|
||||
return os.Open(name)
|
||||
@@ -74,7 +73,6 @@ func (fwfs readWriteFSImpl) OpenAppendable(name string) (WritableFile, error) {
|
||||
return nil, err
|
||||
}
|
||||
file, err := os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0o644)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -127,7 +125,6 @@ func uploads(router *httprouter.Router, baseDir string, fsys WriteFS) {
|
||||
}
|
||||
return fsys.OpenWritable(safePath)
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -39,7 +40,7 @@ type writeMapFS struct {
|
||||
}
|
||||
|
||||
func (fsys writeMapFS) OpenWritable(name string) (WritableFile, error) {
|
||||
var file = &writableMapFile{
|
||||
file := &writableMapFile{
|
||||
MapFile: fstest.MapFile{
|
||||
Data: []byte("content2"),
|
||||
},
|
||||
@@ -50,7 +51,7 @@ func (fsys writeMapFS) OpenWritable(name string) (WritableFile, error) {
|
||||
}
|
||||
|
||||
func (fsys writeMapFS) OpenAppendable(name string) (WritableFile, error) {
|
||||
var file = &writableMapFile{
|
||||
file := &writableMapFile{
|
||||
MapFile: fstest.MapFile{
|
||||
Data: []byte("content2"),
|
||||
},
|
||||
@@ -63,12 +64,12 @@ func (fsys writeMapFS) OpenAppendable(name string) (WritableFile, error) {
|
||||
func TestNewArtifactUploadPrepare(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{})
|
||||
memfs := fstest.MapFS(map[string]*fstest.MapFile{})
|
||||
|
||||
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)
|
||||
@@ -89,12 +90,12 @@ func TestNewArtifactUploadPrepare(t *testing.T) {
|
||||
func TestArtifactUploadBlob(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{})
|
||||
memfs := fstest.MapFS(map[string]*fstest.MapFile{})
|
||||
|
||||
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)
|
||||
@@ -116,12 +117,12 @@ func TestArtifactUploadBlob(t *testing.T) {
|
||||
func TestFinalizeArtifactUpload(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{})
|
||||
memfs := fstest.MapFS(map[string]*fstest.MapFile{})
|
||||
|
||||
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)
|
||||
@@ -142,7 +143,7 @@ func TestFinalizeArtifactUpload(t *testing.T) {
|
||||
func TestListArtifacts(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{
|
||||
memfs := fstest.MapFS(map[string]*fstest.MapFile{
|
||||
"artifact/server/path/1/file.txt": {
|
||||
Data: []byte(""),
|
||||
},
|
||||
@@ -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)
|
||||
@@ -174,7 +175,7 @@ func TestListArtifacts(t *testing.T) {
|
||||
func TestListArtifactContainer(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{
|
||||
memfs := fstest.MapFS(map[string]*fstest.MapFile{
|
||||
"artifact/server/path/1/some/file": {
|
||||
Data: []byte(""),
|
||||
},
|
||||
@@ -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)
|
||||
@@ -207,7 +208,7 @@ func TestListArtifactContainer(t *testing.T) {
|
||||
func TestDownloadArtifactFile(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{
|
||||
memfs := fstest.MapFS(map[string]*fstest.MapFile{
|
||||
"artifact/server/path/1/some/file": {
|
||||
Data: []byte("content"),
|
||||
},
|
||||
@@ -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::")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -347,7 +348,7 @@ func TestMkdirFsImplSafeResolve(t *testing.T) {
|
||||
func TestDownloadArtifactFileUnsafePath(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{
|
||||
memfs := fstest.MapFS(map[string]*fstest.MapFile{
|
||||
"artifact/server/path/some/file": {
|
||||
Data: []byte("content"),
|
||||
},
|
||||
@@ -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)
|
||||
@@ -373,12 +374,12 @@ func TestDownloadArtifactFileUnsafePath(t *testing.T) {
|
||||
func TestArtifactUploadBlobUnsafePath(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{})
|
||||
memfs := fstest.MapFS(map[string]*fstest.MapFile{})
|
||||
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,45 +10,46 @@ 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")
|
||||
taskIDClaim, ok := claims["TaskID"]
|
||||
assert.True(t, ok, "Has TaskID claim in jwt token")
|
||||
assert.Equal(t, float64(taskID), taskIDClaim, "Supplied taskid must match stored one")
|
||||
assert.InDelta(t, float64(taskID), taskIDClaim, 0, "Supplied taskid must match stored one")
|
||||
acClaim, ok := claims["ac"]
|
||||
assert.True(t, ok, "Has ac claim in jwt token")
|
||||
ac, ok := acClaim.(string)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -72,6 +72,7 @@ func (p *Pen) drawTopBars(buf io.Writer, labels ...string) {
|
||||
}
|
||||
fmt.Fprintf(buf, "\n")
|
||||
}
|
||||
|
||||
func (p *Pen) drawBottomBars(buf io.Writer, labels ...string) {
|
||||
style := styleDefs[p.style]
|
||||
for _, label := range labels {
|
||||
@@ -83,6 +84,7 @@ func (p *Pen) drawBottomBars(buf io.Writer, labels ...string) {
|
||||
}
|
||||
fmt.Fprintf(buf, "\n")
|
||||
}
|
||||
|
||||
func (p *Pen) drawLabels(buf io.Writer, labels ...string) {
|
||||
style := styleDefs[p.style]
|
||||
for _, label := range labels {
|
||||
@@ -125,11 +127,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)
|
||||
|
||||
@@ -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)))
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"errors"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewWorkflow(t *testing.T) {
|
||||
@@ -16,11 +18,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 +35,7 @@ func TestNewWorkflow(t *testing.T) {
|
||||
runcount++
|
||||
return nil
|
||||
})
|
||||
assert.Nil(successWorkflow(ctx))
|
||||
require.NoError(t, successWorkflow(ctx))
|
||||
assert.Equal(2, runcount)
|
||||
}
|
||||
|
||||
@@ -55,7 +57,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 +71,7 @@ func TestNewConditionalExecutor(t *testing.T) {
|
||||
return nil
|
||||
})(ctx)
|
||||
|
||||
assert.Nil(err)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(1, trueCount)
|
||||
assert.Equal(1, falseCount)
|
||||
}
|
||||
@@ -79,38 +81,41 @@ func TestNewParallelExecutor(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
count := 0
|
||||
activeCount := 0
|
||||
maxCount := 0
|
||||
var count atomic.Int32
|
||||
var activeCount atomic.Int32
|
||||
var maxCount atomic.Int32
|
||||
emptyWorkflow := NewPipelineExecutor(func(_ context.Context) error {
|
||||
count++
|
||||
count.Add(1)
|
||||
|
||||
activeCount++
|
||||
if activeCount > maxCount {
|
||||
maxCount = activeCount
|
||||
cur := activeCount.Add(1)
|
||||
for {
|
||||
old := maxCount.Load()
|
||||
if cur <= old || maxCount.CompareAndSwap(old, cur) {
|
||||
break
|
||||
}
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
activeCount--
|
||||
activeCount.Add(-1)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
err := NewParallelExecutor(2, emptyWorkflow, emptyWorkflow, emptyWorkflow)(ctx)
|
||||
|
||||
assert.Equal(3, count, "should run all 3 executors")
|
||||
assert.Equal(2, maxCount, "should run at most 2 executors in parallel")
|
||||
assert.Nil(err)
|
||||
assert.Equal(int32(3), count.Load(), "should run all 3 executors")
|
||||
assert.Equal(int32(2), maxCount.Load(), "should run at most 2 executors in parallel")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Reset to test running the executor with 0 parallelism
|
||||
count = 0
|
||||
activeCount = 0
|
||||
maxCount = 0
|
||||
count.Store(0)
|
||||
activeCount.Store(0)
|
||||
maxCount.Store(0)
|
||||
|
||||
errSingle := NewParallelExecutor(0, emptyWorkflow, emptyWorkflow, emptyWorkflow)(ctx)
|
||||
|
||||
assert.Equal(3, count, "should run all 3 executors")
|
||||
assert.Equal(1, maxCount, "should run at most 1 executors in parallel")
|
||||
assert.Nil(errSingle)
|
||||
assert.Equal(int32(3), count.Load(), "should run all 3 executors")
|
||||
assert.Equal(int32(1), maxCount.Load(), "should run at most 1 executors in parallel")
|
||||
require.NoError(t, errSingle)
|
||||
}
|
||||
|
||||
func TestNewParallelExecutorFailed(t *testing.T) {
|
||||
@@ -122,11 +127,11 @@ 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)
|
||||
assert.ErrorIs(context.Canceled, err)
|
||||
assert.ErrorIs(err, context.Canceled)
|
||||
}
|
||||
|
||||
func TestNewParallelExecutorCanceled(t *testing.T) {
|
||||
@@ -135,18 +140,16 @@ func TestNewParallelExecutorCanceled(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
|
||||
errExpected := fmt.Errorf("fake error")
|
||||
|
||||
count := 0
|
||||
var count atomic.Int32
|
||||
successWorkflow := NewPipelineExecutor(func(_ context.Context) error {
|
||||
count++
|
||||
count.Add(1)
|
||||
return nil
|
||||
})
|
||||
errorWorkflow := NewPipelineExecutor(func(_ context.Context) error {
|
||||
count++
|
||||
return errExpected
|
||||
count.Add(1)
|
||||
return errors.New("fake error")
|
||||
})
|
||||
err := NewParallelExecutor(3, errorWorkflow, successWorkflow, successWorkflow)(ctx)
|
||||
assert.Equal(3, count)
|
||||
assert.Error(errExpected, err)
|
||||
assert.Equal(int32(3), count.Load())
|
||||
assert.ErrorIs(err, context.Canceled)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// CopyFile copy file
|
||||
@@ -59,13 +60,13 @@ func CopyDir(source string, dest string) (err error) {
|
||||
// create sub-directories - recursively
|
||||
err = CopyDir(sourcefilepointer, destinationfilepointer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
log.Error(err)
|
||||
}
|
||||
} else {
|
||||
// perform copy
|
||||
err = CopyFile(sourcefilepointer, destinationfilepointer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
@@ -62,7 +62,6 @@ func FindGitRevision(ctx context.Context, file string) (shortSha string, sha str
|
||||
EnableDotGitCommonDir: true,
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("path", file, "not located inside a git repository")
|
||||
return "", "", err
|
||||
@@ -74,7 +73,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()
|
||||
@@ -96,8 +95,8 @@ func FindGitRef(ctx context.Context, file string) (string, error) {
|
||||
logger.Debugf("HEAD points to '%s'", ref)
|
||||
|
||||
// Prefer the git library to iterate over the references and find a matching tag or branch.
|
||||
var refTag = ""
|
||||
var refBranch = ""
|
||||
refTag := ""
|
||||
refBranch := ""
|
||||
repo, err := git.PlainOpenWithOptions(
|
||||
file,
|
||||
&git.PlainOpenOptions{
|
||||
@@ -105,7 +104,6 @@ func FindGitRef(ctx context.Context, file string) (string, error) {
|
||||
EnableDotGitCommonDir: true,
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -144,7 +142,6 @@ func FindGitRef(ctx context.Context, file string) (string, error) {
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -170,8 +167,8 @@ func FindGithubRepo(ctx context.Context, file, githubInstance, remoteName string
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, slug, err := findGitSlug(url, githubInstance)
|
||||
return slug, err
|
||||
_, slug := findGitSlug(url, githubInstance)
|
||||
return slug, nil
|
||||
}
|
||||
|
||||
func findGitRemoteURL(_ context.Context, file, remoteName string) (string, error) {
|
||||
@@ -213,23 +210,23 @@ func matchesRegex(url string, matchers ...findStringSubmatcher) []string {
|
||||
}
|
||||
|
||||
// TODO deprecate and remove githubInstance parameter
|
||||
func findGitSlug(url string, _ /* githubInstance */ string) (string, string, error) {
|
||||
func findGitSlug(url string, _ /* githubInstance */ string) (string, string) {
|
||||
if matches := matchesRegex(url, codeCommitHTTPRegex, codeCommitSSHRegex); matches != nil {
|
||||
return "CodeCommit", matches[2], nil
|
||||
return "CodeCommit", matches[2]
|
||||
}
|
||||
|
||||
if matches := matchesRegex(url, githubHTTPRegex, githubSSHRegex); matches != nil {
|
||||
return "GitHub", fmt.Sprintf("%s/%s", matches[1], matches[2]), nil
|
||||
return "GitHub", fmt.Sprintf("%s/%s", matches[1], matches[2])
|
||||
}
|
||||
|
||||
if matches := matchesRegex(url,
|
||||
regexp.MustCompile(`^https?://(?:[^/]+)/([^/]+)/([^/]+)(?:.git)?$`),
|
||||
regexp.MustCompile(`([^/]+)[:/]([^/]+)/([^/]+)(?:.git)?$`),
|
||||
); matches != nil {
|
||||
return "GitHubEnterprise", fmt.Sprintf("%s/%s", matches[1], matches[2]), nil
|
||||
return "GitHubEnterprise", fmt.Sprintf("%s/%s", matches[1], matches[2])
|
||||
}
|
||||
|
||||
return "", url, nil
|
||||
return "", url
|
||||
}
|
||||
|
||||
// NewGitCloneExecutorInput the input for the NewGitCloneExecutor
|
||||
@@ -319,7 +316,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
|
||||
|
||||
@@ -13,13 +13,13 @@ 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) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var slugTests = []struct {
|
||||
slugTests := []struct {
|
||||
url string // input
|
||||
provider string // expected result
|
||||
slug string // expected result
|
||||
@@ -38,19 +38,15 @@ func TestFindGitSlug(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tt := range slugTests {
|
||||
provider, slug, err := findGitSlug(tt.url, "github.com")
|
||||
provider, slug := findGitSlug(tt.url, "github.com")
|
||||
|
||||
assert.NoError(err)
|
||||
assert.Equal(tt.provider, provider)
|
||||
assert.Equal(tt.slug, slug)
|
||||
}
|
||||
}
|
||||
|
||||
func testDir(t *testing.T) string {
|
||||
basedir, err := os.MkdirTemp("", "act-test")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { _ = os.RemoveAll(basedir) })
|
||||
return basedir
|
||||
return t.TempDir()
|
||||
}
|
||||
|
||||
func cleanGitHooks(dir string) error {
|
||||
@@ -80,23 +76,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 +209,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 +254,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)
|
||||
})
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -66,6 +66,7 @@ func NewDockerBuildExecutor(input NewDockerBuildExecutorInput) common.Executor {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func createBuildContext(ctx context.Context, contextDir string, relDockerfile string) (io.ReadCloser, error) {
|
||||
common.Logger(ctx).Debugf("Creating archive for build context dir '%s' with relative dockerfile '%s'", contextDir, relDockerfile)
|
||||
|
||||
@@ -93,7 +94,7 @@ func createBuildContext(ctx context.Context, contextDir string, relDockerfile st
|
||||
// removed. The daemon will remove them for us, if needed, after it
|
||||
// parses the Dockerfile. Ignore errors here, as they will have been
|
||||
// caught by validateContextDirectory above.
|
||||
var includes = []string{"."}
|
||||
includes := []string{"."}
|
||||
keepThem1, _ := patternmatcher.Matches(".dockerignore", excludes)
|
||||
keepThem2, _ := patternmatcher.Matches(relDockerfile, excludes)
|
||||
if keepThem1 || keepThem2 {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// See DOCKER_LICENSE for the full license text.
|
||||
//
|
||||
|
||||
//nolint:unparam,errcheck,depguard,deadcode,unused
|
||||
//nolint:errcheck,depguard,unused
|
||||
package container
|
||||
|
||||
import (
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -37,9 +38,7 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var (
|
||||
deviceCgroupRuleRegexp = regexp.MustCompile(`^[acb] ([0-9]+|\*):([0-9]+|\*) [rwm]{1,3}$`)
|
||||
)
|
||||
var deviceCgroupRuleRegexp = regexp.MustCompile(`^[acb] ([0-9]+|\*):([0-9]+|\*) [rwm]{1,3}$`)
|
||||
|
||||
// containerOptions is a data object with all the options for creating a container
|
||||
type containerOptions struct {
|
||||
@@ -559,7 +558,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 +835,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)
|
||||
@@ -987,7 +986,7 @@ func validateDeviceCgroupRule(val string) (string, error) {
|
||||
// validDeviceMode checks if the mode for device is valid or not.
|
||||
// Valid mode is a composition of r (read), w (write), and m (mknod).
|
||||
func validDeviceMode(mode string) bool {
|
||||
var legalDeviceMode = map[rune]bool{
|
||||
legalDeviceMode := map[rune]bool{
|
||||
'r': true,
|
||||
'w': true,
|
||||
'm': true,
|
||||
@@ -1066,10 +1065,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")
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// See DOCKER_LICENSE for the full license text.
|
||||
//
|
||||
|
||||
//nolint:unparam,whitespace,depguard,dupl,gocritic
|
||||
//nolint:whitespace,depguard,dupl,gocritic
|
||||
package container
|
||||
|
||||
import (
|
||||
@@ -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,14 +186,13 @@ 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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func TestParseWithVolumes(t *testing.T) {
|
||||
|
||||
// A single volume
|
||||
arr, tryit := setupPlatformVolume([]string{`/tmp`}, []string{`c:\tmp`})
|
||||
if config, hostConfig, _ := mustParse(t, tryit); hostConfig.Binds != nil {
|
||||
@@ -260,7 +260,6 @@ func TestParseWithVolumes(t *testing.T) {
|
||||
t.Fatalf("Error parsing %s. Should have a single bind mount and no volumes", arr[0])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// setupPlatformVolume takes two arrays of volume specs - a Unix style
|
||||
@@ -301,7 +300,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 +338,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)
|
||||
}
|
||||
}
|
||||
@@ -461,7 +460,6 @@ func TestParseDevice(t *testing.T) {
|
||||
t.Fatalf("Expected %v, got %v", deviceMapping, hostconfig.Devices)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestParseNetworkConfig(t *testing.T) {
|
||||
@@ -606,7 +604,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 +675,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)
|
||||
}
|
||||
}
|
||||
@@ -966,7 +964,6 @@ func TestConvertToStandardNotation(t *testing.T) {
|
||||
|
||||
for key, ports := range valid {
|
||||
convertedPorts, err := convertToStandardNotation(ports)
|
||||
|
||||
if err != nil {
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -16,12 +16,17 @@ 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) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
client, err := GetDockerClient(ctx)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
defer client.Close()
|
||||
|
||||
dockerBuild := NewDockerBuildExecutor(NewDockerBuildExecutorInput{
|
||||
@@ -30,7 +35,7 @@ func TestDocker(t *testing.T) {
|
||||
})
|
||||
|
||||
err = dockerBuild(ctx)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
cr := &containerReference{
|
||||
cli: client,
|
||||
@@ -47,7 +52,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 +158,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 +188,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 +221,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 +235,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 +246,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 +260,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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
assert "github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -19,30 +20,34 @@ 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)
|
||||
}
|
||||
|
||||
func TestGetSocketAndHostOnlySocket(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
// Arrange
|
||||
socketURI := "/path/to/my.socket"
|
||||
os.Unsetenv("DOCKER_HOST")
|
||||
@@ -53,8 +58,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,17 +68,21 @@ 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)
|
||||
}
|
||||
|
||||
func TestGetSocketAndHostNoHostNoSocket(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
// Arrange
|
||||
CommonSocketLocations = originalCommonSocketLocations
|
||||
os.Unsetenv("DOCKER_HOST")
|
||||
@@ -83,8 +92,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")
|
||||
}
|
||||
|
||||
@@ -92,12 +101,16 @@ func TestGetSocketAndHostNoHostNoSocket(t *testing.T) {
|
||||
// > Your code breaks setting DOCKER_HOST if shouldMount is false.
|
||||
// > This happens if neither DOCKER_HOST nor --container-daemon-socket has a value, but socketLocation() returns a URI
|
||||
func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
// 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,12 +121,16 @@ 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")
|
||||
}
|
||||
|
||||
func TestGetSocketAndHostNoHostInvalidSocket(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
// Arrange
|
||||
os.Unsetenv("DOCKER_HOST")
|
||||
mySocket := "/my/socket/path.sock"
|
||||
@@ -124,10 +141,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 +159,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")
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -10,15 +10,14 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Type assert HostEnvironment implements ExecutionsEnvironment
|
||||
var _ ExecutionsEnvironment = &HostEnvironment{}
|
||||
|
||||
func TestCopyDir(t *testing.T) {
|
||||
dir, err := os.MkdirTemp("", "test-host-env-*")
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
dir := t.TempDir()
|
||||
ctx := context.Background()
|
||||
e := &HostEnvironment{
|
||||
Path: filepath.Join(dir, "path"),
|
||||
@@ -28,17 +27,16 @@ func TestCopyDir(t *testing.T) {
|
||||
StdOut: os.Stdout,
|
||||
Workdir: path.Join("testdata", "scratch"),
|
||||
}
|
||||
_ = os.MkdirAll(e.Path, 0700)
|
||||
_ = os.MkdirAll(e.TmpDir, 0700)
|
||||
_ = os.MkdirAll(e.ToolCache, 0700)
|
||||
_ = os.MkdirAll(e.ActPath, 0700)
|
||||
err = e.CopyDir(e.Workdir, e.Path, true)(ctx)
|
||||
assert.NoError(t, err)
|
||||
_ = os.MkdirAll(e.Path, 0o700)
|
||||
_ = os.MkdirAll(e.TmpDir, 0o700)
|
||||
_ = os.MkdirAll(e.ToolCache, 0o700)
|
||||
_ = os.MkdirAll(e.ActPath, 0o700)
|
||||
err := e.CopyDir(e.Workdir, e.Path, true)(ctx)
|
||||
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{
|
||||
@@ -49,22 +47,22 @@ func TestGetContainerArchive(t *testing.T) {
|
||||
StdOut: os.Stdout,
|
||||
Workdir: path.Join("testdata", "scratch"),
|
||||
}
|
||||
_ = os.MkdirAll(e.Path, 0700)
|
||||
_ = os.MkdirAll(e.TmpDir, 0700)
|
||||
_ = os.MkdirAll(e.ToolCache, 0700)
|
||||
_ = os.MkdirAll(e.ActPath, 0700)
|
||||
_ = os.MkdirAll(e.Path, 0o700)
|
||||
_ = os.MkdirAll(e.TmpDir, 0o700)
|
||||
_ = os.MkdirAll(e.ToolCache, 0o700)
|
||||
_ = os.MkdirAll(e.ActPath, 0o700)
|
||||
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, 0o600)
|
||||
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)
|
||||
|
||||
@@ -10,8 +10,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type LinuxContainerEnvironmentExtensions struct {
|
||||
}
|
||||
type LinuxContainerEnvironmentExtensions struct{}
|
||||
|
||||
// Resolves the equivalent host path inside the container
|
||||
// This is required for windows and WSL 2 to translate things like C:\Users\Myproject to /mnt/users/Myproject
|
||||
@@ -63,8 +62,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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -3,6 +3,7 @@ package filecollector
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
@@ -97,8 +98,7 @@ type Fs interface {
|
||||
Readlink(path string) (string, error)
|
||||
}
|
||||
|
||||
type DefaultFs struct {
|
||||
}
|
||||
type DefaultFs struct{}
|
||||
|
||||
func (*DefaultFs) Walk(root string, fn filepath.WalkFunc) error {
|
||||
return filepath.Walk(root, fn)
|
||||
@@ -134,7 +134,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:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package lookpath
|
||||
|
||||
import "os"
|
||||
@@ -6,8 +9,7 @@ type Env interface {
|
||||
Getenv(name string) string
|
||||
}
|
||||
|
||||
type defaultEnv struct {
|
||||
}
|
||||
type defaultEnv struct{}
|
||||
|
||||
func (*defaultEnv) Getenv(name string) string {
|
||||
return os.Getenv(name)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package lookpath
|
||||
|
||||
type Error struct {
|
||||
|
||||
@@ -20,7 +20,7 @@ func findExecutable(file string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
|
||||
if m := d.Mode(); !m.IsDir() && m&0o111 != 0 {
|
||||
return nil
|
||||
}
|
||||
return fs.ErrPermission
|
||||
|
||||
@@ -22,7 +22,7 @@ func findExecutable(file string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
|
||||
if m := d.Mode(); !m.IsDir() && m&0o111 != 0 {
|
||||
return nil
|
||||
}
|
||||
return fs.ErrPermission
|
||||
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user