Compare commits

...

10 Commits

Author SHA1 Message Date
ed08d1dcb4 chore: update configuration files and improve linting for Windows
Some checks failed
Codespell / Check for spelling errors (push) Has been cancelled
promote / promote (push) Has been cancelled
- Added `go1.24.0.linux-amd64.tar.gz` to `.gitignore`.
- Removed unnecessary newline in `.mergify.yml`.
- Updated `codecov.yml` to correct indentation for ignored files.
- Enhanced `Makefile` to support linting on Windows.
- Adjusted `.github/dependabot.yml` for proper indentation.
- Fixed string quotes in `.github/workflows/checks.yml`.
- Modified `pkg/container/util_windows.go` to ignore unused parameter.
- Updated error handling in `pkg/lookpath/lp_windows.go`.
- Refactored `pkg/runner/step_action_remote.go` to improve URL handling.
- Updated `pkg/runner/hashfiles/index.js` with significant changes for better performance and structure.
2025-08-03 04:28:08 +07:00
github-actions[bot]
bf8e52ba71 chore: bump VERSION to 0.2.80 2025-08-01 02:53:02 +00:00
ChristopherHX
61396d8085 fix: use ubuntu-latest bookworm instead of buster for tests (#5884)
* buster is now end of life
* apt-get update fails for some tests using ubuntu-latest
* buster cdn moved to archived domain
2025-07-25 20:33:59 +00:00
dependabot[bot]
5319acf6e2 build(deps): bump the dependencies group with 5 updates (#5861)
Bumps the dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/docker/cli](https://github.com/docker/cli) | `28.2.2+incompatible` | `28.3.0+incompatible` |
| [github.com/docker/docker](https://github.com/docker/docker) | `28.2.2+incompatible` | `28.3.0+incompatible` |
| [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) | `5.16.0` | `5.16.2` |
| [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) | `1.4.0` | `1.4.2` |
| [golang.org/x/term](https://github.com/golang/term) | `0.31.0` | `0.32.0` |


Updates `github.com/docker/cli` from 28.2.2+incompatible to 28.3.0+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.2.2...v28.3.0)

Updates `github.com/docker/docker` from 28.2.2+incompatible to 28.3.0+incompatible
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.2.2...v28.3.0)

Updates `github.com/go-git/go-git/v5` from 5.16.0 to 5.16.2
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.16.0...v5.16.2)

Updates `go.etcd.io/bbolt` from 1.4.0 to 1.4.2
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.2)

Updates `golang.org/x/term` from 0.31.0 to 0.32.0
- [Commits](https://github.com/golang/term/compare/v0.31.0...v0.32.0)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.0+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: github.com/docker/docker
  dependency-version: 28.3.0+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: github.com/go-git/go-git/v5
  dependency-version: 5.16.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: golang.org/x/term
  dependency-version: 0.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2025-07-01 06:25:55 +00:00
github-actions[bot]
7e22245859 chore: bump VERSION to 0.2.79 2025-07-01 02:46:18 +00:00
dependabot[bot]
dd58f5e20f build(deps): bump github.com/go-viper/mapstructure/v2 (#5837)
Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/go-viper/mapstructure/releases)
- [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: github.com/go-viper/mapstructure/v2
  dependency-version: 2.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-27 17:16:33 +00:00
Ryan Fleet
0bc47aea68 added info log when container image platform mismatched (#3225)
* added info log when container image platform mismatched

* inline image architecture comparison into ImageExistsLocally function as per review request
2025-06-19 21:37:15 +00:00
ChristopherHX
7c7b383c10 fix: post step failure is job failure (#5297)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2025-06-13 16:53:18 +00:00
ChristopherHX
515dd6612c feat: allow workflow description (#5326)
Otherwise act would reject such workflows right away
2025-06-13 16:33:10 +00:00
ChristopherHX
4ba1c2bde6 feat: --validate and --strict (#2717)
* feat: `--validate` and `--strict`

* fix missing changes

* add test for strict validate

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2025-06-11 22:02:16 +00:00
29 changed files with 5818 additions and 4799 deletions

View File

@@ -49,7 +49,7 @@ jobs:
- name: Test Summary
uses: test-summary/action@v2
with:
paths: "unit-tests.xml"
paths: 'unit-tests.xml'
if: always()
- 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
@@ -83,10 +83,9 @@ jobs:
- name: Test Summary
uses: test-summary/action@v2
with:
paths: "unit-tests.xml"
paths: 'unit-tests.xml'
if: always()
snapshot:
name: snapshot
runs-on: ubuntu-latest

1
.gitignore vendored
View File

@@ -32,3 +32,4 @@ unit-tests.xml
# megalinter
report/
go1.24.0.linux-amd64.tar.gz

View File

@@ -1,4 +1,3 @@
pull_request_rules:
- name: warn on conflicts
conditions:

View File

@@ -53,11 +53,19 @@ lint-md:
.PHONY: lint-rest
lint-rest:
ifeq ($(OS),Windows_NT)
docker run --rm -it \
-v "$(shell cd):/tmp/lint" \
-e GITHUB_STATUS_REPORTER=false \
-e GITHUB_COMMENT_REPORTER=false \
megalinter/megalinter-go:v5
else
docker run --rm -it \
-v $(PWD):/tmp/lint \
-e GITHUB_STATUS_REPORTER=false \
-e GITHUB_COMMENT_REPORTER=false \
megalinter/megalinter-go:v5
endif
.PHONY: lint
lint: lint-go lint-rest

View File

@@ -1 +1 @@
0.2.78
0.2.80

View File

@@ -62,6 +62,8 @@ type Input struct {
useNewActionCache bool
localRepository []string
listOptions bool
validate bool
strict bool
concurrentJobs int
}

View File

@@ -66,6 +66,8 @@ func createRootCommand(ctx context.Context, input *Input, version string) *cobra
}
rootCmd.Flags().BoolP("watch", "w", false, "watch the contents of the local repo and run when files change")
rootCmd.Flags().BoolVar(&input.validate, "validate", false, "validate workflows")
rootCmd.Flags().BoolVar(&input.strict, "strict", false, "use strict workflow schema")
rootCmd.Flags().BoolP("list", "l", false, "list workflows")
rootCmd.Flags().BoolP("graph", "g", false, "draw workflows")
rootCmd.Flags().StringP("job", "j", "", "run a specific job ID")
@@ -446,7 +448,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
matrixes := parseMatrix(input.matrix)
log.Debugf("Evaluated matrix inclusions: %v", matrixes)
planner, err := model.NewWorkflowPlanner(input.WorkflowsPath(), input.noWorkflowRecurse)
planner, err := model.NewWorkflowPlanner(input.WorkflowsPath(), input.noWorkflowRecurse, input.strict)
if err != nil {
return err
}
@@ -462,6 +464,11 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
return err
}
// check if we should just validate the workflows
if input.validate {
return err
}
// check if we should just draw the graph
graph, err := cmd.Flags().GetBool("graph")
if err != nil {

View File

@@ -9,5 +9,5 @@ coverage:
target: 50%
informational: true
ignore:
# Files generated by Google Protobuf do not require coverage
- '**/*.pb.go'
# Files generated by Google Protobuf do not require coverage
- '**/*.pb.go'

18
go.mod
View File

@@ -8,11 +8,11 @@ require (
github.com/adrg/xdg v0.5.3
github.com/andreaskoch/go-fswatch v1.0.0
github.com/creack/pty v1.1.24
github.com/docker/cli v28.2.2+incompatible
github.com/docker/docker v28.2.2+incompatible
github.com/docker/cli v28.3.0+incompatible
github.com/docker/docker v28.3.0+incompatible
github.com/docker/go-connections v0.5.0
github.com/go-git/go-billy/v5 v5.6.2
github.com/go-git/go-git/v5 v5.16.0
github.com/go-git/go-git/v5 v5.16.2
github.com/joho/godotenv v1.5.1
github.com/julienschmidt/httprouter v1.3.0
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
@@ -28,16 +28,18 @@ require (
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
github.com/timshannon/bolthold v0.0.0-20240314194003-30aac6950928
go.etcd.io/bbolt v1.4.0
golang.org/x/term v0.31.0
go.etcd.io/bbolt v1.4.2
golang.org/x/term v0.32.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools/v3 v3.5.2
)
require (
dario.cat/mergo v1.0.2
github.com/containerd/errdefs v1.0.0
github.com/distribution/reference v0.6.0
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/moby/go-archive v0.1.0
google.golang.org/protobuf v1.36.6
)
@@ -46,7 +48,6 @@ require (
github.com/ProtonMail/go-crypto v1.1.6 // indirect
github.com/bmatcuk/doublestar/v4 v4.8.0 // indirect
github.com/cloudflare/circl v1.6.1 // 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/cpuguy83/go-md2man/v2 v2.0.6 // indirect
@@ -60,7 +61,7 @@ require (
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/go-cmp v0.7.0 // indirect
@@ -74,7 +75,6 @@ require (
github.com/mattn/go-shellwords v1.0.12 // 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/sys/atomicwriter v0.1.0 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
@@ -105,7 +105,7 @@ require (
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.6.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect

28
go.sum
View File

@@ -47,10 +47,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v28.2.2+incompatible h1:qzx5BNUDFqlvyq4AHzdNB7gSyVTmU4cgsyN9SdInc1A=
github.com/docker/cli v28.2.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v28.2.2+incompatible h1:CjwRSksz8Yo4+RmQ339Dp/D2tGO5JxwYeqtMOEe0LDw=
github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/cli v28.3.0+incompatible h1:s+ttruVLhB5ayeuf2BciwDVxYdKi+RoUlxmwNHV3Vfo=
github.com/docker/cli v28.3.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v28.3.0+incompatible h1:ffS62aKWupCWdvcee7nBU9fhnmknOqDPaJAMtfK0ImQ=
github.com/docker/docker v28.3.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
@@ -73,15 +73,15 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.16.0 h1:k3kuOEpkc0DeY7xlL6NaaNg39xdgQbtH5mwCafHO9AQ=
github.com/go-git/go-git/v5 v5.16.0/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
@@ -220,8 +220,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/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.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
@@ -283,12 +283,12 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
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.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
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.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
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=

View File

@@ -298,7 +298,7 @@ func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
runner, err := runner.New(runnerConfig)
assert.Nil(t, err, tjfi.workflowPath)
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, true)
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, true, false)
assert.Nil(t, err, fullWorkflowPath)
plan, err := planner.PlanEvent(tjfi.eventName)

View File

@@ -8,6 +8,7 @@ import (
cerrdefs "github.com/containerd/errdefs"
"github.com/docker/docker/api/types/image"
"github.com/nektos/act/pkg/common"
)
// ImageExistsLocally returns a boolean indicating if an image with the
@@ -26,10 +27,15 @@ func ImageExistsLocally(ctx context.Context, imageName string, platform string)
return false, err
}
if platform == "" || platform == "any" || fmt.Sprintf("%s/%s", inspectImage.Os, inspectImage.Architecture) == platform {
imagePlatform := fmt.Sprintf("%s/%s", inspectImage.Os, inspectImage.Architecture)
if platform == "" || platform == "any" || imagePlatform == platform {
return true, nil
}
logger := common.Logger(ctx)
logger.Infof("image found but platform does not match: %s (image) != %s (platform)\n", imagePlatform, platform)
return false, nil
}

View File

@@ -6,7 +6,7 @@ import (
"syscall"
)
func getSysProcAttr(cmdLine string, tty bool) *syscall.SysProcAttr {
func getSysProcAttr(cmdLine string, _ bool) *syscall.SysProcAttr {
return &syscall.SysProcAttr{CmdLine: cmdLine, CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP}
}

View File

@@ -77,9 +77,8 @@ func LookPath2(file string, lenv Env) (string, error) {
if strings.ContainsAny(file, `:\/`) {
if f, err := findExecutable(file, exts); err == nil {
return f, nil
} else {
return "", &Error{file, err}
}
return "", &Error{file, ErrNotFound}
}
if f, err := findExecutable(filepath.Join(".", file), exts); err == nil {
return f, nil

View File

@@ -56,7 +56,7 @@ type WorkflowFiles struct {
}
// NewWorkflowPlanner will load a specific workflow, all workflows from a directory or all workflows from a directory and its subdirectories
func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, error) {
func NewWorkflowPlanner(path string, noWorkflowRecurse, strict bool) (WorkflowPlanner, error) {
path, err := filepath.Abs(path)
if err != nil {
return nil, err
@@ -124,7 +124,7 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, e
}
log.Debugf("Reading workflow '%s'", f.Name())
workflow, err := ReadWorkflow(f)
workflow, err := ReadWorkflow(f, strict)
if err != nil {
_ = f.Close()
if err == io.EOF {
@@ -161,7 +161,7 @@ func NewSingleWorkflowPlanner(name string, f io.Reader) (WorkflowPlanner, error)
wp := new(workflowPlanner)
log.Debugf("Reading workflow %s", name)
workflow, err := ReadWorkflow(f)
workflow, err := ReadWorkflow(f, false)
if err != nil {
if err == io.EOF {
return nil, fmt.Errorf("unable to read workflow '%s': file is empty: %w", name, err)

View File

@@ -31,7 +31,7 @@ func TestPlanner(t *testing.T) {
assert.NoError(t, err, workdir)
for _, table := range tables {
fullWorkflowPath := filepath.Join(workdir, table.workflowPath)
_, err = NewWorkflowPlanner(fullWorkflowPath, table.noWorkflowRecurse)
_, err = NewWorkflowPlanner(fullWorkflowPath, table.noWorkflowRecurse, false)
if table.errorMessage == "" {
assert.NoError(t, err, "WorkflowPlanner should exit without any error")
} else {

View File

@@ -80,6 +80,20 @@ func (w *Workflow) UnmarshalYAML(node *yaml.Node) error {
return node.Decode((*WorkflowDefault)(w))
}
type WorkflowStrict Workflow
func (w *WorkflowStrict) UnmarshalYAML(node *yaml.Node) error {
// Validate the schema before deserializing it into our model
if err := (&schema.Node{
Definition: "workflow-root-strict",
Schema: schema.GetWorkflowSchema(),
}).UnmarshalYAML(node); err != nil {
return errors.Join(err, fmt.Errorf("Actions YAML Strict Schema Validation Error detected:\nFor more information, see: https://nektosact.com/usage/schema.html"))
}
type WorkflowDefault Workflow
return node.Decode((*WorkflowDefault)(w))
}
type WorkflowDispatchInput struct {
Description string `yaml:"description"`
Required bool `yaml:"required"`
@@ -711,7 +725,12 @@ func (s *Step) Type() StepType {
}
// ReadWorkflow returns a list of jobs for a given workflow file reader
func ReadWorkflow(in io.Reader) (*Workflow, error) {
func ReadWorkflow(in io.Reader, strict bool) (*Workflow, error) {
if strict {
w := new(WorkflowStrict)
err := yaml.NewDecoder(in).Decode(w)
return (*Workflow)(w), err
}
w := new(Workflow)
err := yaml.NewDecoder(in).Decode(w)
return w, err

View File

@@ -19,7 +19,7 @@ jobs:
- uses: ./actions/docker-url
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.On(), 1)
@@ -38,7 +38,7 @@ jobs:
- uses: ./actions/docker-url
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.On(), 2)
@@ -64,7 +64,7 @@ jobs:
- uses: ./actions/docker-url
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.On(), 2)
assert.Contains(t, workflow.On(), "push")
@@ -83,7 +83,7 @@ jobs:
steps:
- uses: ./actions/docker-url`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest"})
}
@@ -101,7 +101,7 @@ jobs:
steps:
- uses: ./actions/docker-url`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest", "linux"})
}
@@ -126,7 +126,7 @@ jobs:
- uses: ./actions/docker-url
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.Jobs, 2)
assert.Contains(t, workflow.Jobs["test"].Container().Image, "nginx:latest")
@@ -156,7 +156,7 @@ jobs:
- uses: ./actions/docker-url
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.Jobs, 1)
@@ -194,7 +194,7 @@ jobs:
uses: ./some/path/to/workflow.yaml
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.Jobs, 6)
@@ -238,7 +238,7 @@ jobs:
uses: some/path/to/workflow.yaml
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.Jobs, 4)
@@ -280,7 +280,7 @@ jobs:
uses: ./local-action
`
_, err := ReadWorkflow(strings.NewReader(yaml))
_, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.Error(t, err, "read workflow should fail")
}
@@ -312,7 +312,7 @@ jobs:
echo "${{ needs.test1.outputs.some-b-key }}"
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.Jobs, 2)
@@ -327,7 +327,7 @@ jobs:
}
func TestReadWorkflow_Strategy(t *testing.T) {
w, err := NewWorkflowPlanner("testdata/strategy/push.yml", true)
w, err := NewWorkflowPlanner("testdata/strategy/push.yml", true, false)
assert.NoError(t, err)
p, err := w.PlanJob("strategy-only-max-parallel")
@@ -418,7 +418,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
yaml := `
name: local-action-docker-url
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
workflowDispatch := workflow.WorkflowDispatchConfig()
assert.Nil(t, workflowDispatch)
@@ -427,7 +427,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
name: local-action-docker-url
on: push
`
workflow, err = ReadWorkflow(strings.NewReader(yaml))
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
workflowDispatch = workflow.WorkflowDispatchConfig()
assert.Nil(t, workflowDispatch)
@@ -436,7 +436,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
name: local-action-docker-url
on: workflow_dispatch
`
workflow, err = ReadWorkflow(strings.NewReader(yaml))
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
workflowDispatch = workflow.WorkflowDispatchConfig()
assert.NotNil(t, workflowDispatch)
@@ -446,7 +446,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
name: local-action-docker-url
on: [push, pull_request]
`
workflow, err = ReadWorkflow(strings.NewReader(yaml))
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
workflowDispatch = workflow.WorkflowDispatchConfig()
assert.Nil(t, workflowDispatch)
@@ -455,7 +455,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
name: local-action-docker-url
on: [push, workflow_dispatch]
`
workflow, err = ReadWorkflow(strings.NewReader(yaml))
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
workflowDispatch = workflow.WorkflowDispatchConfig()
assert.NotNil(t, workflowDispatch)
@@ -467,7 +467,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
- push
- workflow_dispatch
`
workflow, err = ReadWorkflow(strings.NewReader(yaml))
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
workflowDispatch = workflow.WorkflowDispatchConfig()
assert.NotNil(t, workflowDispatch)
@@ -479,7 +479,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
push:
pull_request:
`
workflow, err = ReadWorkflow(strings.NewReader(yaml))
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
workflowDispatch = workflow.WorkflowDispatchConfig()
assert.Nil(t, workflowDispatch)
@@ -501,7 +501,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
- warning
- debug
`
workflow, err = ReadWorkflow(strings.NewReader(yaml))
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
assert.NoError(t, err, "read workflow should succeed")
workflowDispatch = workflow.WorkflowDispatchConfig()
assert.NotNil(t, workflowDispatch)
@@ -517,3 +517,19 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
Type: "choice",
}, workflowDispatch.Inputs["logLevel"])
}
func TestReadWorkflow_InvalidStringEvent(t *testing.T) {
yaml := `
name: local-action-docker-url
on: push2
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: ./actions/docker-url
`
_, err := ReadWorkflow(strings.NewReader(yaml), true)
assert.Error(t, err, "read workflow should succeed")
}

File diff suppressed because it is too large Load Diff

View File

@@ -92,7 +92,7 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo
return nil
}))
postExec := useStepLogger(rc, stepModel, stepStagePost, step.post())
postExec := useStepLogger(rc, stepModel, stepStagePost, step.post().ThenError(setJobError))
if postExecutor != nil {
// run the post executor in reverse order
postExecutor = postExec.Finally(postExecutor)

View File

@@ -115,7 +115,7 @@ func cloneIfRequired(rc *RunContext, remoteReusableWorkflow remoteReusableWorkfl
func newReusableWorkflowExecutor(rc *RunContext, directory string, workflow string) common.Executor {
return func(ctx context.Context) error {
planner, err := model.NewWorkflowPlanner(path.Join(directory, workflow), true)
planner, err := model.NewWorkflowPlanner(path.Join(directory, workflow), true, false)
if err != nil {
return err
}

View File

@@ -25,7 +25,7 @@ import (
)
var (
baseImage = "node:16-buster-slim"
baseImage = "node:24-bookworm-slim"
platforms map[string]string
logLevel = log.DebugLevel
workdir = "testdata"
@@ -55,7 +55,7 @@ func init() {
}
func TestNoWorkflowsFoundByPlanner(t *testing.T) {
planner, err := model.NewWorkflowPlanner("res", true)
planner, err := model.NewWorkflowPlanner("res", true, false)
assert.NoError(t, err)
out := log.StandardLogger().Out
@@ -75,7 +75,7 @@ func TestNoWorkflowsFoundByPlanner(t *testing.T) {
}
func TestGraphMissingEvent(t *testing.T) {
planner, err := model.NewWorkflowPlanner("testdata/issue-1595/no-event.yml", true)
planner, err := model.NewWorkflowPlanner("testdata/issue-1595/no-event.yml", true, false)
assert.NoError(t, err)
out := log.StandardLogger().Out
@@ -93,7 +93,7 @@ func TestGraphMissingEvent(t *testing.T) {
}
func TestGraphMissingFirst(t *testing.T) {
planner, err := model.NewWorkflowPlanner("testdata/issue-1595/no-first.yml", true)
planner, err := model.NewWorkflowPlanner("testdata/issue-1595/no-first.yml", true, false)
assert.NoError(t, err)
plan, err := planner.PlanEvent("push")
@@ -103,7 +103,7 @@ func TestGraphMissingFirst(t *testing.T) {
}
func TestGraphWithMissing(t *testing.T) {
planner, err := model.NewWorkflowPlanner("testdata/issue-1595/missing.yml", true)
planner, err := model.NewWorkflowPlanner("testdata/issue-1595/missing.yml", true, false)
assert.NoError(t, err)
out := log.StandardLogger().Out
@@ -122,7 +122,7 @@ func TestGraphWithMissing(t *testing.T) {
func TestGraphWithSomeMissing(t *testing.T) {
log.SetLevel(log.DebugLevel)
planner, err := model.NewWorkflowPlanner("testdata/issue-1595/", true)
planner, err := model.NewWorkflowPlanner("testdata/issue-1595/", true, false)
assert.NoError(t, err)
out := log.StandardLogger().Out
@@ -140,7 +140,7 @@ func TestGraphWithSomeMissing(t *testing.T) {
}
func TestGraphEvent(t *testing.T) {
planner, err := model.NewWorkflowPlanner("testdata/basic", true)
planner, err := model.NewWorkflowPlanner("testdata/basic", true, false)
assert.NoError(t, err)
plan, err := planner.PlanEvent("push")
@@ -198,7 +198,7 @@ func (j *TestJobFileInfo) runTest(ctx context.Context, t *testing.T, cfg *Config
runner, err := New(runnerConfig)
assert.Nil(t, err, j.workflowPath)
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, true)
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, true, false)
if j.errorMessage != "" && err != nil {
assert.Error(t, err, j.errorMessage)
} else if assert.Nil(t, err, fullWorkflowPath) {
@@ -376,13 +376,24 @@ func (factory *captureJobLoggerFactory) WithJobLogger() *logrus.Logger {
return logger
}
func TestPullFailureIsJobFailure(t *testing.T) {
func TestPullAndPostStepFailureIsJobFailure(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
tables := []TestJobFileInfo{
{workdir, "checkout", "push", "pull failure", map[string]string{"ubuntu-latest": "localhost:0000/missing:latest"}, secrets},
defCache := &GoGitActionCache{
path.Clean(path.Join(workdir, "cache")),
}
mockCache := &mockCache{}
tables := []struct {
TestJobFileInfo
ActionCache ActionCache
SetupResult string
}{
{TestJobFileInfo{workdir, "checkout", "push", "pull failure", map[string]string{"ubuntu-latest": "localhost:0000/missing:latest"}, secrets}, defCache, "failure"},
{TestJobFileInfo{workdir, "post-step-failure-is-job-failure", "push", "post failure", map[string]string{"ubuntu-latest": "-self-hosted"}, secrets}, mockCache, "success"},
}
for _, table := range tables {
@@ -397,9 +408,7 @@ func TestPullFailureIsJobFailure(t *testing.T) {
if _, err := os.Stat(eventFile); err == nil {
config.EventPath = eventFile
}
config.ActionCache = &GoGitActionCache{
path.Clean(path.Join(workdir, "cache")),
}
config.ActionCache = table.ActionCache
logger := logrus.New()
logger.SetOutput(&factory.buffer)
@@ -418,7 +427,7 @@ func TestPullFailureIsJobFailure(t *testing.T) {
hasJobResult = true
}
if val, ok := entry["stepResult"]; ok && !hasStepResult {
assert.Equal(t, "failure", val)
assert.Equal(t, table.SetupResult, val)
hasStepResult = true
}
}

View File

@@ -50,7 +50,6 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor {
}
github := sar.getGithubContext(ctx)
sar.remoteAction.URL = github.ServerURL
if sar.remoteAction.IsCheckout() && isLocalCheckout(github, sar.Step) && !sar.RunContext.Config.NoSkipCheckout {
common.Logger(ctx).Debugf("Skipping local actions/checkout because workdir was already copied")
@@ -111,7 +110,7 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor {
URL: sar.remoteAction.CloneURL(),
Ref: sar.remoteAction.Ref,
Dir: actionDir,
Token: github.Token,
Token: "",
OfflineMode: sar.RunContext.Config.ActionOfflineMode,
})
var ntErr common.Executor
@@ -270,6 +269,26 @@ func (ra *remoteAction) IsCheckout() bool {
}
func newRemoteAction(action string) *remoteAction {
// support http(s)://host/owner/repo@v3
for _, schema := range []string{"https://", "http://"} {
if strings.HasPrefix(action, schema) {
splits := strings.SplitN(strings.TrimPrefix(action, schema), "/", 2)
if len(splits) != 2 {
return nil
}
ret := parseAction(splits[1])
if ret == nil {
return nil
}
ret.URL = schema + splits[0]
return ret
}
}
return parseAction(action)
}
func parseAction(action string) *remoteAction {
// GitHub's document[^] describes:
// > We strongly recommend that you include the version of
// > the action you are using by specifying a Git ref, SHA, or Docker tag number.
@@ -285,7 +304,7 @@ func newRemoteAction(action string) *remoteAction {
Repo: matches[2],
Path: matches[4],
Ref: matches[6],
URL: "https://github.com",
URL: "",
}
}

View File

@@ -0,0 +1,4 @@
runs:
using: node20
main: main.js
post: post.js

View File

@@ -0,0 +1,2 @@
console.log('This is a post step failure test');
process.exit(1);

View File

@@ -0,0 +1,9 @@
name: basic
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./post-step-failure-is-job-failure/post-step-failure

View File

@@ -7,6 +7,7 @@
"properties": {
"on": "on",
"name": "workflow-name",
"description": "string",
"run-name": "run-name",
"defaults": "workflow-defaults",
"env": "workflow-env",
@@ -28,6 +29,7 @@
"required": true
},
"name": "workflow-name",
"description": "string",
"run-name": "run-name",
"defaults": "workflow-defaults",
"env": "workflow-env",