mirror of
https://gitea.com/gitea/runner.git
synced 2026-11-06 15:20:29 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
589db33e70 | ||
|
|
1032f857a1 | ||
|
|
e56b984c04 | ||
|
|
fa5334eb24 | ||
|
|
7c6f1261d4 | ||
|
|
fbd6316928 | ||
|
|
ade5b8202e | ||
|
|
a31f3962c0 | ||
|
|
04244fc3f7 | ||
|
|
cb58492678 | ||
|
|
9faadad0ce | ||
|
|
352096c5bf | ||
|
|
b5c50bb3ab | ||
|
|
8af9a2b47a | ||
|
|
fab2d6ae04 | ||
|
|
15dd63a839 | ||
|
|
9aafec169b | ||
|
|
f923badec7 | ||
|
|
48944e136c | ||
|
|
40dcee0991 | ||
|
|
f33e5a6245 | ||
|
|
f2d545565f | ||
|
|
90c1275f0e | ||
|
|
3232358e71 | ||
|
|
2e98baa34a | ||
|
|
505907eb2a | ||
|
|
9933ea0d92 | ||
|
|
5dd5436169 | ||
|
|
28740d7788 | ||
|
|
ddf9159a8f | ||
|
|
658101d9cb | ||
|
|
f0f9f0c8ab | ||
|
|
ae6e5dfcf7 | ||
|
|
f4418eff18 | ||
|
|
0f7efae806 | ||
|
|
aab249000c | ||
|
|
c82077e6b5 | ||
|
|
9f91fdd0eb | ||
|
|
7a7a5d9051 | ||
|
|
90d11b8692 | ||
|
|
c4b57fbcb2 | ||
|
|
e6dbe2a1ca | ||
|
|
774f316c8b | ||
|
|
823e9489d6 | ||
|
|
dc38bf1895 | ||
|
|
96b866a3a8 | ||
|
|
3b11bac2ad | ||
|
|
47caafd037 | ||
|
|
50e0509007 | ||
|
|
8920c4a170 | ||
|
|
bbf9d7e90f | ||
|
|
46f471a900 | ||
|
|
aa28f8d99c | ||
|
|
6a7e18b124 | ||
|
|
53329c46ff | ||
|
|
6b1aea9c04 | ||
|
|
edec9a8f91 | ||
|
|
6a9a447f86 | ||
|
|
5302c25feb | ||
|
|
a616ed1a10 | ||
|
|
f0b5aff3bb | ||
|
|
44b4736703 | ||
|
|
b1ae30dda8 | ||
|
|
0d687268c7 | ||
|
|
425a570261 | ||
|
|
4c8179ee12 | ||
|
|
5ae13f0bd7 | ||
|
|
3510152e36 | ||
|
|
8dfb805c62 | ||
|
|
a7080f5457 | ||
|
|
8b72d1c7ae | ||
|
|
8bc0275e74 | ||
|
|
0348aaac59 | ||
|
|
9712481bed | ||
|
|
b5f901b2d9 | ||
|
|
0e2a3e00f5 | ||
|
|
b282356e9e | ||
|
|
b075e3a1d5 | ||
|
|
e27189ea32 | ||
|
|
59e478464e | ||
|
|
e1c7b20898 | ||
|
|
2f78411c3d | ||
|
|
d1d3cad4b0 | ||
|
|
1735b26e66 | ||
|
|
65ed62d2f5 | ||
|
|
ec03f19650 | ||
|
|
8567324a19 | ||
|
|
be2df361ef | ||
|
|
a5085dde0c | ||
|
|
cef86d1140 | ||
|
|
94c45acf6b | ||
|
|
1760899d27 | ||
|
|
a7eca813ea | ||
|
|
23ec12b8cf | ||
|
|
a1fc2b3ca7 | ||
|
|
5977042b86 | ||
|
|
6bc19cbc33 | ||
|
|
75006a59cc | ||
|
|
4da97f53de | ||
|
|
45270656df | ||
|
|
e14f42c40a | ||
|
|
e6630e2e36 | ||
|
|
f1f9142a3c | ||
|
|
f17cad1bbe | ||
|
|
daf52d0e62 | ||
|
|
8c8a8ce401 | ||
|
|
08c681be0c | ||
|
|
91bfe4c186 | ||
|
|
825c6f97b7 | ||
|
|
2f3e5c7125 | ||
|
|
4d9de6ca8c | ||
|
|
feb39666cc | ||
|
|
61cd71c9f8 | ||
|
|
0adfc1c7cc | ||
|
|
e3c68668fa | ||
|
|
f1b27d5274 | ||
|
|
655a39fd61 | ||
|
|
cca7d54117 | ||
|
|
934471813a | ||
|
|
1e940f028b | ||
|
|
2020ce79bf | ||
|
|
00e9b3d62b | ||
|
|
130b9f1877 | ||
|
|
4c35288175 | ||
|
|
990db1bfc0 | ||
|
|
d07fbfc8c3 | ||
|
|
10dc6fb60d | ||
|
|
ed35b09b8f | ||
|
|
03f0829d09 | ||
|
|
7fc1b91ba6 | ||
|
|
82c3c2df1a | ||
|
|
9fc823e4b1 | ||
|
|
12999b61dd | ||
|
|
49a2fcc138 | ||
|
|
8f88e4f15a | ||
|
|
a1bb3b56fd | ||
|
|
1a7ec5f339 | ||
|
|
5d01cb8904 | ||
|
|
dcf84d8a53 | ||
|
|
73adae040d | ||
|
|
db662b3690 | ||
|
|
cf92a979e2 | ||
|
|
87058716fb | ||
|
|
c701ba4787 | ||
|
|
57ff1df6e0 | ||
|
|
3dcfd6ea3d | ||
|
|
c6006ee699 | ||
|
|
f2629f2ea3 | ||
|
|
cf48ed88ba | ||
|
|
ccc27329dc | ||
|
|
b0bd503b11 | ||
|
|
8c14933e70 | ||
|
|
34d15f21c2 | ||
|
|
32d29f0813 | ||
|
|
2e2c0400c8 | ||
|
|
054c8d912f | ||
|
|
9e4a5f7363 | ||
|
|
ec38401097 | ||
|
|
45bfe0a9b2 | ||
|
|
316534996a | ||
|
|
67b1363d25 | ||
|
|
946c41cf4f | ||
|
|
341d49a24d | ||
|
|
b21d476aca | ||
|
|
a29307a9d9 | ||
|
|
4bfbfec477 | ||
|
|
fed01c9807 | ||
|
|
a83f29d5a9 | ||
|
|
69c55ee003 | ||
|
|
01ef57c667 | ||
|
|
a384adbbc6 | ||
|
|
e3271d8469 | ||
|
|
84386c1b16 | ||
|
|
fd7c8580af | ||
|
|
35596a182b | ||
|
|
c9d3f67264 | ||
|
|
94031fc198 | ||
|
|
d5e4baed54 | ||
|
|
d4caa7e065 | ||
|
|
de4160b023 | ||
|
|
609c0a0773 | ||
|
|
0c029f7e79 | ||
|
|
eef3c32eb2 | ||
|
|
c40b651873 | ||
|
|
b498341857 | ||
|
|
0d727eb262 | ||
|
|
7c71c94366 | ||
|
|
49d2cb0cb5 | ||
|
|
85626b6bbd | ||
|
|
35400f76fa | ||
|
|
0cf31b2d22 | ||
|
|
c8cc7b2448 | ||
|
|
3be962cdb3 | ||
|
|
a5edbc9ac4 | ||
|
|
66bab3d805 | ||
|
|
293926f5d5 | ||
|
|
43c5ba923f | ||
|
|
acc5afc428 | ||
|
|
27a1a90d25 | ||
|
|
83ec0ba909 | ||
|
|
ed86e2f15a | ||
|
|
d4bebccc12 | ||
|
|
c75b67e892 | ||
|
|
bc6031eff7 | ||
|
|
c69c353d93 | ||
|
|
fcc016e9b3 | ||
|
|
d5caee38f2 | ||
|
|
9e26208e13 | ||
|
|
a05c5ba3ad | ||
|
|
c248520a66 | ||
|
|
10d639cc6b | ||
|
|
5a8134410d | ||
|
|
b79c3aa1a3 | ||
|
|
9c6499ec08 | ||
|
|
d139faa40c | ||
|
|
220efa69c0 | ||
|
|
df3cb60978 | ||
|
|
7e7096e60b | ||
|
|
8eea12dd78 | ||
|
|
c8fad20f49 | ||
|
|
1596e4b1fd | ||
|
|
c9e076db68 | ||
|
|
bc1842d649 | ||
|
|
90b8cc6a7a | ||
|
|
4d5a35ac65 | ||
|
|
8f81f40d62 | ||
|
|
9f90cba993 | ||
|
|
48b05a0ca8 | ||
|
|
9eb8b08a69 | ||
|
|
4d868b7f3c | ||
|
|
63a57edaa3 | ||
|
|
5180cd56e1 | ||
|
|
370989b2d0 | ||
|
|
71f470d670 | ||
|
|
c0c363bf59 | ||
|
|
0d71463662 | ||
|
|
ebcf341de7 | ||
|
|
14334f76ed | ||
|
|
f24e0721dc | ||
|
|
e36300ce28 | ||
|
|
09ddbe166f | ||
|
|
da0713e629 | ||
|
|
bbd055ac3b | ||
|
|
462b2660de | ||
|
|
ebdbfeb54a | ||
|
|
436b441cad | ||
|
|
552dbcdda9 | ||
|
|
a50b094c1a | ||
|
|
6cc53f16d8 | ||
|
|
8fcd56dc7b | ||
|
|
c9318f08e2 | ||
|
|
c7f8919470 | ||
|
|
14dfa5cc15 | ||
|
|
99a53a1f4c | ||
|
|
df2219eeb8 | ||
|
|
216f3d1740 | ||
|
|
8aa186897f | ||
|
|
3fa7707bc1 | ||
|
|
9038442191 | ||
|
|
c133be12d8 | ||
|
|
1072e3c383 | ||
|
|
a4513405b5 | ||
|
|
410765b516 | ||
|
|
06b9c3962e | ||
|
|
0b64655a40 | ||
|
|
75820a6a3e | ||
|
|
f1869f70b9 | ||
|
|
990cf93c71 | ||
|
|
f7a52789d9 | ||
|
|
cf27d3f300 | ||
|
|
7abe039c31 | ||
|
|
9ba9604256 | ||
|
|
6d2200b3d6 | ||
|
|
0cbdbd36b6 | ||
|
|
0f97dd873a | ||
|
|
8996b9b0e4 | ||
|
|
715d0e85ce | ||
|
|
1ab84ac8e8 | ||
|
|
1d50f0f5fd | ||
|
|
d1017d752f | ||
|
|
474683c0e8 | ||
|
|
03c4c4e116 | ||
|
|
b3e7d6a62d | ||
|
|
2354f5bb18 | ||
|
|
5781e233c1 | ||
|
|
f05e08a767 | ||
|
|
86f66eaa45 | ||
|
|
64c9856ba7 | ||
|
|
66ec50e427 | ||
|
|
44988db9f8 | ||
|
|
519726b46b | ||
|
|
3f676a742b | ||
|
|
e9e42e850b | ||
|
|
8f950ccec0 | ||
|
|
45de6199d1 | ||
|
|
ab4e06f977 | ||
|
|
cab56996b7 | ||
|
|
a13ed0c52e | ||
|
|
5fc35faf17 | ||
|
|
bfcc6f56f3 | ||
|
|
8f9d7506dc | ||
|
|
561bfad7c5 | ||
|
|
88ae188699 | ||
|
|
9830f34d36 | ||
|
|
8cffac65d9 | ||
|
|
2e1326b725 | ||
|
|
abdb547b1b | ||
|
|
d1114da299 | ||
|
|
cbd21b8ec5 | ||
|
|
d650bae0b6 | ||
|
|
222b5100b6 | ||
|
|
93e42d1465 | ||
|
|
93c8de3ec4 | ||
|
|
2442cdd8ad | ||
|
|
08c94bb564 | ||
|
|
d178051832 | ||
|
|
2f879c41c4 | ||
|
|
41b5fa6b55 | ||
|
|
378966e45f | ||
|
|
9c7d2be7c6 | ||
|
|
e08495af09 | ||
|
|
bf5e3dc302 | ||
|
|
a503f7429f | ||
|
|
cce60d466b | ||
|
|
7bebd2bbad | ||
|
|
d4c1515f4e | ||
|
|
45b0429b21 | ||
|
|
dada0730b0 | ||
|
|
c161a48a0a | ||
|
|
3a1503138b | ||
|
|
7486d2ab91 | ||
|
|
82431d8e11 | ||
|
|
20c3d85ba9 | ||
|
|
5051e4aebd | ||
|
|
d3d56ed0ef | ||
|
|
631f801aa6 | ||
|
|
6030610c04 | ||
|
|
9be39b8cd4 | ||
|
|
f2fb8798fa | ||
|
|
449388f3ab | ||
|
|
a3e9bbed25 | ||
|
|
3281c6637d | ||
|
|
c5edbbd004 | ||
|
|
aa765ea4d0 | ||
|
|
307c2c63de | ||
|
|
7d55fd57c9 | ||
|
|
bca586ffd0 | ||
|
|
d359276fe1 | ||
|
|
0b885c5e5f | ||
|
|
4d7ef95d40 | ||
|
|
14a345504f | ||
|
|
4eb5213294 | ||
|
|
9225a3a856 | ||
|
|
b83f36674b | ||
|
|
dfcb104af0 | ||
|
|
3b7ac17410 | ||
|
|
906d52ae0b | ||
|
|
aa9ed05903 | ||
|
|
5213612033 | ||
|
|
518aa1b2a7 | ||
|
|
827bd953e7 | ||
|
|
e54de37242 | ||
|
|
08282a519f | ||
|
|
db7ee2eaf4 | ||
|
|
c7cb750616 | ||
|
|
5903c08c14 | ||
|
|
2babadbc94 | ||
|
|
e397fcc259 | ||
|
|
eee792a019 |
No files matched your search
@@ -0,0 +1,52 @@
|
|||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
.idea
|
||||||
|
# Goland's output filename can not be set manually
|
||||||
|
/go_build_*
|
||||||
|
|
||||||
|
# MS VSCode
|
||||||
|
.vscode
|
||||||
|
__debug_bin*
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
||||||
|
*coverage.out
|
||||||
|
coverage.all
|
||||||
|
coverage.txt
|
||||||
|
cpu.out
|
||||||
|
|
||||||
|
*.db
|
||||||
|
*.log
|
||||||
|
|
||||||
|
/act_runner
|
||||||
|
/debug
|
||||||
|
|
||||||
|
/bin
|
||||||
|
/dist
|
||||||
|
/.env
|
||||||
|
/.runner
|
||||||
|
/config.yaml
|
||||||
|
/Dockerfile
|
||||||
|
.DS_Store
|
||||||
+10
-12
@@ -1,21 +1,19 @@
|
|||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{go}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
[{*.md,*_test.go}]
|
[go.*]
|
||||||
indent_style = unset
|
indent_style = tab
|
||||||
indent_size = unset
|
|
||||||
|
|
||||||
[**/Dockerfile]
|
[Makefile]
|
||||||
indent_style = space
|
indent_style = tab
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
[*.{yml,yaml,js,json,sh,nuspec}]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
---
|
||||||
|
name: release-nightly
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOCKER_ORG: gitea
|
||||||
|
DOCKER_LATEST: nightly
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version-file: "go.mod"
|
||||||
|
- name: goreleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v6
|
||||||
|
with:
|
||||||
|
distribution: goreleaser-pro
|
||||||
|
args: release --nightly
|
||||||
|
env:
|
||||||
|
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||||
|
AWS_REGION: ${{ secrets.AWS_REGION }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
S3_REGION: ${{ secrets.AWS_REGION }}
|
||||||
|
S3_BUCKET: ${{ secrets.AWS_BUCKET }}
|
||||||
|
GORELEASER_FORCE_TOKEN: "gitea"
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
release-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
variant:
|
||||||
|
- target: basic
|
||||||
|
tag_suffix: ""
|
||||||
|
- target: dind
|
||||||
|
tag_suffix: "-dind"
|
||||||
|
- target: dind-rootless
|
||||||
|
tag_suffix: "-dind-rootless"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # all history for all branches and tags
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker BuildX
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Echo the tag
|
||||||
|
run: echo "${{ env.DOCKER_ORG }}/act_runner:nightly${{ matrix.variant.tag_suffix }}"
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
target: ${{ matrix.variant.target }}
|
||||||
|
platforms: |
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ env.DOCKER_ORG }}/act_runner:nightly${{ matrix.variant.tag_suffix }}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
name: release-tag
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # all history for all branches and tags
|
||||||
|
- uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version-file: "go.mod"
|
||||||
|
- name: Import GPG key
|
||||||
|
id: import_gpg
|
||||||
|
uses: crazy-max/ghaction-import-gpg@v6
|
||||||
|
with:
|
||||||
|
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
passphrase: ${{ secrets.PASSPHRASE }}
|
||||||
|
fingerprint: CC64B1DB67ABBEECAB24B6455FC346329753F4B0
|
||||||
|
- name: goreleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v6
|
||||||
|
with:
|
||||||
|
distribution: goreleaser-pro
|
||||||
|
args: release
|
||||||
|
env:
|
||||||
|
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||||
|
AWS_REGION: ${{ secrets.AWS_REGION }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
S3_REGION: ${{ secrets.AWS_REGION }}
|
||||||
|
S3_BUCKET: ${{ secrets.AWS_BUCKET }}
|
||||||
|
GORELEASER_FORCE_TOKEN: "gitea"
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
|
||||||
|
release-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
variant:
|
||||||
|
- target: basic
|
||||||
|
tag_suffix: ""
|
||||||
|
- target: dind
|
||||||
|
tag_suffix: "-dind"
|
||||||
|
- target: dind-rootless
|
||||||
|
tag_suffix: "-dind-rootless"
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
env:
|
||||||
|
DOCKER_ORG: gitea
|
||||||
|
DOCKER_LATEST: latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # all history for all branches and tags
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker BuildX
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Repo Meta
|
||||||
|
id: repo_meta
|
||||||
|
run: |
|
||||||
|
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}') >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: "Docker meta"
|
||||||
|
id: docker_meta
|
||||||
|
uses: https://github.com/docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.DOCKER_ORG }}/${{ steps.repo_meta.outputs.REPO_NAME }}
|
||||||
|
tags: |
|
||||||
|
type=semver,pattern={{major}}.{{minor}}.{{patch}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
flavor: |
|
||||||
|
latest=true
|
||||||
|
suffix=${{ matrix.variant.tag_suffix }},onlatest=true
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
target: ${{ matrix.variant.target }}
|
||||||
|
platforms: |
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||||
@@ -8,14 +8,13 @@ jobs:
|
|||||||
name: check and test
|
name: check and test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
- name: vet checks
|
- name: lint
|
||||||
run: go vet -v ./...
|
run: make lint
|
||||||
- name: build
|
- name: build
|
||||||
run: go build -v ./...
|
run: make build
|
||||||
- name: test
|
- name: test
|
||||||
run: | # Test only the new packages in this fork. Add more packages as needed.
|
run: make test
|
||||||
go test -v ./pkg/jobparser
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
github: cplee
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
name: Bug report
|
|
||||||
description: Use this template for reporting bugs/issues.
|
|
||||||
labels:
|
|
||||||
- 'kind/bug'
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
- type: textarea
|
|
||||||
id: act-debug
|
|
||||||
attributes:
|
|
||||||
label: Bug report info
|
|
||||||
render: plain text
|
|
||||||
description: |
|
|
||||||
Output of `act --bug-report`
|
|
||||||
placeholder: |
|
|
||||||
act --bug-report
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: act-command
|
|
||||||
attributes:
|
|
||||||
label: Command used with act
|
|
||||||
description: |
|
|
||||||
Please paste your whole command
|
|
||||||
placeholder: |
|
|
||||||
act -P ubuntu-latest=node:12 -v -d ...
|
|
||||||
render: sh
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: Describe issue
|
|
||||||
description: |
|
|
||||||
Also tell us what did you expect to happen?
|
|
||||||
placeholder: |
|
|
||||||
Describe issue
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: repo
|
|
||||||
attributes:
|
|
||||||
label: Link to GitHub repository
|
|
||||||
description: |
|
|
||||||
Provide link to GitHub repository, you can skip it if the repository is private or you don't have it on GitHub, otherwise please provide it as it might help us troubleshoot problem
|
|
||||||
placeholder: |
|
|
||||||
https://github.com/nektos/act
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: workflow
|
|
||||||
attributes:
|
|
||||||
label: Workflow content
|
|
||||||
description: |
|
|
||||||
Please paste your **whole** workflow here
|
|
||||||
placeholder: |
|
|
||||||
name: My workflow
|
|
||||||
on: ['push', 'schedule']
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
KEY: VAL
|
|
||||||
[...]
|
|
||||||
render: yml
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: |
|
|
||||||
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. Please verify that the log output doesn't contain any sensitive data.
|
|
||||||
render: sh
|
|
||||||
placeholder: |
|
|
||||||
Use `act -v` for verbose output
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: additional-info
|
|
||||||
attributes:
|
|
||||||
label: Additional information
|
|
||||||
placeholder: |
|
|
||||||
Additional information that doesn't fit elsewhere
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
blank_issues_enabled: true
|
|
||||||
contact_links:
|
|
||||||
- name: Start a discussion
|
|
||||||
url: https://github.com/nektos/act/discussions/new
|
|
||||||
about: You can ask for help here!
|
|
||||||
- name: Ask on Gitter
|
|
||||||
url: https://gitter.im/nektos/act
|
|
||||||
about: You can ask for help here!
|
|
||||||
- name: Ask on Gitter (via Matrix)
|
|
||||||
url: https://matrix.to/#/#nektos_act:gitter.im?via=gitter.im&via=matrix.org
|
|
||||||
about: If you prefer Matrix over Gitter
|
|
||||||
- name: Want to contribute to act?
|
|
||||||
url: https://github.com/nektos/act/blob/master/CONTRIBUTING.md
|
|
||||||
about: Be sure to read contributing guidelines!
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
name: Feature request
|
|
||||||
description: Use this template for requesting a feature/enhancement.
|
|
||||||
labels:
|
|
||||||
- 'kind/feature-request'
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Please note that incompatibility with GitHub Actions should be opened as a bug report, not a new feature.
|
|
||||||
- type: input
|
|
||||||
id: act-version
|
|
||||||
attributes:
|
|
||||||
label: Act version
|
|
||||||
description: |
|
|
||||||
What version of `act` are you using? Version can be obtained via `act --version`
|
|
||||||
If you've built it from source, please provide commit hash
|
|
||||||
placeholder: |
|
|
||||||
act --version
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: feature
|
|
||||||
attributes:
|
|
||||||
label: Feature description
|
|
||||||
description: Describe feature that you would like to see
|
|
||||||
placeholder: ...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
name: Wiki issue
|
|
||||||
description: Report issue/improvement ragarding documentation (wiki)
|
|
||||||
labels:
|
|
||||||
- 'kind/discussion'
|
|
||||||
- 'area/docs'
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this issue!
|
|
||||||
- type: textarea
|
|
||||||
id: details
|
|
||||||
attributes:
|
|
||||||
label: Details
|
|
||||||
description: |
|
|
||||||
Describe issue
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
FROM alpine:3.17
|
|
||||||
|
|
||||||
ARG CHOCOVERSION=1.1.0
|
|
||||||
|
|
||||||
RUN apk add --no-cache bash ca-certificates git \
|
|
||||||
&& apk --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing add mono mono-dev \
|
|
||||||
&& cert-sync /etc/ssl/certs/ca-certificates.crt \
|
|
||||||
&& wget "https://github.com/chocolatey/choco/archive/${CHOCOVERSION}.tar.gz" -O- | tar -xzf - \
|
|
||||||
&& cd choco-"${CHOCOVERSION}" \
|
|
||||||
&& chmod +x build.sh zip.sh \
|
|
||||||
&& ./build.sh -v \
|
|
||||||
&& mv ./code_drop/chocolatey/console /opt/chocolatey \
|
|
||||||
&& mkdir -p /opt/chocolatey/lib \
|
|
||||||
&& rm -rf /choco-"${CHOCOVERSION}" \
|
|
||||||
&& apk del mono-dev \
|
|
||||||
&& rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
ENV ChocolateyInstall=/opt/chocolatey
|
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
name: 'Chocolatey Packager'
|
|
||||||
description: 'Create the choco package and push it'
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: 'Version of package'
|
|
||||||
required: false
|
|
||||||
apiKey:
|
|
||||||
description: 'API Key for chocolately'
|
|
||||||
required: false
|
|
||||||
push:
|
|
||||||
description: 'Option for if package is going to be pushed'
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
runs:
|
|
||||||
using: 'docker'
|
|
||||||
image: 'Dockerfile'
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
function choco {
|
|
||||||
mono /opt/chocolatey/choco.exe "$@" --allow-unofficial --nocolor
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_version {
|
|
||||||
local version=${INPUT_VERSION:-$(git describe --tags)}
|
|
||||||
version=(${version//[!0-9.-]/})
|
|
||||||
local version_parts=(${version//-/ })
|
|
||||||
version=${version_parts[0]}
|
|
||||||
if [ ${#version_parts[@]} -gt 1 ]; then
|
|
||||||
version=${version_parts}.${version_parts[1]}
|
|
||||||
fi
|
|
||||||
echo "$version"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Determine the version to pack
|
|
||||||
VERSION=$(get_version)
|
|
||||||
echo "Packing version ${VERSION} of act"
|
|
||||||
rm -f act-cli.*.nupkg
|
|
||||||
mkdir -p tools
|
|
||||||
cp LICENSE tools/LICENSE.txt
|
|
||||||
cp VERIFICATION tools/VERIFICATION.txt
|
|
||||||
cp dist/act_windows_amd64_v1/act.exe tools/
|
|
||||||
choco pack act-cli.nuspec --version ${VERSION}
|
|
||||||
if [[ "$INPUT_PUSH" == "true" ]]; then
|
|
||||||
choco push act-cli.${VERSION}.nupkg --api-key ${INPUT_APIKEY} -s https://push.chocolatey.org/ --timeout 180
|
|
||||||
fi
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
name: 'run-tests'
|
|
||||||
description: 'Runs go test and upload a step summary'
|
|
||||||
inputs:
|
|
||||||
filter:
|
|
||||||
description: 'The go test pattern for the tests to run'
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
upload-logs-name:
|
|
||||||
description: 'Choose the name of the log artifact'
|
|
||||||
required: false
|
|
||||||
default: logs-${{ github.job }}-${{ strategy.job-index }}
|
|
||||||
upload-logs:
|
|
||||||
description: 'If true uploads logs of each tests as an artifact'
|
|
||||||
required: false
|
|
||||||
default: 'true'
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- uses: actions/github-script@v6
|
|
||||||
with:
|
|
||||||
github-token: none # No reason to grant access to the GITHUB_TOKEN
|
|
||||||
script: |
|
|
||||||
let myOutput = '';
|
|
||||||
var fs = require('fs');
|
|
||||||
var uploadLogs = process.env.UPLOAD_LOGS === 'true';
|
|
||||||
if(uploadLogs) {
|
|
||||||
await io.mkdirP('logs');
|
|
||||||
}
|
|
||||||
var filename = null;
|
|
||||||
const options = {};
|
|
||||||
options.ignoreReturnCode = true;
|
|
||||||
options.env = Object.assign({}, process.env);
|
|
||||||
delete options.env.ACTIONS_RUNTIME_URL;
|
|
||||||
delete options.env.ACTIONS_RUNTIME_TOKEN;
|
|
||||||
delete options.env.ACTIONS_CACHE_URL;
|
|
||||||
options.listeners = {
|
|
||||||
stdout: (data) => {
|
|
||||||
for(line of data.toString().split('\n')) {
|
|
||||||
if(/^\s*(===\s[^\s]+\s|---\s[^\s]+:\s)/.test(line)) {
|
|
||||||
if(uploadLogs) {
|
|
||||||
var runprefix = "=== RUN ";
|
|
||||||
if(line.startsWith(runprefix)) {
|
|
||||||
filename = "logs/" + line.substring(runprefix.length).replace(/[^A-Za-z0-9]/g, '-') + ".txt";
|
|
||||||
fs.writeFileSync(filename, line + "\n");
|
|
||||||
} else if(filename) {
|
|
||||||
fs.appendFileSync(filename, line + "\n");
|
|
||||||
filename = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
myOutput += line + "\n";
|
|
||||||
} else if(filename) {
|
|
||||||
fs.appendFileSync(filename, line + "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var args = ['test', '-v', '-cover', '-coverprofile=coverage.txt', '-covermode=atomic', '-timeout', '20m'];
|
|
||||||
var filter = process.env.FILTER;
|
|
||||||
if(filter) {
|
|
||||||
args.push('-run');
|
|
||||||
args.push(filter);
|
|
||||||
}
|
|
||||||
args.push('./...');
|
|
||||||
var exitcode = await exec.exec('go', args, options);
|
|
||||||
if(process.env.GITHUB_STEP_SUMMARY) {
|
|
||||||
core.summary.addCodeBlock(myOutput);
|
|
||||||
await core.summary.write();
|
|
||||||
}
|
|
||||||
process.exit(exitcode);
|
|
||||||
env:
|
|
||||||
FILTER: ${{ inputs.filter }}
|
|
||||||
UPLOAD_LOGS: ${{ inputs.upload-logs }}
|
|
||||||
- uses: actions/upload-artifact@v3
|
|
||||||
if: always() && inputs.upload-logs == 'true' && !env.ACT
|
|
||||||
with:
|
|
||||||
name: ${{ inputs.upload-logs-name }}
|
|
||||||
path: logs
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# To get started with Dependabot version updates, you'll need to specify which
|
|
||||||
# package ecosystems to update and where the package manifests are located.
|
|
||||||
# Please see the documentation for all configuration options:
|
|
||||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
|
||||||
|
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: 'github-actions'
|
|
||||||
directory: '/'
|
|
||||||
schedule:
|
|
||||||
interval: 'weekly'
|
|
||||||
- package-ecosystem: 'gomod'
|
|
||||||
directory: '/'
|
|
||||||
schedule:
|
|
||||||
interval: 'weekly'
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
test-*.yml
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
name: checks
|
|
||||||
on: [pull_request, workflow_dispatch]
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
cancel-in-progress: true
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
env:
|
|
||||||
ACT_OWNER: ${{ github.repository_owner }}
|
|
||||||
ACT_REPOSITORY: ${{ github.repository }}
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
name: lint
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: golangci/[email protected]
|
|
||||||
with:
|
|
||||||
version: v1.53
|
|
||||||
only-new-issues: true
|
|
||||||
- uses: megalinter/megalinter/flavors/[email protected]
|
|
||||||
env:
|
|
||||||
DEFAULT_BRANCH: master
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
VALIDATE_ALL_CODEBASE: false
|
|
||||||
GITHUB_STATUS_REPORTER: ${{ !env.ACT }}
|
|
||||||
GITHUB_COMMENT_REPORTER: ${{ !env.ACT }}
|
|
||||||
|
|
||||||
test-linux:
|
|
||||||
name: test-linux
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
with:
|
|
||||||
path: ~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
- name: Run Tests
|
|
||||||
uses: ./.github/actions/run-tests
|
|
||||||
with:
|
|
||||||
upload-logs-name: logs-linux
|
|
||||||
- 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
|
|
||||||
- name: Upload Codecov report
|
|
||||||
uses: codecov/[email protected]
|
|
||||||
with:
|
|
||||||
files: coverage.txt
|
|
||||||
fail_ci_if_error: true # optional (default = false)
|
|
||||||
|
|
||||||
test-host:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os:
|
|
||||||
- windows-latest
|
|
||||||
- macos-latest
|
|
||||||
name: test-${{matrix.os}}
|
|
||||||
runs-on: ${{matrix.os}}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- name: Run Tests
|
|
||||||
uses: ./.github/actions/run-tests
|
|
||||||
with:
|
|
||||||
filter: '^TestRunEventHostEnvironment$'
|
|
||||||
upload-logs-name: logs-${{ matrix.os }}
|
|
||||||
|
|
||||||
snapshot:
|
|
||||||
name: snapshot
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
with:
|
|
||||||
path: ~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
- name: GoReleaser
|
|
||||||
uses: goreleaser/goreleaser-action@v5
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
args: release --snapshot --clean
|
|
||||||
- name: Capture x86_64 (64-bit) Linux binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-linux-amd64
|
|
||||||
path: dist/act_linux_amd64_v1/act
|
|
||||||
- name: Capture i386 (32-bit) Linux binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-linux-i386
|
|
||||||
path: dist/act_linux_386/act
|
|
||||||
- name: Capture arm64 (64-bit) Linux binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-linux-arm64
|
|
||||||
path: dist/act_linux_arm64/act
|
|
||||||
- name: Capture armv6 (32-bit) Linux binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-linux-armv6
|
|
||||||
path: dist/act_linux_arm_6/act
|
|
||||||
- name: Capture armv7 (32-bit) Linux binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-linux-armv7
|
|
||||||
path: dist/act_linux_arm_7/act
|
|
||||||
- name: Capture x86_64 (64-bit) Windows binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-windows-amd64
|
|
||||||
path: dist/act_windows_amd64_v1/act.exe
|
|
||||||
- name: Capture i386 (32-bit) Windows binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-windows-i386
|
|
||||||
path: dist/act_windows_386/act.exe
|
|
||||||
- name: Capture arm64 (64-bit) Windows binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-windows-arm64
|
|
||||||
path: dist/act_windows_arm64/act.exe
|
|
||||||
- name: Capture armv7 (32-bit) Windows binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-windows-armv7
|
|
||||||
path: dist/act_windows_arm_7/act.exe
|
|
||||||
- name: Capture x86_64 (64-bit) MacOS binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-macos-amd64
|
|
||||||
path: dist/act_darwin_amd64_v1/act
|
|
||||||
- name: Capture arm64 (64-bit) MacOS binary
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: act-macos-arm64
|
|
||||||
path: dist/act_darwin_arm64/act
|
|
||||||
- name: Chocolatey
|
|
||||||
uses: ./.github/actions/choco
|
|
||||||
with:
|
|
||||||
version: v0.0.0-pr
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
name: promote
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 2 1 * *'
|
|
||||||
workflow_dispatch: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: promote
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: master
|
|
||||||
token: ${{ secrets.GORELEASER_GITHUB_TOKEN }}
|
|
||||||
- uses: fregante/setup-git-user@v2
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
with:
|
|
||||||
path: ~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
- run: make promote
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
name: release
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- v*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
if: ${{ !env.ACT }}
|
|
||||||
with:
|
|
||||||
path: ~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
- name: GoReleaser
|
|
||||||
uses: goreleaser/goreleaser-action@v5
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
args: release --clean
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN }}
|
|
||||||
- name: Winget
|
|
||||||
uses: vedantmgoyal2009/winget-releaser@v2
|
|
||||||
with:
|
|
||||||
identifier: nektos.act
|
|
||||||
installers-regex: '_Windows_\w+\.zip$'
|
|
||||||
token: ${{ secrets.WINGET_TOKEN }}
|
|
||||||
- name: Chocolatey
|
|
||||||
uses: ./.github/actions/choco
|
|
||||||
with:
|
|
||||||
version: ${{ github.ref }}
|
|
||||||
apiKey: ${{ secrets.CHOCO_APIKEY }}
|
|
||||||
push: true
|
|
||||||
- name: GitHub CLI extension
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GORELEASER_GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
const mainRef = (await github.rest.git.getRef({
|
|
||||||
owner: 'nektos',
|
|
||||||
repo: 'gh-act',
|
|
||||||
ref: 'heads/main',
|
|
||||||
})).data;
|
|
||||||
console.log(mainRef);
|
|
||||||
github.rest.git.createRef({
|
|
||||||
owner: 'nektos',
|
|
||||||
repo: 'gh-act',
|
|
||||||
ref: context.ref,
|
|
||||||
sha: mainRef.object.sha,
|
|
||||||
});
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
name: 'Close stale issues'
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
name: Stale
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v9
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
stale-issue-message: 'Issue is stale and will be closed in 14 days unless there is new activity'
|
|
||||||
stale-pr-message: 'PR is stale and will be closed in 14 days unless there is new activity'
|
|
||||||
stale-issue-label: 'stale'
|
|
||||||
exempt-issue-labels: 'stale-exempt,kind/feature-request'
|
|
||||||
stale-pr-label: 'stale'
|
|
||||||
exempt-pr-labels: 'stale-exempt'
|
|
||||||
remove-stale-when-updated: 'True'
|
|
||||||
operations-per-run: 500
|
|
||||||
days-before-stale: 180
|
|
||||||
days-before-close: 14
|
|
||||||
+11
-32
@@ -1,34 +1,13 @@
|
|||||||
# Binaries for programs and plugins
|
/act_runner
|
||||||
*.exe
|
|
||||||
*.exe~
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Test binary, build with `go test -c`
|
|
||||||
*.test
|
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
|
||||||
*.out
|
|
||||||
|
|
||||||
/dist/
|
|
||||||
.todo
|
|
||||||
|
|
||||||
*.nupkg
|
|
||||||
.vscode/
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# Path for actions cache created when running tests
|
|
||||||
pkg/runner/act/
|
|
||||||
|
|
||||||
# act binary
|
|
||||||
dist/local/act
|
|
||||||
|
|
||||||
coverage.txt
|
|
||||||
|
|
||||||
.env
|
.env
|
||||||
.secrets
|
.runner
|
||||||
|
coverage.txt
|
||||||
|
/config.yaml
|
||||||
|
|
||||||
# megalinter
|
# Jetbrains
|
||||||
report/
|
.idea
|
||||||
act
|
# MS VSCode
|
||||||
|
.vscode
|
||||||
|
__debug_bin
|
||||||
|
# gorelease binary folder
|
||||||
|
dist
|
||||||
@@ -1 +0,0 @@
|
|||||||
b910a42edfab7a02b08a52ecef203fd419725642:pkg/container/testdata/docker-pull-options/config.json:generic-api-key:4
|
|
||||||
+120
-46
@@ -1,51 +1,125 @@
|
|||||||
# Minimum golangci-lint version required: v1.46.0
|
version: "2"
|
||||||
run:
|
output:
|
||||||
timeout: 3m
|
sort-order:
|
||||||
|
- file
|
||||||
skip-dirs:
|
|
||||||
- report # megalinter results+fixes
|
|
||||||
|
|
||||||
linters-settings:
|
|
||||||
gocyclo:
|
|
||||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
|
||||||
min-complexity: 15
|
|
||||||
gocritic:
|
|
||||||
disabled-checks:
|
|
||||||
- ifElseChain
|
|
||||||
importas:
|
|
||||||
aliases:
|
|
||||||
- pkg: 'github.com/sirupsen/logrus'
|
|
||||||
alias: log
|
|
||||||
- pkg: 'github.com/stretchr/testify/assert'
|
|
||||||
alias: assert
|
|
||||||
depguard:
|
|
||||||
rules:
|
|
||||||
main:
|
|
||||||
deny:
|
|
||||||
- pkg: github.com/pkg/errors
|
|
||||||
desc: Please use "errors" package from standard library
|
|
||||||
- pkg: gotest.tools/v3
|
|
||||||
desc: Please keep tests unified using only github.com/stretchr/testify
|
|
||||||
- pkg: log
|
|
||||||
desc: Please keep logging unified using only github.com/sirupsen/logrus
|
|
||||||
linters:
|
linters:
|
||||||
|
default: none
|
||||||
enable:
|
enable:
|
||||||
- megacheck
|
- bidichk
|
||||||
- govet
|
- bodyclose
|
||||||
- revive
|
|
||||||
- gocyclo
|
|
||||||
- gosec
|
|
||||||
- unconvert
|
|
||||||
- dupl
|
|
||||||
- nakedret
|
|
||||||
- prealloc
|
|
||||||
- exportloopref
|
|
||||||
- gocritic
|
|
||||||
- goimports
|
|
||||||
- whitespace
|
|
||||||
- misspell
|
|
||||||
- depguard
|
- depguard
|
||||||
- importas
|
- dupl
|
||||||
- contextcheck
|
- errcheck
|
||||||
|
- forbidigo
|
||||||
|
- gocheckcompilerdirectives
|
||||||
|
- gocritic
|
||||||
|
- goheader
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- mirror
|
||||||
|
- modernize
|
||||||
|
- nakedret
|
||||||
|
- nilnil
|
||||||
- nolintlint
|
- nolintlint
|
||||||
|
- perfsprint
|
||||||
- revive
|
- revive
|
||||||
|
- staticcheck
|
||||||
|
- testifylint
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- usestdlibvars
|
||||||
|
- usetesting
|
||||||
|
- wastedassign
|
||||||
|
settings:
|
||||||
|
depguard:
|
||||||
|
rules:
|
||||||
|
main:
|
||||||
|
deny:
|
||||||
|
- pkg: io/ioutil
|
||||||
|
desc: use os or io instead
|
||||||
|
- pkg: golang.org/x/exp
|
||||||
|
desc: it's experimental and unreliable
|
||||||
|
- pkg: github.com/pkg/errors
|
||||||
|
desc: use builtin errors package instead
|
||||||
|
nolintlint:
|
||||||
|
allow-unused: false
|
||||||
|
require-explanation: true
|
||||||
|
require-specific: true
|
||||||
|
gocritic:
|
||||||
|
enabled-checks:
|
||||||
|
- equalFold
|
||||||
|
disabled-checks:
|
||||||
|
- ifElseChain
|
||||||
|
revive:
|
||||||
|
severity: error
|
||||||
|
rules:
|
||||||
|
- name: blank-imports
|
||||||
|
- name: constant-logical-expr
|
||||||
|
- name: context-as-argument
|
||||||
|
- name: context-keys-type
|
||||||
|
- name: dot-imports
|
||||||
|
- name: empty-lines
|
||||||
|
- name: error-return
|
||||||
|
- name: error-strings
|
||||||
|
- name: exported
|
||||||
|
- name: identical-branches
|
||||||
|
- name: if-return
|
||||||
|
- name: increment-decrement
|
||||||
|
- name: modifies-value-receiver
|
||||||
|
- name: package-comments
|
||||||
|
- name: redefines-builtin-id
|
||||||
|
- name: superfluous-else
|
||||||
|
- name: time-naming
|
||||||
|
- name: unexported-return
|
||||||
|
- name: var-declaration
|
||||||
|
- name: var-naming
|
||||||
|
staticcheck:
|
||||||
|
checks:
|
||||||
|
- all
|
||||||
|
- -ST1005
|
||||||
|
usetesting:
|
||||||
|
os-temp-dir: true
|
||||||
|
perfsprint:
|
||||||
|
concat-loop: false
|
||||||
|
govet:
|
||||||
|
enable:
|
||||||
|
- nilness
|
||||||
|
- unusedwrite
|
||||||
|
goheader:
|
||||||
|
values:
|
||||||
|
regexp:
|
||||||
|
HEADER: 'Copyright \d{4} The Gitea Authors\. All rights reserved\.(\nCopyright [^\n]+)*\nSPDX-License-Identifier: MIT'
|
||||||
|
template: '{{ HEADER }}'
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
|
rules:
|
||||||
|
- linters:
|
||||||
|
- forbidigo
|
||||||
|
path: cmd
|
||||||
|
issues:
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gci
|
||||||
|
- gofumpt
|
||||||
|
settings:
|
||||||
|
gci:
|
||||||
|
custom-order: true
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- prefix(gitea.com/gitea/act_runner)
|
||||||
|
- blank
|
||||||
|
- default
|
||||||
|
gofumpt:
|
||||||
|
extra-rules: true
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
run:
|
||||||
|
timeout: 10m
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "usage: $0 <path>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SUM=$(shasum -a 256 "$1" | cut -d' ' -f1)
|
||||||
|
BASENAME=$(basename "$1")
|
||||||
|
echo -n "${SUM} ${BASENAME}" > "$1".sha256
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go mod tidy
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- darwin
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
- freebsd
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm
|
||||||
|
- arm64
|
||||||
|
- loong64
|
||||||
|
- s390x
|
||||||
|
- riscv64
|
||||||
|
goarm:
|
||||||
|
- "5"
|
||||||
|
- "6"
|
||||||
|
- "7"
|
||||||
|
ignore:
|
||||||
|
- goos: darwin
|
||||||
|
goarch: arm
|
||||||
|
- goos: darwin
|
||||||
|
goarch: ppc64le
|
||||||
|
- goos: darwin
|
||||||
|
goarch: s390x
|
||||||
|
- goos: windows
|
||||||
|
goarch: ppc64le
|
||||||
|
- goos: windows
|
||||||
|
goarch: s390x
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm
|
||||||
|
goarm: "5"
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm
|
||||||
|
goarm: "6"
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm
|
||||||
|
goarm: "7"
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm64
|
||||||
|
- goos: freebsd
|
||||||
|
goarch: ppc64le
|
||||||
|
- goos: freebsd
|
||||||
|
goarch: s390x
|
||||||
|
- goos: freebsd
|
||||||
|
goarch: arm
|
||||||
|
goarm: "5"
|
||||||
|
- goos: freebsd
|
||||||
|
goarch: arm
|
||||||
|
goarm: "6"
|
||||||
|
- goos: freebsd
|
||||||
|
goarch: arm
|
||||||
|
goarm: "7"
|
||||||
|
- goos: freebsd
|
||||||
|
goarch: arm64
|
||||||
|
flags:
|
||||||
|
- -trimpath
|
||||||
|
ldflags:
|
||||||
|
- -s -w -X gitea.com/gitea/act_runner/internal/pkg/ver.version={{ .Summary }}
|
||||||
|
binary: >-
|
||||||
|
{{ .ProjectName }}-
|
||||||
|
{{- .Version }}-
|
||||||
|
{{- .Os }}-
|
||||||
|
{{- if eq .Arch "amd64" }}amd64
|
||||||
|
{{- else if eq .Arch "amd64_v1" }}amd64
|
||||||
|
{{- else if eq .Arch "386" }}386
|
||||||
|
{{- else }}{{ .Arch }}{{ end }}
|
||||||
|
{{- if .Arm }}-{{ .Arm }}{{ end }}
|
||||||
|
no_unique_dist_dir: true
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- cmd: xz -k -9 {{ .Path }}
|
||||||
|
dir: ./dist/
|
||||||
|
- cmd: sh .goreleaser.checksum.sh {{ .Path }}
|
||||||
|
- cmd: sh .goreleaser.checksum.sh {{ .Path }}.xz
|
||||||
|
|
||||||
|
blobs:
|
||||||
|
-
|
||||||
|
provider: s3
|
||||||
|
bucket: "{{ .Env.S3_BUCKET }}"
|
||||||
|
region: "{{ .Env.S3_REGION }}"
|
||||||
|
directory: "act_runner/{{.Version}}"
|
||||||
|
extra_files:
|
||||||
|
- glob: ./**.xz
|
||||||
|
- glob: ./**.sha256
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- format: binary
|
||||||
|
name_template: "{{ .Binary }}"
|
||||||
|
allow_different_binary_count: true
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
|
extra_files:
|
||||||
|
- glob: ./**.xz
|
||||||
|
|
||||||
|
snapshot:
|
||||||
|
version_template: "{{ .Branch }}-devel"
|
||||||
|
|
||||||
|
nightly:
|
||||||
|
version_template: "nightly"
|
||||||
|
|
||||||
|
gitea_urls:
|
||||||
|
api: https://gitea.com/api/v1
|
||||||
|
download: https://gitea.com
|
||||||
|
|
||||||
|
release:
|
||||||
|
extra_files:
|
||||||
|
- glob: ./**.xz
|
||||||
|
- glob: ./**.xz.sha256
|
||||||
|
|
||||||
|
# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
|
||||||
|
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
before:
|
|
||||||
hooks:
|
|
||||||
- go mod tidy
|
|
||||||
builds:
|
|
||||||
- env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
goos:
|
|
||||||
- darwin
|
|
||||||
- linux
|
|
||||||
- windows
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- '386'
|
|
||||||
- arm64
|
|
||||||
- arm
|
|
||||||
goarm:
|
|
||||||
- '6'
|
|
||||||
- '7'
|
|
||||||
ignore:
|
|
||||||
- goos: windows
|
|
||||||
goarm: '6'
|
|
||||||
checksum:
|
|
||||||
name_template: 'checksums.txt'
|
|
||||||
archives:
|
|
||||||
- name_template: >-
|
|
||||||
{{ .ProjectName }}_
|
|
||||||
{{- title .Os }}_
|
|
||||||
{{- if eq .Arch "amd64" }}x86_64
|
|
||||||
{{- else if eq .Arch "386" }}i386
|
|
||||||
{{- else }}{{ .Arch }}{{ end }}
|
|
||||||
{{- if .Arm }}v{{ .Arm }}{{ end }}
|
|
||||||
format_overrides:
|
|
||||||
- goos: windows
|
|
||||||
format: zip
|
|
||||||
changelog:
|
|
||||||
groups:
|
|
||||||
- title: 'New Features'
|
|
||||||
regexp: "^.*feat[(\\w)]*:+.*$"
|
|
||||||
order: 0
|
|
||||||
- title: 'Bug fixes'
|
|
||||||
regexp: "^.*fix[(\\w)]*:+.*$"
|
|
||||||
order: 1
|
|
||||||
- title: 'Documentation updates'
|
|
||||||
regexp: "^.*docs[(\\w)]*:+.*$"
|
|
||||||
order: 2
|
|
||||||
- title: 'Other'
|
|
||||||
order: 999
|
|
||||||
release:
|
|
||||||
prerelease: auto
|
|
||||||
mode: append
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Default state for all rules
|
|
||||||
default: true
|
|
||||||
|
|
||||||
# MD013/line-length - Line length
|
|
||||||
MD013:
|
|
||||||
line_length: 1024
|
|
||||||
|
|
||||||
# MD033/no-inline-html - Inline HTML
|
|
||||||
MD033: false
|
|
||||||
|
|
||||||
# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading
|
|
||||||
MD041: false
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
APPLY_FIXES: none
|
|
||||||
DISABLE:
|
|
||||||
- ACTION
|
|
||||||
- BASH
|
|
||||||
- COPYPASTE
|
|
||||||
- DOCKERFILE
|
|
||||||
- GO
|
|
||||||
- JAVASCRIPT
|
|
||||||
- SPELL
|
|
||||||
DISABLE_LINTERS:
|
|
||||||
- YAML_YAMLLINT
|
|
||||||
- MARKDOWN_MARKDOWN_TABLE_FORMATTER
|
|
||||||
- MARKDOWN_MARKDOWN_LINK_CHECK
|
|
||||||
- REPOSITORY_CHECKOV
|
|
||||||
- REPOSITORY_TRIVY
|
|
||||||
FILTER_REGEX_EXCLUDE: (.*testdata/*|install.sh|pkg/container/docker_cli.go|pkg/container/DOCKER_LICENSE|VERSION)
|
|
||||||
MARKDOWN_MARKDOWNLINT_CONFIG_FILE: .markdownlint.yml
|
|
||||||
PARALLEL: false
|
|
||||||
PRINT_ALPACA: false
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
pull_request_rules:
|
|
||||||
- name: warn on conflicts
|
|
||||||
conditions:
|
|
||||||
- -draft
|
|
||||||
- -closed
|
|
||||||
- -merged
|
|
||||||
- conflict
|
|
||||||
actions:
|
|
||||||
comment:
|
|
||||||
message: '@{{author}} this pull request is now in conflict 😩'
|
|
||||||
label:
|
|
||||||
add:
|
|
||||||
- conflict
|
|
||||||
- name: remove conflict label if not needed
|
|
||||||
conditions:
|
|
||||||
- -conflict
|
|
||||||
actions:
|
|
||||||
label:
|
|
||||||
remove:
|
|
||||||
- conflict
|
|
||||||
- name: warn on needs-work
|
|
||||||
conditions:
|
|
||||||
- -draft
|
|
||||||
- -closed
|
|
||||||
- -merged
|
|
||||||
- or:
|
|
||||||
- check-failure=lint
|
|
||||||
- check-failure=test-linux
|
|
||||||
- check-failure=codecov/patch
|
|
||||||
- check-failure=codecov/project
|
|
||||||
- check-failure=snapshot
|
|
||||||
actions:
|
|
||||||
comment:
|
|
||||||
message: '@{{author}} this pull request has failed checks 🛠'
|
|
||||||
label:
|
|
||||||
add:
|
|
||||||
- needs-work
|
|
||||||
- name: remove needs-work label if not needed
|
|
||||||
conditions:
|
|
||||||
- check-success=lint
|
|
||||||
- check-success=test-linux
|
|
||||||
- check-success=codecov/patch
|
|
||||||
- check-success=codecov/project
|
|
||||||
- check-success=snapshot
|
|
||||||
actions:
|
|
||||||
label:
|
|
||||||
remove:
|
|
||||||
- needs-work
|
|
||||||
- name: Automatic maintainer assignment
|
|
||||||
conditions:
|
|
||||||
- '-approved-reviews-by=@nektos/act-maintainers'
|
|
||||||
- -draft
|
|
||||||
- -merged
|
|
||||||
- -closed
|
|
||||||
- -conflict
|
|
||||||
- check-success=lint
|
|
||||||
- check-success=test-linux
|
|
||||||
- check-success=codecov/patch
|
|
||||||
- check-success=codecov/project
|
|
||||||
- check-success=snapshot
|
|
||||||
actions:
|
|
||||||
request_reviews:
|
|
||||||
teams:
|
|
||||||
- '@nektos/act-maintainers'
|
|
||||||
- name: Automatic merge on approval
|
|
||||||
conditions:
|
|
||||||
- '#changes-requested-reviews-by=0'
|
|
||||||
- or:
|
|
||||||
- 'approved-reviews-by=@nektos/act-committers'
|
|
||||||
- 'author~=^dependabot(|-preview)\[bot\]$'
|
|
||||||
- and:
|
|
||||||
- 'approved-reviews-by=@nektos/act-maintainers'
|
|
||||||
- '#approved-reviews-by>=2'
|
|
||||||
- and:
|
|
||||||
- 'author=@nektos/act-maintainers'
|
|
||||||
- 'approved-reviews-by=@nektos/act-maintainers'
|
|
||||||
- '#approved-reviews-by>=1'
|
|
||||||
- -draft
|
|
||||||
- -merged
|
|
||||||
- -closed
|
|
||||||
- check-success=lint
|
|
||||||
- check-success=test-linux
|
|
||||||
- check-success=codecov/patch
|
|
||||||
- check-success=codecov/project
|
|
||||||
- check-success=snapshot
|
|
||||||
actions:
|
|
||||||
queue:
|
|
||||||
method: squash
|
|
||||||
name: default
|
|
||||||
queue_rules:
|
|
||||||
- name: default
|
|
||||||
conditions:
|
|
||||||
- check-success=lint
|
|
||||||
- check-success=test-linux
|
|
||||||
- check-success=codecov/patch
|
|
||||||
- check-success=codecov/project
|
|
||||||
- check-success=snapshot
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
**/testdata
|
|
||||||
pkg/runner/res
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
overrides:
|
|
||||||
- files: '*.yml'
|
|
||||||
options:
|
|
||||||
singleQuote: true
|
|
||||||
- files: '*.json'
|
|
||||||
options:
|
|
||||||
singleQuote: false
|
|
||||||
Vendored
-9
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"editorconfig.editorconfig",
|
|
||||||
"golang.go",
|
|
||||||
"davidanson.vscode-markdownlint",
|
|
||||||
"esbenp.prettier-vscode",
|
|
||||||
"redhat.vscode-yaml"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Vendored
-14
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"go.lintTool": "golangci-lint",
|
|
||||||
"go.lintFlags": ["--fix"],
|
|
||||||
"go.testTimeout": "300s",
|
|
||||||
"[json]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
||||||
},
|
|
||||||
"[markdown]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
||||||
},
|
|
||||||
"[yaml]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
- Use `make help` to find available development targets
|
||||||
|
- Run `make fmt` to format `.go` files, and run `make lint-go` to lint them
|
||||||
|
- Run `make tidy` after any `go.mod` changes
|
||||||
|
- Run single go unit tests with `go test -run '^TestName$' ./modulepath/`
|
||||||
|
- Add the current year into the copyright header of new `.go` files
|
||||||
|
- Ensure no trailing whitespace in edited files
|
||||||
|
- Never force-push, amend, or squash unless asked. Use new commits and normal push for pull request updates
|
||||||
|
- Preserve existing code comments, do not remove or rewrite comments that are still relevant
|
||||||
|
- Include authorship attribution in issue and pull request comments
|
||||||
|
- Add `Co-Authored-By` lines to all commits, indicating name and model used
|
||||||
@@ -1 +0,0 @@
|
|||||||
* @nektos/act-maintainers
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
# Contributing to Act
|
|
||||||
|
|
||||||
Help wanted! We'd love your contributions to Act. Please review the following guidelines before contributing. Also, feel free to propose changes to these guidelines by updating this file and submitting a pull request.
|
|
||||||
|
|
||||||
- [I have a question...](#questions)
|
|
||||||
- [I found a bug...](#bugs)
|
|
||||||
- [I have a feature request...](#features)
|
|
||||||
- [I have a contribution to share...](#process)
|
|
||||||
|
|
||||||
## <a id="questions"></a> Have a Question?
|
|
||||||
|
|
||||||
Please don't open a GitHub issue for questions about how to use `act`, as the goal is to use issues for managing bugs and feature requests. Issues that are related to general support will be closed and redirected to our gitter room.
|
|
||||||
|
|
||||||
For all support related questions, please ask the question in our gitter room: [nektos/act](https://gitter.im/nektos/act).
|
|
||||||
|
|
||||||
## <a id="bugs"></a> Found a Bug?
|
|
||||||
|
|
||||||
If you've identified a bug in `act`, please [submit an issue](#issue) to our GitHub repo: [nektos/act](https://github.com/nektos/act/issues/new). Please also feel free to submit a [Pull Request](#pr) with a fix for the bug!
|
|
||||||
|
|
||||||
## <a id="features"></a> Have a Feature Request?
|
|
||||||
|
|
||||||
All feature requests should start with [submitting an issue](#issue) documenting the user story and acceptance criteria. Again, feel free to submit a [Pull Request](#pr) with a proposed implementation of the feature.
|
|
||||||
|
|
||||||
## <a id="process"></a> Ready to Contribute
|
|
||||||
|
|
||||||
### <a id="issue"></a> Create an issue
|
|
||||||
|
|
||||||
Before submitting a new issue, please search the issues to make sure there isn't a similar issue doesn't already exist.
|
|
||||||
|
|
||||||
Assuming no existing issues exist, please ensure you include required information when submitting the issue to ensure we can quickly reproduce your issue.
|
|
||||||
|
|
||||||
We may have additional questions and will communicate through the GitHub issue, so please respond back to our questions to help reproduce and resolve the issue as quickly as possible.
|
|
||||||
|
|
||||||
New issues can be created with in our [GitHub repo](https://github.com/nektos/act/issues/new).
|
|
||||||
|
|
||||||
### <a id="pr"></a>Pull Requests
|
|
||||||
|
|
||||||
Pull requests should target the `master` branch. Please also reference the issue from the description of the pull request using [special keyword syntax](https://help.github.com/articles/closing-issues-via-commit-messages/) to auto close the issue when the PR is merged. For example, include the phrase `fixes #14` in the PR description to have issue #14 auto close. Please send documentation updates for the [act user guide](https://nektosact.com) to [nektos/act-docs](https://github.com/nektos/act-docs).
|
|
||||||
|
|
||||||
### <a id="style"></a> Styleguide
|
|
||||||
|
|
||||||
When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. Here are a few points to keep in mind:
|
|
||||||
|
|
||||||
- Please run `go fmt ./...` before committing to ensure code aligns with go standards.
|
|
||||||
- We use [`golangci-lint`](https://golangci-lint.run/) for linting Go code, run `golangci-lint run --fix` before submitting PR. Editors such as Visual Studio Code or JetBrains IntelliJ; with Go support plugin will offer `golangci-lint` automatically.
|
|
||||||
- There are additional linters and formatters for files such as Markdown documents or YAML/JSON:
|
|
||||||
- Please refer to the [Makefile](Makefile) or [`lint` job in our workflow](.github/workflows/checks.yml) to see how to those linters/formatters work.
|
|
||||||
- You can lint codebase by running `go run main.go -j lint --env RUN_LOCAL=true` or `act -j lint --env RUN_LOCAL=true`
|
|
||||||
- In `Makefile`, there are tools that require `npx` which is shipped with `nodejs`.
|
|
||||||
- Our `Makefile` exports `GITHUB_TOKEN` from `~/.config/github/token`, you have been warned.
|
|
||||||
- You can run `make pr` to cleanup dependencies, format/lint code and run tests.
|
|
||||||
- All dependencies must be defined in the `go.mod` file.
|
|
||||||
- Advanced IDEs and code editors (like VSCode) will take care of that, but to be sure, run `go mod tidy` to validate dependencies.
|
|
||||||
- For details on the approved style, check out [Effective Go](https://golang.org/doc/effective_go.html).
|
|
||||||
- Before running tests, please be aware that they are multi-architecture so for them to not fail, you need to run `docker run --privileged --rm tonistiigi/binfmt --install amd64,arm64` before ([more info available in #765](https://github.com/nektos/act/issues/765)).
|
|
||||||
|
|
||||||
Also, consider the original design principles:
|
|
||||||
|
|
||||||
- **Polyglot** - There will be no prescribed language or framework for developing the microservices. The only requirement will be that the service will be run inside a container and exposed via an HTTP endpoint.
|
|
||||||
- **Cloud Provider** - At this point, the tool will assume AWS for the cloud provider and will not be written in a cloud agnostic manner. However, this does not preclude refactoring to add support for other providers at a later time.
|
|
||||||
- **Declarative** - All resource administration will be handled in a declarative vs. imperative manner. A file will be used to declared the desired state of the resources and the tool will simply assert the actual state matches the desired state. The tool will accomplish this by generating CloudFormation templates.
|
|
||||||
- **Stateless** - The tool will not maintain its own state. Rather, it will rely on the CloudFormation stacks to determine the state of the platform.
|
|
||||||
- **Secure** - All security will be managed by AWS IAM credentials. No additional authentication or authorization mechanisms will be introduced.
|
|
||||||
|
|
||||||
### License
|
|
||||||
|
|
||||||
By contributing your code, you agree to license your contribution under the terms of the [MIT License](LICENSE).
|
|
||||||
|
|
||||||
All files are released with the MIT license.
|
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
### BUILDER STAGE
|
||||||
|
#
|
||||||
|
#
|
||||||
|
FROM golang:1.26-alpine AS builder
|
||||||
|
|
||||||
|
# Do not remove `git` here, it is required for getting runner version when executing `make build`
|
||||||
|
RUN apk add --no-cache make git
|
||||||
|
|
||||||
|
ARG GOPROXY
|
||||||
|
ENV GOPROXY=${GOPROXY:-}
|
||||||
|
|
||||||
|
COPY . /opt/src/act_runner
|
||||||
|
WORKDIR /opt/src/act_runner
|
||||||
|
|
||||||
|
RUN make clean && make build
|
||||||
|
|
||||||
|
### DIND VARIANT
|
||||||
|
#
|
||||||
|
#
|
||||||
|
FROM docker:28-dind AS dind
|
||||||
|
|
||||||
|
RUN apk add --no-cache s6 bash git tzdata
|
||||||
|
|
||||||
|
COPY --from=builder /opt/src/act_runner/act_runner /usr/local/bin/act_runner
|
||||||
|
COPY scripts/run.sh /usr/local/bin/run.sh
|
||||||
|
COPY scripts/s6 /etc/s6
|
||||||
|
|
||||||
|
VOLUME /data
|
||||||
|
|
||||||
|
ENTRYPOINT ["s6-svscan","/etc/s6"]
|
||||||
|
|
||||||
|
### DIND-ROOTLESS VARIANT
|
||||||
|
#
|
||||||
|
#
|
||||||
|
FROM docker:28-dind-rootless AS dind-rootless
|
||||||
|
|
||||||
|
USER root
|
||||||
|
RUN apk add --no-cache s6 bash git tzdata
|
||||||
|
|
||||||
|
COPY --from=builder /opt/src/act_runner/act_runner /usr/local/bin/act_runner
|
||||||
|
COPY scripts/run.sh /usr/local/bin/run.sh
|
||||||
|
COPY scripts/s6 /etc/s6
|
||||||
|
|
||||||
|
VOLUME /data
|
||||||
|
|
||||||
|
RUN mkdir -p /data && chown -R rootless:rootless /etc/s6 /data
|
||||||
|
|
||||||
|
ENV DOCKER_HOST=unix:///run/user/1000/docker.sock
|
||||||
|
|
||||||
|
USER rootless
|
||||||
|
ENTRYPOINT ["s6-svscan","/etc/s6"]
|
||||||
|
|
||||||
|
### BASIC VARIANT
|
||||||
|
#
|
||||||
|
#
|
||||||
|
FROM alpine AS basic
|
||||||
|
RUN apk add --no-cache tini bash git tzdata
|
||||||
|
|
||||||
|
COPY --from=builder /opt/src/act_runner/act_runner /usr/local/bin/act_runner
|
||||||
|
COPY scripts/run.sh /usr/local/bin/run.sh
|
||||||
|
|
||||||
|
VOLUME /data
|
||||||
|
|
||||||
|
ENTRYPOINT ["/sbin/tini","--","run.sh"]
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
# List of Docker images for `act`
|
|
||||||
|
|
||||||
**Warning:** Below badges with size for each image are displaying size of **compressed image size in registry. After pulling the image, size can be drastically different due to Docker uncompressing the image layers.**
|
|
||||||
|
|
||||||
## Images based on [`buildpack-deps`][hub/_/buildpack-deps]
|
|
||||||
|
|
||||||
**Note 1: `node` images are based on Debian root filesystem, while it is extremely similar to Ubuntu, there might be some differences**
|
|
||||||
|
|
||||||
**Note 2: `node` `-slim` images don't have `python` installed, if you want to use actions or software that is depending on `python`, you need to specify image manually**
|
|
||||||
|
|
||||||
| Image | Size |
|
|
||||||
| ------------------------------------- | ---------------------------------------------------------- |
|
|
||||||
| [`node:16-bullseye`][hub/_/node] | ![`bullseye-size`][hub/_/node/16-bullseye/size] |
|
|
||||||
| [`node:16-bullseye-slim`][hub/_/node] | ![`micro-bullseye-size`][hub/_/node/16-bullseye-slim/size] |
|
|
||||||
| [`node:16-buster`][hub/_/node] | ![`buster-size`][hub/_/node/16-buster/size] |
|
|
||||||
| [`node:16-buster-slim`][hub/_/node] | ![`micro-buster-size`][hub/_/node/16-buster-slim/size] |
|
|
||||||
|
|
||||||
**Note: `catthehacker/ubuntu` images are based on Ubuntu root filesystem**
|
|
||||||
|
|
||||||
| Image | GitHub Repository |
|
|
||||||
| ------------------------------------------------------------ | ------------------------------------------------------------- |
|
|
||||||
| [`catthehacker/ubuntu:act-latest`][ghcr/catthehacker/ubuntu] | [`catthehacker/docker-images`][gh/catthehacker/docker_images] |
|
|
||||||
| [`catthehacker/ubuntu:act-22.04`][ghcr/catthehacker/ubuntu] | [`catthehacker/docker-images`][gh/catthehacker/docker_images] |
|
|
||||||
| [`catthehacker/ubuntu:act-20.04`][ghcr/catthehacker/ubuntu] | [`catthehacker/docker-images`][gh/catthehacker/docker_images] |
|
|
||||||
| [`catthehacker/ubuntu:act-18.04`][ghcr/catthehacker/ubuntu] | [`catthehacker/docker-images`][gh/catthehacker/docker_images] |
|
|
||||||
|
|
||||||
## Images based on [`actions/virtual-environments`][gh/actions/virtual-environments]
|
|
||||||
|
|
||||||
**Note: `nektos/act-environments-ubuntu` have been last updated in February, 2020. It's recommended to update the image manually after `docker pull` if you decide to use it.**
|
|
||||||
|
|
||||||
| Image | Size | GitHub Repository |
|
|
||||||
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
||||||
| [`nektos/act-environments-ubuntu:18.04`][hub/nektos/act-environments-ubuntu] | ![`nektos:18.04`][hub/nektos/act-environments-ubuntu/18.04/size] | [`nektos/act-environments`][gh/nektos/act-environments] |
|
|
||||||
| [`nektos/act-environments-ubuntu:18.04-lite`][hub/nektos/act-environments-ubuntu] | ![`nektos:18.04-lite`][hub/nektos/act-environments-ubuntu/18.04-lite/size] | [`nektos/act-environments`][gh/nektos/act-environments] |
|
|
||||||
| [`nektos/act-environments-ubuntu:18.04-full`][hub/nektos/act-environments-ubuntu] | ![`nektos:18.04-full`][hub/nektos/act-environments-ubuntu/18.04-full/size] | [`nektos/act-environments`][gh/nektos/act-environments] |
|
|
||||||
|
|
||||||
| Image | GitHub Repository |
|
|
||||||
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
||||||
| [`catthehacker/ubuntu:full-latest`][ghcr/catthehacker/ubuntu] | [`catthehacker/virtual-environments-fork`][gh/catthehacker/virtual-environments-fork] |
|
|
||||||
| [`catthehacker/ubuntu:full-20.04`][ghcr/catthehacker/ubuntu] | [`catthehacker/virtual-environments-fork`][gh/catthehacker/virtual-environments-fork] |
|
|
||||||
| [`catthehacker/ubuntu:full-18.04`][ghcr/catthehacker/ubuntu] | [`catthehacker/virtual-environments-fork`][gh/catthehacker/virtual-environments-fork] |
|
|
||||||
|
|
||||||
Feel free to make a pull request with your image added here
|
|
||||||
|
|
||||||
[hub/_/buildpack-deps]: https://hub.docker.com/_/buildpack-deps
|
|
||||||
[hub/_/node]: https://hub.docker.com/r/_/node
|
|
||||||
[hub/_/node/16-bullseye/size]: https://img.shields.io/docker/image-size/_/node/16-bullseye
|
|
||||||
[hub/_/node/16-bullseye-slim/size]: https://img.shields.io/docker/image-size/_/node/16-bullseye-slim
|
|
||||||
[hub/_/node/16-buster/size]: https://img.shields.io/docker/image-size/_/node/16-buster
|
|
||||||
[hub/_/node/16-buster-slim/size]: https://img.shields.io/docker/image-size/_/node/16-buster-slim
|
|
||||||
[ghcr/catthehacker/ubuntu]: https://github.com/catthehacker/docker_images/pkgs/container/ubuntu
|
|
||||||
[hub/nektos/act-environments-ubuntu]: https://hub.docker.com/r/nektos/act-environments-ubuntu
|
|
||||||
[hub/nektos/act-environments-ubuntu/18.04/size]: https://img.shields.io/docker/image-size/nektos/act-environments-ubuntu/18.04
|
|
||||||
[hub/nektos/act-environments-ubuntu/18.04-lite/size]: https://img.shields.io/docker/image-size/nektos/act-environments-ubuntu/18.04-lite
|
|
||||||
[hub/nektos/act-environments-ubuntu/18.04-full/size]: https://img.shields.io/docker/image-size/nektos/act-environments-ubuntu/18.04-full
|
|
||||||
|
|
||||||
<!--
|
|
||||||
[hub/<username>/<image>]: https://hub.docker.com/r/[username]/[image]
|
|
||||||
[hub/<username>/<image>/<tag>/size]: https://img.shields.io/docker/image-size/[username]/[image]/[tag]
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- GitHub repository links -->
|
|
||||||
|
|
||||||
[gh/nektos/act-environments]: https://github.com/nektos/act-environments
|
|
||||||
[gh/actions/virtual-environments]: https://github.com/actions/virtual-environments
|
|
||||||
[gh/catthehacker/docker_images]: https://github.com/catthehacker/docker_images
|
|
||||||
[gh/catthehacker/virtual-environments-fork]: https://github.com/catthehacker/virtual-environments-fork
|
|
||||||
@@ -1,7 +1,4 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2022 The Gitea Authors
|
Copyright (c) 2022 The Gitea Authors
|
||||||
Copyright (c) 2019
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -10,13 +7,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in
|
||||||
copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
SOFTWARE.
|
THE SOFTWARE.
|
||||||
@@ -1,113 +1,209 @@
|
|||||||
PREFIX ?= /usr/local
|
DIST := dist
|
||||||
VERSION ?= $(shell git describe --tags --dirty --always | sed -e 's/^v//')
|
EXECUTABLE := act_runner
|
||||||
IS_SNAPSHOT = $(if $(findstring -, $(VERSION)),true,false)
|
DIST_DIRS := $(DIST)/binaries $(DIST)/release
|
||||||
MAJOR_VERSION = $(word 1, $(subst ., ,$(VERSION)))
|
GO ?= go
|
||||||
MINOR_VERSION = $(word 2, $(subst ., ,$(VERSION)))
|
SHASUM ?= shasum -a 256
|
||||||
PATCH_VERSION = $(word 3, $(subst ., ,$(word 1,$(subst -, , $(VERSION)))))
|
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
||||||
NEW_VERSION ?= $(MAJOR_VERSION).$(MINOR_VERSION).$(shell echo $$(( $(PATCH_VERSION) + 1)) )
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
|
XGO_VERSION := go-1.26.x
|
||||||
|
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/[email protected]
|
||||||
|
|
||||||
fix = false
|
LINUX_ARCHS ?= linux/amd64,linux/arm64
|
||||||
ifeq (true,$(fix))
|
DARWIN_ARCHS ?= darwin-12/amd64,darwin-12/arm64
|
||||||
FIX = --fix
|
WINDOWS_ARCHS ?= windows/amd64
|
||||||
|
GOFILES := $(shell find . -type f -name "*.go" -o -name "go.mod" ! -name "generated.*")
|
||||||
|
|
||||||
|
DOCKER_IMAGE ?= gitea/act_runner
|
||||||
|
DOCKER_TAG ?= nightly
|
||||||
|
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
||||||
|
DOCKER_ROOTLESS_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)-dind-rootless
|
||||||
|
|
||||||
|
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/[email protected]
|
||||||
|
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
|
||||||
|
|
||||||
|
STATIC ?=
|
||||||
|
EXTLDFLAGS ?=
|
||||||
|
ifneq ($(STATIC),)
|
||||||
|
EXTLDFLAGS = -extldflags "-static"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ACT ?= go run main.go
|
ifeq ($(HAS_GO), GO)
|
||||||
|
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||||
|
export PATH := $(GOPATH)/bin:$(PATH)
|
||||||
|
|
||||||
HAS_TOKEN = $(if $(test -e ~/.config/github/token),true,false)
|
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
|
||||||
ifeq (true,$(HAS_TOKEN))
|
CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
|
||||||
export GITHUB_TOKEN := $(shell cat ~/.config/github/token)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: pr
|
ifeq ($(OS), Windows_NT)
|
||||||
pr: tidy format-all lint test
|
GOFLAGS := -v -buildmode=exe
|
||||||
|
EXECUTABLE ?= $(EXECUTABLE).exe
|
||||||
|
else ifeq ($(OS), Windows)
|
||||||
|
GOFLAGS := -v -buildmode=exe
|
||||||
|
EXECUTABLE ?= $(EXECUTABLE).exe
|
||||||
|
else
|
||||||
|
GOFLAGS := -v
|
||||||
|
EXECUTABLE ?= $(EXECUTABLE)
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: build
|
STORED_VERSION_FILE := VERSION
|
||||||
build:
|
|
||||||
go build -ldflags "-X main.version=$(VERSION)" -o dist/local/act main.go
|
|
||||||
|
|
||||||
.PHONY: format
|
ifneq ($(DRONE_TAG),)
|
||||||
format:
|
VERSION ?= $(subst v,,$(DRONE_TAG))
|
||||||
go fmt ./...
|
RELASE_VERSION ?= $(VERSION)
|
||||||
|
else
|
||||||
|
ifneq ($(DRONE_BRANCH),)
|
||||||
|
VERSION ?= $(subst release/v,,$(DRONE_BRANCH))
|
||||||
|
else
|
||||||
|
VERSION ?= main
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: format-all
|
STORED_VERSION=$(shell cat $(STORED_VERSION_FILE) 2>/dev/null)
|
||||||
format-all:
|
ifneq ($(STORED_VERSION),)
|
||||||
go fmt ./...
|
RELASE_VERSION ?= $(STORED_VERSION)
|
||||||
npx prettier --write .
|
else
|
||||||
|
RELASE_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: test
|
TAGS ?=
|
||||||
test:
|
LDFLAGS ?= -X "gitea.com/gitea/act_runner/internal/pkg/ver.version=v$(RELASE_VERSION)"
|
||||||
go test ./...
|
|
||||||
$(ACT)
|
|
||||||
|
|
||||||
.PHONY: lint-go
|
.PHONY: all
|
||||||
lint-go:
|
all: build
|
||||||
golangci-lint run $(FIX)
|
|
||||||
|
|
||||||
.PHONY: lint-js
|
.PHONY: help
|
||||||
lint-js:
|
help: Makefile ## print Makefile help information.
|
||||||
npx standard $(FIX)
|
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m[TARGETS] default target: build\033[0m\n\n\033[35mTargets:\033[0m\n"} /^[0-9A-Za-z._-]+:.*?##/ { printf " \033[36m%-45s\033[0m %s\n", $$1, $$2 }' Makefile
|
||||||
|
|
||||||
.PHONY: lint-md
|
.PHONY: fmt
|
||||||
lint-md:
|
fmt: ## format the Go code
|
||||||
npx markdownlint . $(FIX)
|
$(GO) run $(GOLANGCI_LINT_PACKAGE) fmt
|
||||||
|
|
||||||
.PHONY: lint-rest
|
.PHONY: go-check
|
||||||
lint-rest:
|
go-check:
|
||||||
docker run --rm -it \
|
$(eval MIN_GO_VERSION_STR := $(shell grep -Eo '^go\s+[0-9]+\.[0-9]+' go.mod | cut -d' ' -f2))
|
||||||
-v $(PWD):/tmp/lint \
|
$(eval MIN_GO_VERSION := $(shell printf "%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' ')))
|
||||||
-e GITHUB_STATUS_REPORTER=false \
|
$(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');))
|
||||||
-e GITHUB_COMMENT_REPORTER=false \
|
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
|
||||||
megalinter/megalinter-go:v5
|
echo "Act Runner requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: fmt-check
|
||||||
|
fmt-check: fmt
|
||||||
|
@diff=$$(git diff --color=always); \
|
||||||
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "Please run 'make fmt' and commit the result:"; \
|
||||||
|
printf "%s" "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: deps-tools
|
||||||
|
deps-tools: ## install tool dependencies
|
||||||
|
$(GO) install $(GOLANGCI_LINT_PACKAGE) & \
|
||||||
|
$(GO) install $(GXZ_PACKAGE) & \
|
||||||
|
$(GO) install $(XGO_PACKAGE) & \
|
||||||
|
$(GO) install $(GOVULNCHECK_PACKAGE) & \
|
||||||
|
wait
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: lint-go lint-rest
|
lint: lint-go ## lint everything
|
||||||
|
|
||||||
.PHONY: lint-fix
|
.PHONY: lint-go
|
||||||
lint-fix: lint-md lint-go
|
lint-go: ## lint go files
|
||||||
|
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
|
||||||
|
|
||||||
.PHONY: fix
|
.PHONY: lint-go-fix
|
||||||
fix:
|
lint-go-fix: ## lint go files and fix issues
|
||||||
make lint-fix fix=true
|
$(GO) run $(GOLANGCI_LINT_PACKAGE) run --fix
|
||||||
|
|
||||||
|
.PHONY: security-check
|
||||||
|
security-check: deps-tools
|
||||||
|
GOEXPERIMENT= $(GO) run $(GOVULNCHECK_PACKAGE) -show color ./... || true
|
||||||
|
|
||||||
.PHONY: tidy
|
.PHONY: tidy
|
||||||
tidy:
|
tidy: ## run go mod tidy
|
||||||
go mod tidy
|
$(GO) mod tidy
|
||||||
|
|
||||||
|
.PHONY: tidy-check
|
||||||
|
tidy-check: tidy
|
||||||
|
@diff=$$(git diff --color=always -- go.mod go.sum); \
|
||||||
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "Please run 'make tidy' and commit the result:"; \
|
||||||
|
printf "%s" "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: fmt-check security-check ## test everything
|
||||||
|
@$(GO) test -race -short -v -cover -coverprofile coverage.txt ./... && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
||||||
|
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
install: build
|
install: $(GOFILES) ## install the act_runner binary via `go install`
|
||||||
@cp dist/local/act $(PREFIX)/bin/act
|
$(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(EXTLDFLAGS) $(LDFLAGS)'
|
||||||
@chmod 755 $(PREFIX)/bin/act
|
|
||||||
@act --version
|
|
||||||
|
|
||||||
.PHONY: installer
|
.PHONY: build
|
||||||
installer:
|
build: go-check $(EXECUTABLE) ## build the act_runner binary
|
||||||
@GO111MODULE=off go get github.com/goreleaser/godownloader
|
|
||||||
godownloader -r nektos/act -o install.sh
|
|
||||||
|
|
||||||
.PHONY: promote
|
$(EXECUTABLE): $(GOFILES)
|
||||||
promote:
|
$(GO) build -v -tags '$(TAGS)' -ldflags '-s -w $(EXTLDFLAGS) $(LDFLAGS)' -o $@
|
||||||
@git fetch --tags
|
|
||||||
@echo "VERSION:$(VERSION) IS_SNAPSHOT:$(IS_SNAPSHOT) NEW_VERSION:$(NEW_VERSION)"
|
.PHONY: deps-backend
|
||||||
ifeq (false,$(IS_SNAPSHOT))
|
deps-backend: ## install backend dependencies
|
||||||
@echo "Unable to promote a non-snapshot"
|
$(GO) mod download
|
||||||
@exit 1
|
|
||||||
|
.PHONY: release
|
||||||
|
release: release-windows release-linux release-darwin release-copy release-compress release-check ## build release artifacts
|
||||||
|
|
||||||
|
$(DIST_DIRS):
|
||||||
|
mkdir -p $(DIST_DIRS)
|
||||||
|
|
||||||
|
.PHONY: release-windows
|
||||||
|
release-windows: | $(DIST_DIRS)
|
||||||
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(WINDOWS_ARCHS)' -out $(EXECUTABLE)-$(VERSION) .
|
||||||
|
ifeq ($(CI),true)
|
||||||
|
cp -r /build/* $(DIST)/binaries/
|
||||||
endif
|
endif
|
||||||
ifneq ($(shell git status -s),)
|
|
||||||
@echo "Unable to promote a dirty workspace"
|
.PHONY: release-linux
|
||||||
@exit 1
|
release-linux: | $(DIST_DIRS)
|
||||||
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out $(EXECUTABLE)-$(VERSION) .
|
||||||
|
ifeq ($(CI),true)
|
||||||
|
cp -r /build/* $(DIST)/binaries/
|
||||||
endif
|
endif
|
||||||
echo -n $(NEW_VERSION) > VERSION
|
|
||||||
git add VERSION
|
|
||||||
git commit -m "chore: bump VERSION to $(NEW_VERSION)"
|
|
||||||
git tag -a -m "releasing v$(NEW_VERSION)" v$(NEW_VERSION)
|
|
||||||
git push origin master
|
|
||||||
git push origin v$(NEW_VERSION)
|
|
||||||
|
|
||||||
.PHONY: snapshot
|
.PHONY: release-darwin
|
||||||
snapshot:
|
release-darwin: | $(DIST_DIRS)
|
||||||
goreleaser build \
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w $(LDFLAGS)' -targets '$(DARWIN_ARCHS)' -out $(EXECUTABLE)-$(VERSION) .
|
||||||
--clean \
|
ifeq ($(CI),true)
|
||||||
--single-target \
|
cp -r /build/* $(DIST)/binaries/
|
||||||
--snapshot
|
endif
|
||||||
|
|
||||||
.PHONY: clean all
|
.PHONY: release-copy
|
||||||
|
release-copy: | $(DIST_DIRS)
|
||||||
|
cd $(DIST); for file in `find . -type f -name "*"`; do cp $${file} ./release/; done;
|
||||||
|
|
||||||
|
.PHONY: release-check
|
||||||
|
release-check: | $(DIST_DIRS)
|
||||||
|
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "checksumming $${file}" && $(SHASUM) `echo $${file} | sed 's/^..//'` > $${file}.sha256; done;
|
||||||
|
|
||||||
|
.PHONY: release-compress
|
||||||
|
release-compress: | $(DIST_DIRS)
|
||||||
|
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && $(GO) run $(GXZ_PACKAGE) -k -9 $${file}; done;
|
||||||
|
|
||||||
|
.PHONY: docker
|
||||||
|
docker: ## build the docker image
|
||||||
|
if ! docker buildx version >/dev/null 2>&1; then \
|
||||||
|
ARG_DISABLE_CONTENT_TRUST=--disable-content-trust=false; \
|
||||||
|
fi; \
|
||||||
|
docker build $${ARG_DISABLE_CONTENT_TRUST} -t $(DOCKER_REF) .
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean: ## delete binary and coverage files
|
||||||
|
$(GO) clean -x -i ./...
|
||||||
|
rm -rf coverage.txt $(EXECUTABLE) $(DIST)
|
||||||
|
|
||||||
|
.PHONY: version
|
||||||
|
version: ## print the version
|
||||||
|
@echo $(VERSION)
|
||||||
@@ -1,62 +1,108 @@
|
|||||||
## Forking rules
|
# act runner
|
||||||
|
|
||||||
This is a custom fork of [nektos/act](https://github.com/nektos/act/), for the purpose of serving [act_runner](https://gitea.com/gitea/act_runner).
|
Act runner is a runner for Gitea.
|
||||||
|
|
||||||
It cannot be used as command line tool anymore, but only as a library.
|
## Installation
|
||||||
|
|
||||||
It's a soft fork, which means that it will track the latest release of nektos/act.
|
### Prerequisites
|
||||||
|
|
||||||
Branches:
|
Docker Engine Community version is required for docker mode. To install Docker CE, follow the official [install instructions](https://docs.docker.com/engine/install/).
|
||||||
|
|
||||||
- `main`: default branch, contains custom changes, based on the latest release(not the latest of the master branch) of nektos/act.
|
### Download pre-built binary
|
||||||
- `nektos/master`: mirror for the master branch of nektos/act.
|
|
||||||
|
|
||||||
Tags:
|
Visit [here](https://dl.gitea.com/act_runner/) and download the right version for your platform.
|
||||||
|
|
||||||
- `nektos/vX.Y.Z`: mirror for `vX.Y.Z` of [nektos/act](https://github.com/nektos/act/).
|
### Build from source
|
||||||
- `vX.YZ.*`: based on `nektos/vX.Y.Z`, contains custom changes.
|
|
||||||
- Examples:
|
|
||||||
- `nektos/v0.2.23` -> `v0.223.*`
|
|
||||||
- `nektos/v0.3.1` -> `v0.301.*`, not ~~`v0.31.*`~~
|
|
||||||
- `nektos/v0.10.1` -> `v0.1001.*`, not ~~`v0.101.*`~~
|
|
||||||
- `nektos/v0.3.100` -> not ~~`v0.3100.*`~~, I don't think it's really going to happen, if it does, we can find a way to handle it.
|
|
||||||
|
|
||||||
---
|
```bash
|
||||||
|
make build
|
||||||
|
```
|
||||||
|
|
||||||

|
### Build a docker image
|
||||||
|
|
||||||
# Overview [](https://github.com/nektos/act/actions) [](https://gitter.im/nektos/act?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://goreportcard.com/report/github.com/nektos/act) [](https://github.com/jonico/awesome-runners)
|
```bash
|
||||||
|
make docker
|
||||||
|
```
|
||||||
|
|
||||||
> "Think globally, `act` locally"
|
## Quickstart
|
||||||
|
|
||||||
Run your [GitHub Actions](https://developer.github.com/actions/) locally! Why would you want to do this? Two reasons:
|
Actions are disabled by default, so you need to add the following to the configuration file of your Gitea instance to enable it:
|
||||||
|
|
||||||
- **Fast Feedback** - Rather than having to commit/push every time you want to test out the changes you are making to your `.github/workflows/` files (or for any changes to embedded GitHub actions), you can use `act` to run the actions locally. The [environment variables](https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables) and [filesystem](https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners#filesystems-on-github-hosted-runners) are all configured to match what GitHub provides.
|
```ini
|
||||||
- **Local Task Runner** - I love [make](<https://en.wikipedia.org/wiki/Make_(software)>). However, I also hate repeating myself. With `act`, you can use the GitHub Actions defined in your `.github/workflows/` to replace your `Makefile`!
|
[actions]
|
||||||
|
ENABLED=true
|
||||||
|
```
|
||||||
|
|
||||||
# How Does It Work?
|
### Register
|
||||||
|
|
||||||
When you run `act` it reads in your GitHub Actions from `.github/workflows/` and determines the set of actions that need to be run. It uses the Docker API to either pull or build the necessary images, as defined in your workflow files and finally determines the execution path based on the dependencies that were defined. Once it has the execution path, it then uses the Docker API to run containers for each action based on the images prepared earlier. The [environment variables](https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables) and [filesystem](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#file-systems) are all configured to match what GitHub provides.
|
```bash
|
||||||
|
./act_runner register
|
||||||
|
```
|
||||||
|
|
||||||
Let's see it in action with a [sample repo](https://github.com/cplee/github-actions-demo)!
|
And you will be asked to input:
|
||||||
|
|
||||||

|
1. Gitea instance URL, like `http://192.168.8.8:3000/`. You should use your gitea instance ROOT_URL as the instance argument
|
||||||
|
and you should not use `localhost` or `127.0.0.1` as instance IP;
|
||||||
|
2. Runner token, you can get it from `http://192.168.8.8:3000/admin/actions/runners`;
|
||||||
|
3. Runner name, you can just leave it blank;
|
||||||
|
4. Runner labels, you can just leave it blank.
|
||||||
|
|
||||||
# Act User Guide
|
The process looks like:
|
||||||
|
|
||||||
Please look at the [act user guide](https://nektosact.com) for more documentation.
|
```text
|
||||||
|
INFO Registering runner, arch=amd64, os=darwin, version=0.1.5.
|
||||||
|
WARN Runner in user-mode.
|
||||||
|
INFO Enter the Gitea instance URL (for example, https://gitea.com/):
|
||||||
|
http://192.168.8.8:3000/
|
||||||
|
INFO Enter the runner token:
|
||||||
|
fe884e8027dc292970d4e0303fe82b14xxxxxxxx
|
||||||
|
INFO Enter the runner name (if set empty, use hostname: Test.local):
|
||||||
|
|
||||||
# Support
|
INFO Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest):
|
||||||
|
|
||||||
Need help? Ask on [Gitter](https://gitter.im/nektos/act)!
|
INFO Registering runner, name=Test.local, instance=http://192.168.8.8:3000/, labels=[ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04 ubuntu-20.04:docker://docker.gitea.com/runner-images:ubuntu-20.04].
|
||||||
|
DEBU Successfully pinged the Gitea instance server
|
||||||
|
INFO Runner registered successfully.
|
||||||
|
```
|
||||||
|
|
||||||
# Contributing
|
You can also register with command line arguments.
|
||||||
|
|
||||||
Want to contribute to act? Awesome! Check out the [contributing guidelines](CONTRIBUTING.md) to get involved.
|
```bash
|
||||||
|
./act_runner register --instance http://192.168.8.8:3000 --token <my_runner_token> --no-interactive
|
||||||
|
```
|
||||||
|
|
||||||
## Manually building from source
|
If the registry succeed, it will run immediately. Next time, you could run the runner directly.
|
||||||
|
|
||||||
- Install Go tools 1.20+ - (<https://golang.org/doc/install>)
|
### Run
|
||||||
- Clone this repo `git clone [email protected]:nektos/act.git`
|
|
||||||
- Run unit tests with `make test`
|
```bash
|
||||||
- Build and install: `make install`
|
./act_runner daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run with docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -e GITEA_INSTANCE_URL=https://your_gitea.com -e GITEA_RUNNER_REGISTRATION_TOKEN=<your_token> -v /var/run/docker.sock:/var/run/docker.sock --name my_runner gitea/act_runner:nightly
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
You can also configure the runner with a configuration file.
|
||||||
|
The configuration file is a YAML file, you can generate a sample configuration file with `./act_runner generate-config`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./act_runner generate-config > config.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
You can specify the configuration file path with `-c`/`--config` argument.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./act_runner -c config.yaml register # register with config file
|
||||||
|
./act_runner -c config.yaml daemon # run with config file
|
||||||
|
```
|
||||||
|
|
||||||
|
You can read the latest version of the configuration file online at [config.example.yaml](internal/pkg/config/config.example.yaml).
|
||||||
|
|
||||||
|
### Example Deployments
|
||||||
|
|
||||||
|
Check out the [examples](examples) directory for sample deployment types.
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
VERIFICATION
|
|
||||||
Verification is intended to assist the Chocolatey moderators and community
|
|
||||||
in verifying that this package's contents are trustworthy.
|
|
||||||
|
|
||||||
Checksums: https://github.com/nektos/act/releases, in the checksums.txt file
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Do not remove this test for UTF-8: if “Ω” doesn’t appear as greek uppercase omega letter enclosed in quotation marks, you should use an editor that supports UTF-8, not this one. -->
|
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
|
||||||
<metadata>
|
|
||||||
<id>act-cli</id>
|
|
||||||
<version>0.0.0</version>
|
|
||||||
<packageSourceUrl>https://github.com/nektos/act</packageSourceUrl>
|
|
||||||
<owners>nektos</owners>
|
|
||||||
<title>act (GitHub Actions CLI)</title>
|
|
||||||
<authors>nektos</authors>
|
|
||||||
<projectUrl>https://github.com/nektos/act</projectUrl>
|
|
||||||
<iconUrl>https://raw.githubusercontent.com/wiki/nektos/act/img/logo-150.png</iconUrl>
|
|
||||||
<copyright>Nektos</copyright>
|
|
||||||
<licenseUrl>https://raw.githubusercontent.com/nektos/act/master/LICENSE</licenseUrl>
|
|
||||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
|
||||||
<projectSourceUrl>https://github.com/nektos/act</projectSourceUrl>
|
|
||||||
<docsUrl>https://raw.githubusercontent.com/nektos/act/master/README.md</docsUrl>
|
|
||||||
<bugTrackerUrl>https://github.com/nektos/act/issues</bugTrackerUrl>
|
|
||||||
<tags>act github-actions actions golang ci devops</tags>
|
|
||||||
<summary>Run your GitHub Actions locally 🚀</summary>
|
|
||||||
<description>Run your GitHub Actions locally 🚀</description>
|
|
||||||
</metadata>
|
|
||||||
<files>
|
|
||||||
<file src="tools/**" target="tools" />
|
|
||||||
</files>
|
|
||||||
</package>
|
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 The Gitea Authors
|
||||||
|
Copyright (c) 2019
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2023 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
// Package artifactcache provides a cache handler for the runner.
|
// Package artifactcache provides a cache handler for the runner.
|
||||||
//
|
//
|
||||||
// Inspired by https://github.com/sp-ricard-valverde/github-act-cache-server
|
// Inspired by https://github.com/sp-ricard-valverde/github-act-cache-server
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2023 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package artifactcache
|
package artifactcache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -15,12 +19,12 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/timshannon/bolthold"
|
"github.com/timshannon/bolthold"
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -74,7 +78,7 @@ func StartHandler(dir, outboundIP string, port uint16, logger logrus.FieldLogger
|
|||||||
if outboundIP != "" {
|
if outboundIP != "" {
|
||||||
h.outboundIP = outboundIP
|
h.outboundIP = outboundIP
|
||||||
} else if ip := common.GetOutboundIP(); ip == nil {
|
} else if ip := common.GetOutboundIP(); ip == nil {
|
||||||
return nil, fmt.Errorf("unable to determine outbound IP address")
|
return nil, errors.New("unable to determine outbound IP address")
|
||||||
} else {
|
} else {
|
||||||
h.outboundIP = ip.String()
|
h.outboundIP = ip.String()
|
||||||
}
|
}
|
||||||
@@ -363,7 +367,7 @@ func findCache(db *bolthold.Store, keys []string, version string) (*Cache, error
|
|||||||
}
|
}
|
||||||
return cache, nil
|
return cache, nil
|
||||||
}
|
}
|
||||||
prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix))
|
prefixPattern := "^" + regexp.QuoteMeta(prefix)
|
||||||
re, err := regexp.Compile(prefixPattern)
|
re, err := regexp.Compile(prefixPattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
@@ -380,7 +384,7 @@ func findCache(db *bolthold.Store, keys []string, version string) (*Cache, error
|
|||||||
}
|
}
|
||||||
return cache, nil
|
return cache, nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil //nolint:nilnil // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
|
|
||||||
func insertCache(db *bolthold.Store, cache *Cache) error {
|
func insertCache(db *bolthold.Store, cache *Cache) error {
|
||||||
@@ -415,6 +419,7 @@ const (
|
|||||||
keepOld = 5 * time.Minute
|
keepOld = 5 * time.Minute
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint:gocyclo // function handles many cases
|
||||||
func (h *Handler) gcCache() {
|
func (h *Handler) gcCache() {
|
||||||
if h.gcing.Load() {
|
if h.gcing.Load() {
|
||||||
return
|
return
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2023 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package artifactcache
|
package artifactcache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -41,7 +45,7 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, handler.Close())
|
require.NoError(t, handler.Close())
|
||||||
assert.Nil(t, handler.server)
|
assert.Nil(t, handler.server)
|
||||||
assert.Nil(t, handler.listener)
|
assert.Nil(t, handler.listener)
|
||||||
_, err := http.Post(fmt.Sprintf("%s/caches/%d", base, 1), "", nil)
|
_, err := http.Post(fmt.Sprintf("%s/caches/%d", base, 1), "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
@@ -49,7 +53,7 @@ func TestHandler(t *testing.T) {
|
|||||||
t.Run("get not exist", func(t *testing.T) {
|
t.Run("get not exist", func(t *testing.T) {
|
||||||
key := strings.ToLower(t.Name())
|
key := strings.ToLower(t.Name())
|
||||||
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20"
|
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20"
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
|
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 204, resp.StatusCode)
|
require.Equal(t, 204, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -64,7 +68,7 @@ func TestHandler(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("clean", func(t *testing.T) {
|
t.Run("clean", func(t *testing.T) {
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/clean", base), "", nil)
|
resp, err := http.Post(base+"/clean", "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -72,7 +76,7 @@ func TestHandler(t *testing.T) {
|
|||||||
t.Run("reserve with bad request", func(t *testing.T) {
|
t.Run("reserve with bad request", func(t *testing.T) {
|
||||||
body := []byte(`invalid json`)
|
body := []byte(`invalid json`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -90,7 +94,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -104,7 +108,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -117,11 +121,11 @@ func TestHandler(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("upload with bad id", func(t *testing.T) {
|
t.Run("upload with bad id", func(t *testing.T) {
|
||||||
req, err := http.NewRequest(http.MethodPatch,
|
req, err := http.NewRequest(http.MethodPatch,
|
||||||
fmt.Sprintf("%s/caches/invalid_id", base), bytes.NewReader(nil))
|
base+"/caches/invalid_id", bytes.NewReader(nil))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -132,7 +136,7 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -151,7 +155,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -167,12 +171,12 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
}
|
}
|
||||||
@@ -182,7 +186,7 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
}
|
}
|
||||||
@@ -202,7 +206,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -218,7 +222,7 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes xx-99/*")
|
req.Header.Set("Content-Range", "bytes xx-99/*")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
}
|
}
|
||||||
@@ -226,7 +230,7 @@ func TestHandler(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("commit with bad id", func(t *testing.T) {
|
t.Run("commit with bad id", func(t *testing.T) {
|
||||||
{
|
{
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches/invalid_id", base), "", nil)
|
resp, err := http.Post(base+"/caches/invalid_id", "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
}
|
}
|
||||||
@@ -234,7 +238,7 @@ func TestHandler(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("commit with not exist id", func(t *testing.T) {
|
t.Run("commit with not exist id", func(t *testing.T) {
|
||||||
{
|
{
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, 100), "", nil)
|
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, 100), "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
}
|
}
|
||||||
@@ -254,7 +258,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -270,17 +274,17 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 400, resp.StatusCode)
|
assert.Equal(t, 400, resp.StatusCode)
|
||||||
}
|
}
|
||||||
@@ -300,7 +304,7 @@ func TestHandler(t *testing.T) {
|
|||||||
Size: 100,
|
Size: 100,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -316,31 +320,31 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes 0-59/*")
|
req.Header.Set("Content-Range", "bytes 0-59/*")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 500, resp.StatusCode)
|
assert.Equal(t, 500, resp.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get with bad id", func(t *testing.T) {
|
t.Run("get with bad id", func(t *testing.T) {
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/artifacts/invalid_id", base))
|
resp, err := http.Get(base + "/artifacts/invalid_id") //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 400, resp.StatusCode)
|
require.Equal(t, 400, resp.StatusCode)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get with not exist id", func(t *testing.T) {
|
t.Run("get with not exist id", func(t *testing.T) {
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/artifacts/%d", base, 100))
|
resp, err := http.Get(fmt.Sprintf("%s/artifacts/%d", base, 100)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 404, resp.StatusCode)
|
require.Equal(t, 404, resp.StatusCode)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get with not exist id", func(t *testing.T) {
|
t.Run("get with not exist id", func(t *testing.T) {
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/artifacts/%d", base, 100))
|
resp, err := http.Get(fmt.Sprintf("%s/artifacts/%d", base, 100)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 404, resp.StatusCode)
|
require.Equal(t, 404, resp.StatusCode)
|
||||||
})
|
})
|
||||||
@@ -371,7 +375,7 @@ func TestHandler(t *testing.T) {
|
|||||||
key + "_a",
|
key + "_a",
|
||||||
}, ",")
|
}, ",")
|
||||||
|
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version))
|
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, resp.StatusCode)
|
require.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -391,7 +395,7 @@ func TestHandler(t *testing.T) {
|
|||||||
assert.Equal(t, "hit", got.Result)
|
assert.Equal(t, "hit", got.Result)
|
||||||
assert.Equal(t, keys[except], got.CacheKey)
|
assert.Equal(t, keys[except], got.CacheKey)
|
||||||
|
|
||||||
contentResp, err := http.Get(got.ArchiveLocation)
|
contentResp, err := http.Get(got.ArchiveLocation) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, contentResp.StatusCode)
|
require.Equal(t, 200, contentResp.StatusCode)
|
||||||
content, err := io.ReadAll(contentResp.Body)
|
content, err := io.ReadAll(contentResp.Body)
|
||||||
@@ -409,7 +413,7 @@ func TestHandler(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
reqKey := key + "_aBc"
|
reqKey := key + "_aBc"
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKey, version))
|
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKey, version)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, resp.StatusCode)
|
require.Equal(t, 200, resp.StatusCode)
|
||||||
got := struct {
|
got := struct {
|
||||||
@@ -448,7 +452,7 @@ func TestHandler(t *testing.T) {
|
|||||||
key + "_a_b",
|
key + "_a_b",
|
||||||
}, ",")
|
}, ",")
|
||||||
|
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version))
|
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, resp.StatusCode)
|
require.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -466,7 +470,7 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
|
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
|
||||||
assert.Equal(t, keys[expect], got.CacheKey)
|
assert.Equal(t, keys[expect], got.CacheKey)
|
||||||
|
|
||||||
contentResp, err := http.Get(got.ArchiveLocation)
|
contentResp, err := http.Get(got.ArchiveLocation) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, contentResp.StatusCode)
|
require.Equal(t, 200, contentResp.StatusCode)
|
||||||
content, err := io.ReadAll(contentResp.Body)
|
content, err := io.ReadAll(contentResp.Body)
|
||||||
@@ -500,7 +504,7 @@ func TestHandler(t *testing.T) {
|
|||||||
key + "_a_b",
|
key + "_a_b",
|
||||||
}, ",")
|
}, ",")
|
||||||
|
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version))
|
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, resp.StatusCode)
|
require.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -519,7 +523,7 @@ func TestHandler(t *testing.T) {
|
|||||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
|
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
|
||||||
assert.Equal(t, keys[expect], got.CacheKey)
|
assert.Equal(t, keys[expect], got.CacheKey)
|
||||||
|
|
||||||
contentResp, err := http.Get(got.ArchiveLocation)
|
contentResp, err := http.Get(got.ArchiveLocation) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, contentResp.StatusCode)
|
require.Equal(t, 200, contentResp.StatusCode)
|
||||||
content, err := io.ReadAll(contentResp.Body)
|
content, err := io.ReadAll(contentResp.Body)
|
||||||
@@ -528,7 +532,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 // pre-existing issue from nektos/act
|
||||||
var id uint64
|
var id uint64
|
||||||
{
|
{
|
||||||
body, err := json.Marshal(&Request{
|
body, err := json.Marshal(&Request{
|
||||||
@@ -537,7 +541,7 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte
|
|||||||
Size: int64(len(content)),
|
Size: int64(len(content)),
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
|
resp, err := http.Post(base+"/caches", "application/json", bytes.NewReader(body)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
@@ -553,18 +557,18 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
req.Header.Set("Content-Type", "application/octet-stream")
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
req.Header.Set("Content-Range", "bytes 0-99/*")
|
req.Header.Set("Content-Range", "bytes 0-99/*")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
|
resp, err := http.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 200, resp.StatusCode)
|
assert.Equal(t, 200, resp.StatusCode)
|
||||||
}
|
}
|
||||||
var archiveLocation string
|
var archiveLocation string
|
||||||
{
|
{
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
|
resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version)) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, resp.StatusCode)
|
require.Equal(t, 200, resp.StatusCode)
|
||||||
got := struct {
|
got := struct {
|
||||||
@@ -578,7 +582,7 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte
|
|||||||
archiveLocation = got.ArchiveLocation
|
archiveLocation = got.ArchiveLocation
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
resp, err := http.Get(archiveLocation) //nolint:gosec
|
resp, err := http.Get(archiveLocation) //nolint:bodyclose // pre-existing issue from nektos/act
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 200, resp.StatusCode)
|
require.Equal(t, 200, resp.StatusCode)
|
||||||
got, err := io.ReadAll(resp.Body)
|
got, err := io.ReadAll(resp.Body)
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2023 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package artifactcache
|
package artifactcache
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2023 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package artifactcache
|
package artifactcache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -6,6 +10,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Storage struct {
|
type Storage struct {
|
||||||
@@ -103,11 +108,11 @@ func (s *Storage) Remove(id uint64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) filename(id uint64) string {
|
func (s *Storage) filename(id uint64) string {
|
||||||
return filepath.Join(s.rootDir, fmt.Sprintf("%02x", id%0xff), fmt.Sprint(id))
|
return filepath.Join(s.rootDir, fmt.Sprintf("%02x", id%0xff), strconv.FormatUint(id, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) tempDir(id uint64) string {
|
func (s *Storage) tempDir(id uint64) string {
|
||||||
return filepath.Join(s.rootDir, "tmp", fmt.Sprint(id))
|
return filepath.Join(s.rootDir, "tmp", strconv.FormatUint(id, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) tempName(id uint64, offset int64) string {
|
func (s *Storage) tempName(id uint64, offset int64) string {
|
||||||
Vendored
File renamed without changes.
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2021 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package artifacts
|
package artifacts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -13,9 +17,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/julienschmidt/httprouter"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileContainerResourceURL struct {
|
type FileContainerResourceURL struct {
|
||||||
@@ -55,8 +59,7 @@ type WriteFS interface {
|
|||||||
OpenAppendable(name string) (WritableFile, error)
|
OpenAppendable(name string) (WritableFile, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type readWriteFSImpl struct {
|
type readWriteFSImpl struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func (fwfs readWriteFSImpl) Open(name string) (fs.File, error) {
|
func (fwfs readWriteFSImpl) Open(name string) (fs.File, error) {
|
||||||
return os.Open(name)
|
return os.Open(name)
|
||||||
@@ -74,7 +77,6 @@ func (fwfs readWriteFSImpl) OpenAppendable(name string) (WritableFile, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
file, err := os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0o644)
|
file, err := os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0o644)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -88,7 +90,7 @@ func (fwfs readWriteFSImpl) OpenAppendable(name string) (WritableFile, error) {
|
|||||||
|
|
||||||
var gzipExtension = ".gz__"
|
var gzipExtension = ".gz__"
|
||||||
|
|
||||||
func safeResolve(baseDir string, relPath string) string {
|
func safeResolve(baseDir, relPath string) string {
|
||||||
return filepath.Join(baseDir, filepath.Clean(filepath.Join(string(os.PathSeparator), relPath)))
|
return filepath.Join(baseDir, filepath.Clean(filepath.Join(string(os.PathSeparator), relPath)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +129,6 @@ func uploads(router *httprouter.Router, baseDir string, fsys WriteFS) {
|
|||||||
}
|
}
|
||||||
return fsys.OpenWritable(safePath)
|
return fsys.OpenWritable(safePath)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -275,7 +276,7 @@ func downloads(router *httprouter.Router, baseDir string, fsys fs.FS) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Serve(ctx context.Context, artifactPath string, addr string, port string) context.CancelFunc {
|
func Serve(ctx context.Context, artifactPath, addr, port string) context.CancelFunc {
|
||||||
serverContext, cancel := context.WithCancel(ctx)
|
serverContext, cancel := context.WithCancel(ctx)
|
||||||
logger := common.Logger(serverContext)
|
logger := common.Logger(serverContext)
|
||||||
|
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2021 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package artifacts
|
package artifacts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -13,12 +17,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"testing/fstest"
|
"testing/fstest"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/model"
|
||||||
|
"gitea.com/gitea/act_runner/act/runner"
|
||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/model"
|
|
||||||
"github.com/nektos/act/pkg/runner"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type writableMapFile struct {
|
type writableMapFile struct {
|
||||||
@@ -39,7 +43,7 @@ type writeMapFS struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fsys writeMapFS) OpenWritable(name string) (WritableFile, error) {
|
func (fsys writeMapFS) OpenWritable(name string) (WritableFile, error) {
|
||||||
var file = &writableMapFile{
|
file := &writableMapFile{
|
||||||
MapFile: fstest.MapFile{
|
MapFile: fstest.MapFile{
|
||||||
Data: []byte("content2"),
|
Data: []byte("content2"),
|
||||||
},
|
},
|
||||||
@@ -50,7 +54,7 @@ func (fsys writeMapFS) OpenWritable(name string) (WritableFile, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fsys writeMapFS) OpenAppendable(name string) (WritableFile, error) {
|
func (fsys writeMapFS) OpenAppendable(name string) (WritableFile, error) {
|
||||||
var file = &writableMapFile{
|
file := &writableMapFile{
|
||||||
MapFile: fstest.MapFile{
|
MapFile: fstest.MapFile{
|
||||||
Data: []byte("content2"),
|
Data: []byte("content2"),
|
||||||
},
|
},
|
||||||
@@ -63,12 +67,12 @@ func (fsys writeMapFS) OpenAppendable(name string) (WritableFile, error) {
|
|||||||
func TestNewArtifactUploadPrepare(t *testing.T) {
|
func TestNewArtifactUploadPrepare(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{})
|
memfs := fstest.MapFS(map[string]*fstest.MapFile{})
|
||||||
|
|
||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
||||||
|
|
||||||
req, _ := http.NewRequest("POST", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
req, _ := http.NewRequest(http.MethodPost, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -89,12 +93,12 @@ func TestNewArtifactUploadPrepare(t *testing.T) {
|
|||||||
func TestArtifactUploadBlob(t *testing.T) {
|
func TestArtifactUploadBlob(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{})
|
memfs := fstest.MapFS(map[string]*fstest.MapFile{})
|
||||||
|
|
||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
||||||
|
|
||||||
req, _ := http.NewRequest("PUT", "http://localhost/upload/1?itemPath=some/file", strings.NewReader("content"))
|
req, _ := http.NewRequest(http.MethodPut, "http://localhost/upload/1?itemPath=some/file", strings.NewReader("content"))
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -116,12 +120,12 @@ func TestArtifactUploadBlob(t *testing.T) {
|
|||||||
func TestFinalizeArtifactUpload(t *testing.T) {
|
func TestFinalizeArtifactUpload(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{})
|
memfs := fstest.MapFS(map[string]*fstest.MapFile{})
|
||||||
|
|
||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
||||||
|
|
||||||
req, _ := http.NewRequest("PATCH", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
req, _ := http.NewRequest(http.MethodPatch, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -142,7 +146,7 @@ func TestFinalizeArtifactUpload(t *testing.T) {
|
|||||||
func TestListArtifacts(t *testing.T) {
|
func TestListArtifacts(t *testing.T) {
|
||||||
assert := assert.New(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": {
|
"artifact/server/path/1/file.txt": {
|
||||||
Data: []byte(""),
|
Data: []byte(""),
|
||||||
},
|
},
|
||||||
@@ -151,7 +155,7 @@ func TestListArtifacts(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
downloads(router, "artifact/server/path", memfs)
|
downloads(router, "artifact/server/path", memfs)
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
req, _ := http.NewRequest(http.MethodGet, "http://localhost/_apis/pipelines/workflows/1/artifacts", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -174,7 +178,7 @@ func TestListArtifacts(t *testing.T) {
|
|||||||
func TestListArtifactContainer(t *testing.T) {
|
func TestListArtifactContainer(t *testing.T) {
|
||||||
assert := assert.New(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": {
|
"artifact/server/path/1/some/file": {
|
||||||
Data: []byte(""),
|
Data: []byte(""),
|
||||||
},
|
},
|
||||||
@@ -183,7 +187,7 @@ func TestListArtifactContainer(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
downloads(router, "artifact/server/path", memfs)
|
downloads(router, "artifact/server/path", memfs)
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "http://localhost/download/1?itemPath=some/file", nil)
|
req, _ := http.NewRequest(http.MethodGet, "http://localhost/download/1?itemPath=some/file", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -198,7 +202,7 @@ func TestListArtifactContainer(t *testing.T) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(1, len(response.Value))
|
assert.Equal(1, len(response.Value)) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal("some/file", response.Value[0].Path)
|
assert.Equal("some/file", response.Value[0].Path)
|
||||||
assert.Equal("file", response.Value[0].ItemType)
|
assert.Equal("file", response.Value[0].ItemType)
|
||||||
assert.Equal("http://localhost/artifact/1/some/file/.", response.Value[0].ContentLocation)
|
assert.Equal("http://localhost/artifact/1/some/file/.", response.Value[0].ContentLocation)
|
||||||
@@ -207,7 +211,7 @@ func TestListArtifactContainer(t *testing.T) {
|
|||||||
func TestDownloadArtifactFile(t *testing.T) {
|
func TestDownloadArtifactFile(t *testing.T) {
|
||||||
assert := assert.New(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": {
|
"artifact/server/path/1/some/file": {
|
||||||
Data: []byte("content"),
|
Data: []byte("content"),
|
||||||
},
|
},
|
||||||
@@ -216,7 +220,7 @@ func TestDownloadArtifactFile(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
downloads(router, "artifact/server/path", memfs)
|
downloads(router, "artifact/server/path", memfs)
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "http://localhost/artifact/1/some/file", nil)
|
req, _ := http.NewRequest(http.MethodGet, "http://localhost/artifact/1/some/file", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -272,14 +276,14 @@ func TestArtifactFlow(t *testing.T) {
|
|||||||
|
|
||||||
func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
|
func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
|
||||||
t.Run(tjfi.workflowPath, func(t *testing.T) {
|
t.Run(tjfi.workflowPath, func(t *testing.T) {
|
||||||
fmt.Printf("::group::%s\n", tjfi.workflowPath)
|
fmt.Printf("::group::%s\n", tjfi.workflowPath) //nolint:forbidigo // pre-existing issue from nektos/act
|
||||||
|
|
||||||
if err := os.RemoveAll(artifactsPath); err != nil {
|
if err := os.RemoveAll(artifactsPath); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
workdir, err := filepath.Abs(tjfi.workdir)
|
workdir, err := filepath.Abs(tjfi.workdir)
|
||||||
assert.Nil(t, err, workdir)
|
assert.Nil(t, err, workdir) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
fullWorkflowPath := filepath.Join(workdir, tjfi.workflowPath)
|
fullWorkflowPath := filepath.Join(workdir, tjfi.workflowPath)
|
||||||
runnerConfig := &runner.Config{
|
runnerConfig := &runner.Config{
|
||||||
Workdir: workdir,
|
Workdir: workdir,
|
||||||
@@ -295,24 +299,24 @@ func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
runner, err := runner.New(runnerConfig)
|
runner, err := runner.New(runnerConfig)
|
||||||
assert.Nil(t, err, tjfi.workflowPath)
|
assert.Nil(t, err, tjfi.workflowPath) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, true)
|
planner, err := model.NewWorkflowPlanner(fullWorkflowPath, true)
|
||||||
assert.Nil(t, err, fullWorkflowPath)
|
assert.Nil(t, err, fullWorkflowPath) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
plan, err := planner.PlanEvent(tjfi.eventName)
|
plan, err := planner.PlanEvent(tjfi.eventName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = runner.NewPlanExecutor(plan)(ctx)
|
err = runner.NewPlanExecutor(plan)(ctx)
|
||||||
if tjfi.errorMessage == "" {
|
if tjfi.errorMessage == "" {
|
||||||
assert.Nil(t, err, fullWorkflowPath)
|
assert.Nil(t, err, fullWorkflowPath) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
} else {
|
} else {
|
||||||
assert.Error(t, err, tjfi.errorMessage)
|
assert.Error(t, err, tjfi.errorMessage) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert.Nil(t, plan)
|
assert.Nil(t, plan)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("::endgroup::")
|
fmt.Println("::endgroup::") //nolint:forbidigo // pre-existing issue from nektos/act
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +348,7 @@ func TestMkdirFsImplSafeResolve(t *testing.T) {
|
|||||||
func TestDownloadArtifactFileUnsafePath(t *testing.T) {
|
func TestDownloadArtifactFileUnsafePath(t *testing.T) {
|
||||||
assert := assert.New(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": {
|
"artifact/server/path/some/file": {
|
||||||
Data: []byte("content"),
|
Data: []byte("content"),
|
||||||
},
|
},
|
||||||
@@ -353,7 +357,7 @@ func TestDownloadArtifactFileUnsafePath(t *testing.T) {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
downloads(router, "artifact/server/path", memfs)
|
downloads(router, "artifact/server/path", memfs)
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "http://localhost/artifact/2/../../some/file", nil)
|
req, _ := http.NewRequest(http.MethodGet, "http://localhost/artifact/2/../../some/file", nil)
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
@@ -370,12 +374,12 @@ func TestDownloadArtifactFileUnsafePath(t *testing.T) {
|
|||||||
func TestArtifactUploadBlobUnsafePath(t *testing.T) {
|
func TestArtifactUploadBlobUnsafePath(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
var memfs = fstest.MapFS(map[string]*fstest.MapFile{})
|
memfs := fstest.MapFS(map[string]*fstest.MapFile{})
|
||||||
|
|
||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
uploads(router, "artifact/server/path", writeMapFS{memfs})
|
||||||
|
|
||||||
req, _ := http.NewRequest("PUT", "http://localhost/upload/1?itemPath=../../some/file", strings.NewReader("content"))
|
req, _ := http.NewRequest(http.MethodPut, "http://localhost/upload/1?itemPath=../../some/file", strings.NewReader("content"))
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
router.ServeHTTP(rr, req)
|
router.ServeHTTP(rr, req)
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,9 +1,13 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
// CartesianProduct takes map of lists and returns list of unique tuples
|
// CartesianProduct takes map of lists and returns list of unique tuples
|
||||||
func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interface{} {
|
func CartesianProduct(mapOfLists map[string][]any) []map[string]any {
|
||||||
listNames := make([]string, 0)
|
listNames := make([]string, 0)
|
||||||
lists := make([][]interface{}, 0)
|
lists := make([][]any, 0)
|
||||||
for k, v := range mapOfLists {
|
for k, v := range mapOfLists {
|
||||||
listNames = append(listNames, k)
|
listNames = append(listNames, k)
|
||||||
lists = append(lists, v)
|
lists = append(lists, v)
|
||||||
@@ -11,9 +15,9 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac
|
|||||||
|
|
||||||
listCart := cartN(lists...)
|
listCart := cartN(lists...)
|
||||||
|
|
||||||
rtn := make([]map[string]interface{}, 0)
|
rtn := make([]map[string]any, 0)
|
||||||
for _, list := range listCart {
|
for _, list := range listCart {
|
||||||
vMap := make(map[string]interface{})
|
vMap := make(map[string]any)
|
||||||
for i, v := range list {
|
for i, v := range list {
|
||||||
vMap[listNames[i]] = v
|
vMap[listNames[i]] = v
|
||||||
}
|
}
|
||||||
@@ -22,7 +26,7 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac
|
|||||||
return rtn
|
return rtn
|
||||||
}
|
}
|
||||||
|
|
||||||
func cartN(a ...[]interface{}) [][]interface{} {
|
func cartN(a ...[]any) [][]any {
|
||||||
c := 1
|
c := 1
|
||||||
for _, a := range a {
|
for _, a := range a {
|
||||||
c *= len(a)
|
c *= len(a)
|
||||||
@@ -30,8 +34,8 @@ func cartN(a ...[]interface{}) [][]interface{} {
|
|||||||
if c == 0 || len(a) == 0 {
|
if c == 0 || len(a) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
p := make([][]interface{}, c)
|
p := make([][]any, c)
|
||||||
b := make([]interface{}, c*len(a))
|
b := make([]any, c*len(a))
|
||||||
n := make([]int, len(a))
|
n := make([]int, len(a))
|
||||||
s := 0
|
s := 0
|
||||||
for i := range p {
|
for i := range p {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -8,7 +12,7 @@ import (
|
|||||||
|
|
||||||
func TestCartesianProduct(t *testing.T) {
|
func TestCartesianProduct(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
input := map[string][]interface{}{
|
input := map[string][]any{
|
||||||
"foo": {1, 2, 3, 4},
|
"foo": {1, 2, 3, 4},
|
||||||
"bar": {"a", "b", "c"},
|
"bar": {"a", "b", "c"},
|
||||||
"baz": {false, true},
|
"baz": {false, true},
|
||||||
@@ -25,15 +29,15 @@ func TestCartesianProduct(t *testing.T) {
|
|||||||
assert.Contains(v, "baz")
|
assert.Contains(v, "baz")
|
||||||
}
|
}
|
||||||
|
|
||||||
input = map[string][]interface{}{
|
input = map[string][]any{
|
||||||
"foo": {1, 2, 3, 4},
|
"foo": {1, 2, 3, 4},
|
||||||
"bar": {},
|
"bar": {},
|
||||||
"baz": {false, true},
|
"baz": {false, true},
|
||||||
}
|
}
|
||||||
output = CartesianProduct(input)
|
output = CartesianProduct(input)
|
||||||
assert.Len(output, 0)
|
assert.Len(output, 0) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
input = map[string][]interface{}{}
|
input = map[string][]any{}
|
||||||
output = CartesianProduct(input)
|
output = CartesianProduct(input)
|
||||||
assert.Len(output, 0)
|
assert.Len(output, 0) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -72,6 +76,7 @@ func (p *Pen) drawTopBars(buf io.Writer, labels ...string) {
|
|||||||
}
|
}
|
||||||
fmt.Fprintf(buf, "\n")
|
fmt.Fprintf(buf, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pen) drawBottomBars(buf io.Writer, labels ...string) {
|
func (p *Pen) drawBottomBars(buf io.Writer, labels ...string) {
|
||||||
style := styleDefs[p.style]
|
style := styleDefs[p.style]
|
||||||
for _, label := range labels {
|
for _, label := range labels {
|
||||||
@@ -83,6 +88,7 @@ func (p *Pen) drawBottomBars(buf io.Writer, labels ...string) {
|
|||||||
}
|
}
|
||||||
fmt.Fprintf(buf, "\n")
|
fmt.Fprintf(buf, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pen) drawLabels(buf io.Writer, labels ...string) {
|
func (p *Pen) drawLabels(buf io.Writer, labels ...string) {
|
||||||
style := styleDefs[p.style]
|
style := styleDefs[p.style]
|
||||||
for _, label := range labels {
|
for _, label := range labels {
|
||||||
@@ -125,11 +131,8 @@ func (p *Pen) DrawBoxes(labels ...string) *Drawing {
|
|||||||
|
|
||||||
// Draw to writer
|
// Draw to writer
|
||||||
func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) {
|
func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) {
|
||||||
padSize := (centerOnWidth - d.GetWidth()) / 2
|
padSize := max((centerOnWidth-d.GetWidth())/2, 0)
|
||||||
if padSize < 0 {
|
for l := range strings.SplitSeq(d.buf.String(), "\n") {
|
||||||
padSize = 0
|
|
||||||
}
|
|
||||||
for _, l := range strings.Split(d.buf.String(), "\n") {
|
|
||||||
if len(l) > 0 {
|
if len(l) > 0 {
|
||||||
padding := strings.Repeat(" ", padSize)
|
padding := strings.Repeat(" ", padSize)
|
||||||
fmt.Fprintf(writer, "%s%s\n", padding, l)
|
fmt.Fprintf(writer, "%s%s\n", padding, l)
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -19,7 +23,7 @@ func (w Warning) Error() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Warningf create a warning
|
// Warningf create a warning
|
||||||
func Warningf(format string, args ...interface{}) Warning {
|
func Warningf(format string, args ...any) Warning {
|
||||||
w := Warning{
|
w := Warning{
|
||||||
Message: fmt.Sprintf(format, args...),
|
Message: fmt.Sprintf(format, args...),
|
||||||
}
|
}
|
||||||
@@ -33,7 +37,7 @@ type Executor func(ctx context.Context) error
|
|||||||
type Conditional func(ctx context.Context) bool
|
type Conditional func(ctx context.Context) bool
|
||||||
|
|
||||||
// NewInfoExecutor is an executor that logs messages
|
// NewInfoExecutor is an executor that logs messages
|
||||||
func NewInfoExecutor(format string, args ...interface{}) Executor {
|
func NewInfoExecutor(format string, args ...any) Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
logger := Logger(ctx)
|
logger := Logger(ctx)
|
||||||
logger.Infof(format, args...)
|
logger.Infof(format, args...)
|
||||||
@@ -42,7 +46,7 @@ func NewInfoExecutor(format string, args ...interface{}) Executor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewDebugExecutor is an executor that logs messages
|
// NewDebugExecutor is an executor that logs messages
|
||||||
func NewDebugExecutor(format string, args ...interface{}) Executor {
|
func NewDebugExecutor(format string, args ...any) Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
logger := Logger(ctx)
|
logger := Logger(ctx)
|
||||||
logger.Debugf(format, args...)
|
logger.Debugf(format, args...)
|
||||||
@@ -69,7 +73,7 @@ func NewPipelineExecutor(executors ...Executor) Executor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewConditionalExecutor creates a new executor based on conditions
|
// NewConditionalExecutor creates a new executor based on conditions
|
||||||
func NewConditionalExecutor(conditional Conditional, trueExecutor Executor, falseExecutor Executor) Executor {
|
func NewConditionalExecutor(conditional Conditional, trueExecutor, falseExecutor Executor) Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
if conditional(ctx) {
|
if conditional(ctx) {
|
||||||
if trueExecutor != nil {
|
if trueExecutor != nil {
|
||||||
@@ -128,14 +132,14 @@ func NewParallelExecutor(parallel int, executors ...Executor) Executor {
|
|||||||
}(i, work, errs)
|
}(i, work, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(executors); i++ {
|
for i := range executors {
|
||||||
work <- executors[i]
|
work <- executors[i]
|
||||||
}
|
}
|
||||||
close(work)
|
close(work)
|
||||||
|
|
||||||
// Executor waits all executors to cleanup these resources.
|
// Executor waits all executors to cleanup these resources.
|
||||||
var firstErr error
|
var firstErr error
|
||||||
for i := 0; i < len(executors); i++ {
|
for range executors {
|
||||||
err := <-errs
|
err := <-errs
|
||||||
if firstErr == nil {
|
if firstErr == nil {
|
||||||
firstErr = err
|
firstErr = err
|
||||||
+21
-18
@@ -1,3 +1,6 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -14,32 +17,32 @@ import (
|
|||||||
func TestMaxParallel2Quick(t *testing.T) {
|
func TestMaxParallel2Quick(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
var currentRunning int32
|
var currentRunning atomic.Int32
|
||||||
var maxSimultaneous int32
|
var maxSimultaneous atomic.Int32
|
||||||
|
|
||||||
executors := make([]Executor, 4)
|
executors := make([]Executor, 4)
|
||||||
for i := 0; i < 4; i++ {
|
for i := range 4 {
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
current := atomic.AddInt32(¤tRunning, 1)
|
current := currentRunning.Add(1)
|
||||||
|
|
||||||
// Update max if needed
|
// Update max if needed
|
||||||
for {
|
for {
|
||||||
maxValue := atomic.LoadInt32(&maxSimultaneous)
|
maxValue := maxSimultaneous.Load()
|
||||||
if current <= maxValue || atomic.CompareAndSwapInt32(&maxSimultaneous, maxValue, current) {
|
if current <= maxValue || maxSimultaneous.CompareAndSwap(maxValue, current) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
atomic.AddInt32(¤tRunning, -1)
|
currentRunning.Add(-1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := NewParallelExecutor(2, executors...)(ctx)
|
err := NewParallelExecutor(2, executors...)(ctx)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.LessOrEqual(t, atomic.LoadInt32(&maxSimultaneous), int32(2),
|
assert.LessOrEqual(t, maxSimultaneous.Load(), int32(2),
|
||||||
"Should not exceed max-parallel: 2")
|
"Should not exceed max-parallel: 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,16 +50,16 @@ func TestMaxParallel2Quick(t *testing.T) {
|
|||||||
func TestMaxParallel1Sequential(t *testing.T) {
|
func TestMaxParallel1Sequential(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
var currentRunning int32
|
var currentRunning atomic.Int32
|
||||||
var maxSimultaneous int32
|
var maxSimultaneous atomic.Int32
|
||||||
var executionOrder []int
|
var executionOrder []int
|
||||||
var orderMutex sync.Mutex
|
var orderMutex sync.Mutex
|
||||||
|
|
||||||
executors := make([]Executor, 5)
|
executors := make([]Executor, 5)
|
||||||
for i := 0; i < 5; i++ {
|
for i := range 5 {
|
||||||
taskID := i
|
taskID := i
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
current := atomic.AddInt32(¤tRunning, 1)
|
current := currentRunning.Add(1)
|
||||||
|
|
||||||
// Track execution order
|
// Track execution order
|
||||||
orderMutex.Lock()
|
orderMutex.Lock()
|
||||||
@@ -65,22 +68,22 @@ func TestMaxParallel1Sequential(t *testing.T) {
|
|||||||
|
|
||||||
// Update max if needed
|
// Update max if needed
|
||||||
for {
|
for {
|
||||||
maxValue := atomic.LoadInt32(&maxSimultaneous)
|
maxValue := maxSimultaneous.Load()
|
||||||
if current <= maxValue || atomic.CompareAndSwapInt32(&maxSimultaneous, maxValue, current) {
|
if current <= maxValue || maxSimultaneous.CompareAndSwap(maxValue, current) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(20 * time.Millisecond)
|
time.Sleep(20 * time.Millisecond)
|
||||||
atomic.AddInt32(¤tRunning, -1)
|
currentRunning.Add(-1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := NewParallelExecutor(1, executors...)(ctx)
|
err := NewParallelExecutor(1, executors...)(ctx)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, int32(1), atomic.LoadInt32(&maxSimultaneous),
|
assert.Equal(t, int32(1), maxSimultaneous.Load(),
|
||||||
"max-parallel: 1 should only run 1 task at a time")
|
"max-parallel: 1 should only run 1 task at a time")
|
||||||
assert.Len(t, executionOrder, 5, "All 5 tasks should have executed")
|
assert.Len(t, executionOrder, 5, "All 5 tasks should have executed")
|
||||||
}
|
}
|
||||||
+38
-35
@@ -1,3 +1,6 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -13,21 +16,21 @@ import (
|
|||||||
// TestMaxParallelJobExecution tests actual job execution with max-parallel
|
// TestMaxParallelJobExecution tests actual job execution with max-parallel
|
||||||
func TestMaxParallelJobExecution(t *testing.T) {
|
func TestMaxParallelJobExecution(t *testing.T) {
|
||||||
t.Run("MaxParallel=1 Sequential", func(t *testing.T) {
|
t.Run("MaxParallel=1 Sequential", func(t *testing.T) {
|
||||||
var currentRunning int32
|
var currentRunning atomic.Int32
|
||||||
var maxConcurrent int32
|
var maxConcurrent int32
|
||||||
var executionOrder []int
|
var executionOrder []int
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
|
|
||||||
executors := make([]Executor, 5)
|
executors := make([]Executor, 5)
|
||||||
for i := 0; i < 5; i++ {
|
for i := range 5 {
|
||||||
taskID := i
|
taskID := i
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
current := atomic.AddInt32(¤tRunning, 1)
|
current := currentRunning.Add(1)
|
||||||
|
|
||||||
// Track max concurrent
|
// Track max concurrent
|
||||||
for {
|
for {
|
||||||
max := atomic.LoadInt32(&maxConcurrent)
|
maxValue := atomic.LoadInt32(&maxConcurrent)
|
||||||
if current <= max || atomic.CompareAndSwapInt32(&maxConcurrent, max, current) {
|
if current <= maxValue || atomic.CompareAndSwapInt32(&maxConcurrent, maxValue, current) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,44 +40,44 @@ func TestMaxParallelJobExecution(t *testing.T) {
|
|||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
atomic.AddInt32(¤tRunning, -1)
|
currentRunning.Add(-1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err := NewParallelExecutor(1, executors...)(ctx)
|
err := NewParallelExecutor(1, executors...)(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
assert.Equal(t, int32(1), maxConcurrent, "Should never exceed 1 concurrent execution")
|
assert.Equal(t, int32(1), maxConcurrent, "Should never exceed 1 concurrent execution")
|
||||||
assert.Len(t, executionOrder, 5, "All tasks should execute")
|
assert.Len(t, executionOrder, 5, "All tasks should execute")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("MaxParallel=3 Limited", func(t *testing.T) {
|
t.Run("MaxParallel=3 Limited", func(t *testing.T) {
|
||||||
var currentRunning int32
|
var currentRunning atomic.Int32
|
||||||
var maxConcurrent int32
|
var maxConcurrent int32
|
||||||
|
|
||||||
executors := make([]Executor, 10)
|
executors := make([]Executor, 10)
|
||||||
for i := 0; i < 10; i++ {
|
for i := range 10 {
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
current := atomic.AddInt32(¤tRunning, 1)
|
current := currentRunning.Add(1)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
max := atomic.LoadInt32(&maxConcurrent)
|
maxValue := atomic.LoadInt32(&maxConcurrent)
|
||||||
if current <= max || atomic.CompareAndSwapInt32(&maxConcurrent, max, current) {
|
if current <= maxValue || atomic.CompareAndSwapInt32(&maxConcurrent, maxValue, current) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(20 * time.Millisecond)
|
time.Sleep(20 * time.Millisecond)
|
||||||
atomic.AddInt32(¤tRunning, -1)
|
currentRunning.Add(-1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err := NewParallelExecutor(3, executors...)(ctx)
|
err := NewParallelExecutor(3, executors...)(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
assert.LessOrEqual(t, int(maxConcurrent), 3, "Should never exceed 3 concurrent executions")
|
assert.LessOrEqual(t, int(maxConcurrent), 3, "Should never exceed 3 concurrent executions")
|
||||||
assert.GreaterOrEqual(t, int(maxConcurrent), 1, "Should have at least 1 concurrent execution")
|
assert.GreaterOrEqual(t, int(maxConcurrent), 1, "Should have at least 1 concurrent execution")
|
||||||
@@ -82,22 +85,22 @@ func TestMaxParallelJobExecution(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("MaxParallel=0 Uses1Worker", func(t *testing.T) {
|
t.Run("MaxParallel=0 Uses1Worker", func(t *testing.T) {
|
||||||
var maxConcurrent int32
|
var maxConcurrent int32
|
||||||
var currentRunning int32
|
var currentRunning atomic.Int32
|
||||||
|
|
||||||
executors := make([]Executor, 5)
|
executors := make([]Executor, 5)
|
||||||
for i := 0; i < 5; i++ {
|
for i := range 5 {
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
current := atomic.AddInt32(¤tRunning, 1)
|
current := currentRunning.Add(1)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
max := atomic.LoadInt32(&maxConcurrent)
|
maxValue := atomic.LoadInt32(&maxConcurrent)
|
||||||
if current <= max || atomic.CompareAndSwapInt32(&maxConcurrent, max, current) {
|
if current <= maxValue || atomic.CompareAndSwapInt32(&maxConcurrent, maxValue, current) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
atomic.AddInt32(¤tRunning, -1)
|
currentRunning.Add(-1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +108,7 @@ func TestMaxParallelJobExecution(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
// When maxParallel is 0 or negative, it defaults to 1
|
// When maxParallel is 0 or negative, it defaults to 1
|
||||||
err := NewParallelExecutor(0, executors...)(ctx)
|
err := NewParallelExecutor(0, executors...)(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
assert.Equal(t, int32(1), maxConcurrent, "Should use 1 worker when max-parallel is 0")
|
assert.Equal(t, int32(1), maxConcurrent, "Should use 1 worker when max-parallel is 0")
|
||||||
})
|
})
|
||||||
@@ -117,7 +120,7 @@ func TestMaxParallelWithErrors(t *testing.T) {
|
|||||||
var successCount int32
|
var successCount int32
|
||||||
|
|
||||||
executors := make([]Executor, 5)
|
executors := make([]Executor, 5)
|
||||||
for i := 0; i < 5; i++ {
|
for i := range 5 {
|
||||||
taskID := i
|
taskID := i
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
if taskID == 2 {
|
if taskID == 2 {
|
||||||
@@ -132,7 +135,7 @@ func TestMaxParallelWithErrors(t *testing.T) {
|
|||||||
err := NewParallelExecutor(2, executors...)(ctx)
|
err := NewParallelExecutor(2, executors...)(ctx)
|
||||||
|
|
||||||
// Should return the error from task 2
|
// Should return the error from task 2
|
||||||
assert.Error(t, err)
|
assert.Error(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// Other tasks should still execute
|
// Other tasks should still execute
|
||||||
assert.Equal(t, int32(4), successCount, "4 tasks should succeed")
|
assert.Equal(t, int32(4), successCount, "4 tasks should succeed")
|
||||||
@@ -143,7 +146,7 @@ func TestMaxParallelWithErrors(t *testing.T) {
|
|||||||
|
|
||||||
var startedCount int32
|
var startedCount int32
|
||||||
executors := make([]Executor, 10)
|
executors := make([]Executor, 10)
|
||||||
for i := 0; i < 10; i++ {
|
for i := range 10 {
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
atomic.AddInt32(&startedCount, 1)
|
atomic.AddInt32(&startedCount, 1)
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
@@ -158,8 +161,8 @@ func TestMaxParallelWithErrors(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
err := NewParallelExecutor(3, executors...)(ctx)
|
err := NewParallelExecutor(3, executors...)(ctx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.ErrorIs(t, err, context.Canceled)
|
assert.ErrorIs(t, err, context.Canceled) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// Not all tasks should start due to cancellation (but timing may vary)
|
// Not all tasks should start due to cancellation (but timing may vary)
|
||||||
// Just verify cancellation occurred
|
// Just verify cancellation occurred
|
||||||
@@ -175,7 +178,7 @@ func TestMaxParallelPerformance(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("ParallelFasterThanSequential", func(t *testing.T) {
|
t.Run("ParallelFasterThanSequential", func(t *testing.T) {
|
||||||
executors := make([]Executor, 10)
|
executors := make([]Executor, 10)
|
||||||
for i := 0; i < 10; i++ {
|
for i := range 10 {
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
return nil
|
return nil
|
||||||
@@ -188,13 +191,13 @@ func TestMaxParallelPerformance(t *testing.T) {
|
|||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := NewParallelExecutor(1, executors...)(ctx)
|
err := NewParallelExecutor(1, executors...)(ctx)
|
||||||
sequentialDuration := time.Since(start)
|
sequentialDuration := time.Since(start)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// Parallel (max-parallel=5)
|
// Parallel (max-parallel=5)
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
err = NewParallelExecutor(5, executors...)(ctx)
|
err = NewParallelExecutor(5, executors...)(ctx)
|
||||||
parallelDuration := time.Since(start)
|
parallelDuration := time.Since(start)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// Parallel should be significantly faster
|
// Parallel should be significantly faster
|
||||||
assert.Less(t, parallelDuration, sequentialDuration/2,
|
assert.Less(t, parallelDuration, sequentialDuration/2,
|
||||||
@@ -203,7 +206,7 @@ func TestMaxParallelPerformance(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("OptimalWorkerCount", func(t *testing.T) {
|
t.Run("OptimalWorkerCount", func(t *testing.T) {
|
||||||
executors := make([]Executor, 20)
|
executors := make([]Executor, 20)
|
||||||
for i := 0; i < 20; i++ {
|
for i := range 20 {
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
return nil
|
return nil
|
||||||
@@ -220,7 +223,7 @@ func TestMaxParallelPerformance(t *testing.T) {
|
|||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := NewParallelExecutor(count, executors...)(ctx)
|
err := NewParallelExecutor(count, executors...)(ctx)
|
||||||
durations[count] = time.Since(start)
|
durations[count] = time.Since(start)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
|
|
||||||
// More workers should generally be faster (up to a point)
|
// More workers should generally be faster (up to a point)
|
||||||
@@ -236,7 +239,7 @@ func TestMaxParallelResourceSharing(t *testing.T) {
|
|||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
|
|
||||||
executors := make([]Executor, 100)
|
executors := make([]Executor, 100)
|
||||||
for i := 0; i < 100; i++ {
|
for i := range 100 {
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
sharedCounter++
|
sharedCounter++
|
||||||
@@ -247,7 +250,7 @@ func TestMaxParallelResourceSharing(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err := NewParallelExecutor(10, executors...)(ctx)
|
err := NewParallelExecutor(10, executors...)(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
assert.Equal(t, 100, sharedCounter, "All tasks should increment counter")
|
assert.Equal(t, 100, sharedCounter, "All tasks should increment counter")
|
||||||
})
|
})
|
||||||
@@ -256,7 +259,7 @@ func TestMaxParallelResourceSharing(t *testing.T) {
|
|||||||
resultChan := make(chan int, 50)
|
resultChan := make(chan int, 50)
|
||||||
|
|
||||||
executors := make([]Executor, 50)
|
executors := make([]Executor, 50)
|
||||||
for i := 0; i < 50; i++ {
|
for i := range 50 {
|
||||||
taskID := i
|
taskID := i
|
||||||
executors[i] = func(ctx context.Context) error {
|
executors[i] = func(ctx context.Context) error {
|
||||||
resultChan <- taskID
|
resultChan <- taskID
|
||||||
@@ -266,7 +269,7 @@ func TestMaxParallelResourceSharing(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err := NewParallelExecutor(5, executors...)(ctx)
|
err := NewParallelExecutor(5, executors...)(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
close(resultChan)
|
close(resultChan)
|
||||||
|
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -16,11 +21,11 @@ func TestNewWorkflow(t *testing.T) {
|
|||||||
|
|
||||||
// empty
|
// empty
|
||||||
emptyWorkflow := NewPipelineExecutor()
|
emptyWorkflow := NewPipelineExecutor()
|
||||||
assert.Nil(emptyWorkflow(ctx))
|
assert.Nil(emptyWorkflow(ctx)) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// error case
|
// error case
|
||||||
errorWorkflow := NewErrorExecutor(fmt.Errorf("test error"))
|
errorWorkflow := NewErrorExecutor(errors.New("test error"))
|
||||||
assert.NotNil(errorWorkflow(ctx))
|
assert.NotNil(errorWorkflow(ctx)) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// multiple success case
|
// multiple success case
|
||||||
runcount := 0
|
runcount := 0
|
||||||
@@ -33,7 +38,7 @@ func TestNewWorkflow(t *testing.T) {
|
|||||||
runcount++
|
runcount++
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
assert.Nil(successWorkflow(ctx))
|
assert.Nil(successWorkflow(ctx)) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(2, runcount)
|
assert.Equal(2, runcount)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +60,7 @@ func TestNewConditionalExecutor(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
})(ctx)
|
})(ctx)
|
||||||
|
|
||||||
assert.Nil(err)
|
assert.Nil(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(0, trueCount)
|
assert.Equal(0, trueCount)
|
||||||
assert.Equal(1, falseCount)
|
assert.Equal(1, falseCount)
|
||||||
|
|
||||||
@@ -69,7 +74,7 @@ func TestNewConditionalExecutor(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
})(ctx)
|
})(ctx)
|
||||||
|
|
||||||
assert.Nil(err)
|
assert.Nil(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(1, trueCount)
|
assert.Equal(1, trueCount)
|
||||||
assert.Equal(1, falseCount)
|
assert.Equal(1, falseCount)
|
||||||
}
|
}
|
||||||
@@ -79,38 +84,39 @@ func TestNewParallelExecutor(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
count := 0
|
var count, activeCount, maxCount atomic.Int32
|
||||||
activeCount := 0
|
|
||||||
maxCount := 0
|
|
||||||
emptyWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
|
emptyWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
|
||||||
count++
|
count.Add(1)
|
||||||
|
|
||||||
activeCount++
|
active := activeCount.Add(1)
|
||||||
if activeCount > maxCount {
|
for {
|
||||||
maxCount = activeCount
|
m := maxCount.Load()
|
||||||
|
if active <= m || maxCount.CompareAndSwap(m, active) {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
activeCount--
|
activeCount.Add(-1)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
err := NewParallelExecutor(2, emptyWorkflow, emptyWorkflow, emptyWorkflow)(ctx)
|
err := NewParallelExecutor(2, emptyWorkflow, emptyWorkflow, emptyWorkflow)(ctx)
|
||||||
|
|
||||||
assert.Equal(3, count, "should run all 3 executors")
|
assert.Equal(int32(3), count.Load(), "should run all 3 executors")
|
||||||
assert.Equal(2, maxCount, "should run at most 2 executors in parallel")
|
assert.Equal(int32(2), maxCount.Load(), "should run at most 2 executors in parallel")
|
||||||
assert.Nil(err)
|
assert.Nil(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// Reset to test running the executor with 0 parallelism
|
// Reset to test running the executor with 0 parallelism
|
||||||
count = 0
|
count.Store(0)
|
||||||
activeCount = 0
|
activeCount.Store(0)
|
||||||
maxCount = 0
|
maxCount.Store(0)
|
||||||
|
|
||||||
errSingle := NewParallelExecutor(0, emptyWorkflow, emptyWorkflow, emptyWorkflow)(ctx)
|
errSingle := NewParallelExecutor(0, emptyWorkflow, emptyWorkflow, emptyWorkflow)(ctx)
|
||||||
|
|
||||||
assert.Equal(3, count, "should run all 3 executors")
|
assert.Equal(int32(3), count.Load(), "should run all 3 executors")
|
||||||
assert.Equal(1, maxCount, "should run at most 1 executors in parallel")
|
assert.Equal(int32(1), maxCount.Load(), "should run at most 1 executors in parallel")
|
||||||
assert.Nil(errSingle)
|
assert.Nil(errSingle) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewParallelExecutorFailed(t *testing.T) {
|
func TestNewParallelExecutorFailed(t *testing.T) {
|
||||||
@@ -122,7 +128,7 @@ func TestNewParallelExecutorFailed(t *testing.T) {
|
|||||||
count := 0
|
count := 0
|
||||||
errorWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
|
errorWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
|
||||||
count++
|
count++
|
||||||
return fmt.Errorf("fake error")
|
return errors.New("fake error")
|
||||||
})
|
})
|
||||||
err := NewParallelExecutor(1, errorWorkflow)(ctx)
|
err := NewParallelExecutor(1, errorWorkflow)(ctx)
|
||||||
assert.Equal(1, count)
|
assert.Equal(1, count)
|
||||||
@@ -135,18 +141,18 @@ func TestNewParallelExecutorCanceled(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
errExpected := fmt.Errorf("fake error")
|
errExpected := errors.New("fake error")
|
||||||
|
|
||||||
count := 0
|
var count atomic.Int32
|
||||||
successWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
|
successWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
|
||||||
count++
|
count.Add(1)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
errorWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
|
errorWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
|
||||||
count++
|
count.Add(1)
|
||||||
return errExpected
|
return errExpected
|
||||||
})
|
})
|
||||||
err := NewParallelExecutor(3, errorWorkflow, successWorkflow, successWorkflow)(ctx)
|
err := NewParallelExecutor(3, errorWorkflow, successWorkflow, successWorkflow)(ctx)
|
||||||
assert.Equal(3, count)
|
assert.Equal(int32(3), count.Load())
|
||||||
assert.Error(errExpected, err)
|
assert.Error(errExpected, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -7,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CopyFile copy file
|
// CopyFile copy file
|
||||||
func CopyFile(source string, dest string) (err error) {
|
func CopyFile(source, dest string) (err error) {
|
||||||
sourcefile, err := os.Open(source)
|
sourcefile, err := os.Open(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -30,11 +34,11 @@ func CopyFile(source string, dest string) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyDir recursive copy of directory
|
// CopyDir recursive copy of directory
|
||||||
func CopyDir(source string, dest string) (err error) {
|
func CopyDir(source, dest string) (err error) {
|
||||||
// get properties of source dir
|
// get properties of source dir
|
||||||
sourceinfo, err := os.Stat(source)
|
sourceinfo, err := os.Stat(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -59,13 +63,13 @@ func CopyDir(source string, dest string) (err error) {
|
|||||||
// create sub-directories - recursively
|
// create sub-directories - recursively
|
||||||
err = CopyDir(sourcefilepointer, destinationfilepointer)
|
err = CopyDir(sourcefilepointer, destinationfilepointer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err) //nolint:forbidigo // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// perform copy
|
// perform copy
|
||||||
err = CopyFile(sourcefilepointer, destinationfilepointer)
|
err = CopyFile(sourcefilepointer, destinationfilepointer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err) //nolint:forbidigo // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -11,6 +15,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/config"
|
"github.com/go-git/go-git/v5/config"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
@@ -18,8 +24,6 @@ import (
|
|||||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -52,7 +56,7 @@ func (e *Error) Commit() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindGitRevision get the current git revision
|
// FindGitRevision get the current git revision
|
||||||
func FindGitRevision(ctx context.Context, file string) (shortSha string, sha string, err error) {
|
func FindGitRevision(ctx context.Context, file string) (shortSha, sha string, err error) {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
|
|
||||||
gitDir, err := git.PlainOpenWithOptions(
|
gitDir, err := git.PlainOpenWithOptions(
|
||||||
@@ -62,7 +66,6 @@ func FindGitRevision(ctx context.Context, file string) (shortSha string, sha str
|
|||||||
EnableDotGitCommonDir: true,
|
EnableDotGitCommonDir: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Error("path", file, "not located inside a git repository")
|
logger.WithError(err).Error("path", file, "not located inside a git repository")
|
||||||
return "", "", err
|
return "", "", err
|
||||||
@@ -74,7 +77,7 @@ func FindGitRevision(ctx context.Context, file string) (shortSha string, sha str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if head.Hash().IsZero() {
|
if head.Hash().IsZero() {
|
||||||
return "", "", fmt.Errorf("HEAD sha1 could not be resolved")
|
return "", "", errors.New("HEAD sha1 could not be resolved")
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := head.Hash().String()
|
hash := head.Hash().String()
|
||||||
@@ -96,8 +99,8 @@ func FindGitRef(ctx context.Context, file string) (string, error) {
|
|||||||
logger.Debugf("HEAD points to '%s'", ref)
|
logger.Debugf("HEAD points to '%s'", ref)
|
||||||
|
|
||||||
// Prefer the git library to iterate over the references and find a matching tag or branch.
|
// Prefer the git library to iterate over the references and find a matching tag or branch.
|
||||||
var refTag = ""
|
refTag := ""
|
||||||
var refBranch = ""
|
refBranch := ""
|
||||||
repo, err := git.PlainOpenWithOptions(
|
repo, err := git.PlainOpenWithOptions(
|
||||||
file,
|
file,
|
||||||
&git.PlainOpenOptions{
|
&git.PlainOpenOptions{
|
||||||
@@ -105,7 +108,6 @@ func FindGitRef(ctx context.Context, file string) (string, error) {
|
|||||||
EnableDotGitCommonDir: true,
|
EnableDotGitCommonDir: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -144,7 +146,6 @@ func FindGitRef(ctx context.Context, file string) (string, error) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -198,7 +199,7 @@ func findGitRemoteURL(_ context.Context, file, remoteName string) (string, error
|
|||||||
return remote.Config().URLs[0], nil
|
return remote.Config().URLs[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findGitSlug(url string, githubInstance string) (string, string, error) {
|
func findGitSlug(url, githubInstance string) (string, string, error) { //nolint:unparam // pre-existing issue from nektos/act
|
||||||
if matches := codeCommitHTTPRegex.FindStringSubmatch(url); matches != nil {
|
if matches := codeCommitHTTPRegex.FindStringSubmatch(url); matches != nil {
|
||||||
return "CodeCommit", matches[2], nil
|
return "CodeCommit", matches[2], nil
|
||||||
} else if matches := codeCommitSSHRegex.FindStringSubmatch(url); matches != nil {
|
} else if matches := codeCommitSSHRegex.FindStringSubmatch(url); matches != nil {
|
||||||
@@ -209,7 +210,7 @@ func findGitSlug(url string, githubInstance string) (string, string, error) {
|
|||||||
return "GitHub", fmt.Sprintf("%s/%s", matches[1], matches[2]), nil
|
return "GitHub", fmt.Sprintf("%s/%s", matches[1], matches[2]), nil
|
||||||
} else if githubInstance != "github.com" {
|
} else if githubInstance != "github.com" {
|
||||||
gheHTTPRegex := regexp.MustCompile(fmt.Sprintf(`^https?://%s/(.+)/(.+?)(?:.git)?$`, githubInstance))
|
gheHTTPRegex := regexp.MustCompile(fmt.Sprintf(`^https?://%s/(.+)/(.+?)(?:.git)?$`, githubInstance))
|
||||||
gheSSHRegex := regexp.MustCompile(fmt.Sprintf(`%s[:/](.+)/(.+?)(?:.git)?$`, githubInstance))
|
gheSSHRegex := regexp.MustCompile(githubInstance + "[:/](.+)/(.+?)(?:.git)?$")
|
||||||
if matches := gheHTTPRegex.FindStringSubmatch(url); matches != nil {
|
if matches := gheHTTPRegex.FindStringSubmatch(url); matches != nil {
|
||||||
return "GitHubEnterprise", fmt.Sprintf("%s/%s", matches[1], matches[2]), nil
|
return "GitHubEnterprise", fmt.Sprintf("%s/%s", matches[1], matches[2]), nil
|
||||||
} else if matches := gheSSHRegex.FindStringSubmatch(url); matches != nil {
|
} else if matches := gheSSHRegex.FindStringSubmatch(url); matches != nil {
|
||||||
@@ -276,6 +277,7 @@ func CloneIfRequired(ctx context.Context, refName plumbing.ReferenceName, input
|
|||||||
|
|
||||||
func gitOptions(token string) (fetchOptions git.FetchOptions, pullOptions git.PullOptions) {
|
func gitOptions(token string) (fetchOptions git.FetchOptions, pullOptions git.PullOptions) {
|
||||||
fetchOptions.RefSpecs = []config.RefSpec{"refs/*:refs/*", "HEAD:refs/heads/HEAD"}
|
fetchOptions.RefSpecs = []config.RefSpec{"refs/*:refs/*", "HEAD:refs/heads/HEAD"}
|
||||||
|
fetchOptions.Force = true
|
||||||
pullOptions.Force = true
|
pullOptions.Force = true
|
||||||
|
|
||||||
if token != "" {
|
if token != "" {
|
||||||
@@ -292,7 +294,7 @@ func gitOptions(token string) (fetchOptions git.FetchOptions, pullOptions git.Pu
|
|||||||
|
|
||||||
// NewGitCloneExecutor creates an executor to clone git repos
|
// NewGitCloneExecutor creates an executor to clone git repos
|
||||||
//
|
//
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo // function handles many cases
|
||||||
func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor {
|
func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
@@ -302,7 +304,7 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor {
|
|||||||
cloneLock.Lock()
|
cloneLock.Lock()
|
||||||
defer cloneLock.Unlock()
|
defer cloneLock.Unlock()
|
||||||
|
|
||||||
refName := plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", input.Ref))
|
refName := plumbing.ReferenceName("refs/heads/" + input.Ref)
|
||||||
r, err := CloneIfRequired(ctx, refName, input, logger)
|
r, err := CloneIfRequired(ctx, refName, input, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -6,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -17,7 +22,7 @@ import (
|
|||||||
func TestFindGitSlug(t *testing.T) {
|
func TestFindGitSlug(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
var slugTests = []struct {
|
slugTests := []struct {
|
||||||
url string // input
|
url string // input
|
||||||
provider string // expected result
|
provider string // expected result
|
||||||
slug string // expected result
|
slug string // expected result
|
||||||
@@ -37,17 +42,14 @@ func TestFindGitSlug(t *testing.T) {
|
|||||||
for _, tt := range slugTests {
|
for _, tt := range slugTests {
|
||||||
provider, slug, err := findGitSlug(tt.url, "github.com")
|
provider, slug, err := findGitSlug(tt.url, "github.com")
|
||||||
|
|
||||||
assert.NoError(err)
|
assert.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(tt.provider, provider)
|
assert.Equal(tt.provider, provider)
|
||||||
assert.Equal(tt.slug, slug)
|
assert.Equal(tt.slug, slug)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDir(t *testing.T) string {
|
func testDir(t *testing.T) string {
|
||||||
basedir, err := os.MkdirTemp("", "act-test")
|
return t.TempDir()
|
||||||
require.NoError(t, err)
|
|
||||||
t.Cleanup(func() { _ = os.RemoveAll(basedir) })
|
|
||||||
return basedir
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanGitHooks(dir string) error {
|
func cleanGitHooks(dir string) error {
|
||||||
@@ -77,23 +79,23 @@ func TestFindGitRemoteURL(t *testing.T) {
|
|||||||
basedir := testDir(t)
|
basedir := testDir(t)
|
||||||
gitConfig()
|
gitConfig()
|
||||||
err := gitCmd("init", basedir)
|
err := gitCmd("init", basedir)
|
||||||
assert.NoError(err)
|
assert.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
err = cleanGitHooks(basedir)
|
err = cleanGitHooks(basedir)
|
||||||
assert.NoError(err)
|
assert.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
remoteURL := "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name"
|
remoteURL := "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo-name"
|
||||||
err = gitCmd("-C", basedir, "remote", "add", "origin", remoteURL)
|
err = gitCmd("-C", basedir, "remote", "add", "origin", remoteURL)
|
||||||
assert.NoError(err)
|
assert.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
u, err := findGitRemoteURL(context.Background(), basedir, "origin")
|
u, err := findGitRemoteURL(context.Background(), basedir, "origin")
|
||||||
assert.NoError(err)
|
assert.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(remoteURL, u)
|
assert.Equal(remoteURL, u)
|
||||||
|
|
||||||
remoteURL = "[email protected]/AwesomeOwner/MyAwesomeRepo.git"
|
remoteURL = "[email protected]/AwesomeOwner/MyAwesomeRepo.git"
|
||||||
err = gitCmd("-C", basedir, "remote", "add", "upstream", remoteURL)
|
err = gitCmd("-C", basedir, "remote", "add", "upstream", remoteURL)
|
||||||
assert.NoError(err)
|
assert.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
u, err = findGitRemoteURL(context.Background(), basedir, "upstream")
|
u, err = findGitRemoteURL(context.Background(), basedir, "upstream")
|
||||||
assert.NoError(err)
|
assert.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(remoteURL, u)
|
assert.Equal(remoteURL, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,8 +165,6 @@ func TestGitFindRef(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
tt := tt
|
|
||||||
name := name
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
dir := filepath.Join(basedir, name)
|
dir := filepath.Join(basedir, name)
|
||||||
require.NoError(t, os.MkdirAll(dir, 0o755))
|
require.NoError(t, os.MkdirAll(dir, 0o755))
|
||||||
@@ -212,15 +212,71 @@ func TestGitCloneExecutor(t *testing.T) {
|
|||||||
|
|
||||||
err := clone(context.Background())
|
err := clone(context.Background())
|
||||||
if tt.Err != nil {
|
if tt.Err != nil {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, tt.Err, err)
|
assert.Equal(t, tt.Err, err)
|
||||||
} else {
|
} else {
|
||||||
assert.Empty(t, err)
|
assert.Empty(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGitCloneExecutorNonFastForwardRef(t *testing.T) {
|
||||||
|
// Simulate the scenario where a remote ref (e.g. a GitHub PR head ref) changes
|
||||||
|
// non-fast-forward between two fetches. Before the fix, the fetch used Force=false,
|
||||||
|
// causing go-git to return ErrForceNeeded and short-circuit the checkout.
|
||||||
|
|
||||||
|
gitConfig()
|
||||||
|
|
||||||
|
// Create a bare "remote" repo with an initial commit on main and a feature branch.
|
||||||
|
remoteDir := t.TempDir()
|
||||||
|
require.NoError(t, gitCmd("init", "--bare", "--initial-branch=main", remoteDir))
|
||||||
|
|
||||||
|
// We need a working clone to push commits from.
|
||||||
|
workDir := t.TempDir()
|
||||||
|
require.NoError(t, gitCmd("clone", remoteDir, workDir))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "checkout", "-b", "main"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "commit", "--allow-empty", "-m", "initial"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "push", "-u", "origin", "main"))
|
||||||
|
|
||||||
|
// Create a feature branch (simulates refs/pull/N/head).
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "checkout", "-b", "feature"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "commit", "--allow-empty", "-m", "feature-1"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "push", "origin", "feature"))
|
||||||
|
|
||||||
|
// First clone via the executor — should succeed and cache the repo.
|
||||||
|
cloneDir := t.TempDir()
|
||||||
|
clone := NewGitCloneExecutor(NewGitCloneExecutorInput{
|
||||||
|
URL: remoteDir,
|
||||||
|
Ref: "main",
|
||||||
|
Dir: cloneDir,
|
||||||
|
})
|
||||||
|
require.NoError(t, clone(context.Background()))
|
||||||
|
|
||||||
|
// Now force-push the feature branch to a non-fast-forward commit (simulates
|
||||||
|
// a PR rebase). This makes refs/heads/feature non-fast-forward.
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "checkout", "main"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "branch", "-D", "feature"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "checkout", "-b", "feature"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "commit", "--allow-empty", "-m", "feature-rewritten"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "push", "--force", "origin", "feature"))
|
||||||
|
|
||||||
|
// Also advance main so we can verify the clone picks up the new commit.
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "checkout", "main"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "commit", "--allow-empty", "-m", "second"))
|
||||||
|
require.NoError(t, gitCmd("-C", workDir, "push", "origin", "main"))
|
||||||
|
|
||||||
|
// Second clone to the same directory — before the fix this returned ErrForceNeeded
|
||||||
|
// and left the working tree at the old commit.
|
||||||
|
err := clone(context.Background())
|
||||||
|
require.NoError(t, err, "fetch with non-fast-forward refs must not fail when Force=true")
|
||||||
|
|
||||||
|
// Verify the working tree was actually updated to the latest main commit.
|
||||||
|
out, err := exec.Command("git", "-C", cloneDir, "log", "--oneline", "-1", "--format=%s").Output()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "second", strings.TrimSpace(string(out)), "working tree should be at the latest commit")
|
||||||
|
}
|
||||||
|
|
||||||
func gitConfig() {
|
func gitConfig() {
|
||||||
if os.Getenv("GITHUB_ACTIONS") == "true" {
|
if os.Getenv("GITHUB_ACTIONS") == "true" {
|
||||||
var err error
|
var err error
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2021 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -18,7 +22,7 @@ func TestLineWriter(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
write := func(s string) {
|
write := func(s string) {
|
||||||
n, err := lineWriter.Write([]byte(s))
|
n, err := lineWriter.Write([]byte(s))
|
||||||
assert.NoError(err)
|
assert.NoError(err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(len(s), n, s)
|
assert.Equal(len(s), n, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2021 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
File renamed without changes.
@@ -1,11 +1,16 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2023 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewContainerInput the input for the New function
|
// NewContainerInput the input for the New function
|
||||||
@@ -45,11 +50,11 @@ type FileEntry struct {
|
|||||||
|
|
||||||
// Container for managing docker run containers
|
// Container for managing docker run containers
|
||||||
type Container interface {
|
type Container interface {
|
||||||
Create(capAdd []string, capDrop []string) common.Executor
|
Create(capAdd, capDrop []string) common.Executor
|
||||||
ConnectToNetwork(name string) common.Executor
|
ConnectToNetwork(name string) common.Executor
|
||||||
Copy(destPath string, files ...*FileEntry) common.Executor
|
Copy(destPath string, files ...*FileEntry) common.Executor
|
||||||
CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error
|
CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error
|
||||||
CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor
|
CopyDir(destPath, srcPath string, useGitIgnore bool) common.Executor
|
||||||
GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error)
|
GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error)
|
||||||
Pull(forcePull bool) common.Executor
|
Pull(forcePull bool) common.Executor
|
||||||
Start(attach bool) common.Executor
|
Start(attach bool) common.Executor
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2021 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -6,10 +10,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config"
|
"github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/cli/cli/config/credentials"
|
"github.com/docker/cli/cli/config/credentials"
|
||||||
"github.com/docker/docker/api/types/registry"
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadDockerAuthConfig(ctx context.Context, image string) (registry.AuthConfig, error) {
|
func LoadDockerAuthConfig(ctx context.Context, image string) (registry.AuthConfig, error) {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -8,14 +12,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
|
|
||||||
// github.com/docker/docker/builder/dockerignore is deprecated
|
// github.com/docker/docker/builder/dockerignore is deprecated
|
||||||
"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
|
"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
|
||||||
"github.com/moby/patternmatcher"
|
"github.com/moby/patternmatcher"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDockerBuildExecutor function to create a run executor for the container
|
// NewDockerBuildExecutor function to create a run executor for the container
|
||||||
@@ -69,7 +72,8 @@ func NewDockerBuildExecutor(input NewDockerBuildExecutorInput) common.Executor {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func createBuildContext(ctx context.Context, contextDir string, relDockerfile string) (io.ReadCloser, error) {
|
|
||||||
|
func createBuildContext(ctx context.Context, contextDir, relDockerfile string) (io.ReadCloser, error) {
|
||||||
common.Logger(ctx).Debugf("Creating archive for build context dir '%s' with relative dockerfile '%s'", contextDir, relDockerfile)
|
common.Logger(ctx).Debugf("Creating archive for build context dir '%s' with relative dockerfile '%s'", contextDir, relDockerfile)
|
||||||
|
|
||||||
// And canonicalize dockerfile name to a platform-independent one
|
// And canonicalize dockerfile name to a platform-independent one
|
||||||
@@ -83,7 +87,7 @@ func createBuildContext(ctx context.Context, contextDir string, relDockerfile st
|
|||||||
|
|
||||||
var excludes []string
|
var excludes []string
|
||||||
if err == nil {
|
if err == nil {
|
||||||
excludes, err = dockerignore.ReadAll(f)
|
excludes, err = dockerignore.ReadAll(f) //nolint:staticcheck // pre-existing issue from nektos/act
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -96,7 +100,7 @@ func createBuildContext(ctx context.Context, contextDir string, relDockerfile st
|
|||||||
// removed. The daemon will remove them for us, if needed, after it
|
// removed. The daemon will remove them for us, if needed, after it
|
||||||
// parses the Dockerfile. Ignore errors here, as they will have been
|
// parses the Dockerfile. Ignore errors here, as they will have been
|
||||||
// caught by validateContextDirectory above.
|
// caught by validateContextDirectory above.
|
||||||
var includes = []string{"."}
|
includes := []string{"."}
|
||||||
keepThem1, _ := patternmatcher.Matches(".dockerignore", excludes)
|
keepThem1, _ := patternmatcher.Matches(".dockerignore", excludes)
|
||||||
keepThem2, _ := patternmatcher.Matches(relDockerfile, excludes)
|
keepThem2, _ := patternmatcher.Matches(relDockerfile, excludes)
|
||||||
if keepThem1 || keepThem2 {
|
if keepThem1 || keepThem2 {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
// This file is exact copy of https://github.com/docker/cli/blob/9ac8584acfd501c3f4da0e845e3a40ed15c85041/cli/command/container/opts.go
|
// This file is exact copy of https://github.com/docker/cli/blob/9ac8584acfd501c3f4da0e845e3a40ed15c85041/cli/command/container/opts.go
|
||||||
@@ -7,7 +11,7 @@
|
|||||||
// See DOCKER_LICENSE for the full license text.
|
// See DOCKER_LICENSE for the full license text.
|
||||||
//
|
//
|
||||||
|
|
||||||
//nolint:unparam,errcheck,depguard,deadcode,unused
|
//nolint:errcheck,depguard,unused // verbatim copy from docker/cli with minimal changes
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -19,6 +23,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -37,9 +42,7 @@ import (
|
|||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var deviceCgroupRuleRegexp = regexp.MustCompile(`^[acb] ([0-9]+|\*):([0-9]+|\*) [rwm]{1,3}$`)
|
||||||
deviceCgroupRuleRegexp = regexp.MustCompile(`^[acb] ([0-9]+|\*):([0-9]+|\*) [rwm]{1,3}$`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// containerOptions is a data object with all the options for creating a container
|
// containerOptions is a data object with all the options for creating a container
|
||||||
type containerOptions struct {
|
type containerOptions struct {
|
||||||
@@ -322,7 +325,7 @@ type containerConfig struct {
|
|||||||
// a HostConfig and returns them with the specified command.
|
// a HostConfig and returns them with the specified command.
|
||||||
// If the specified args are not valid, it will return an error.
|
// If the specified args are not valid, it will return an error.
|
||||||
//
|
//
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo // function handles many cases
|
||||||
func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*containerConfig, error) {
|
func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*containerConfig, error) {
|
||||||
var (
|
var (
|
||||||
attachStdin = copts.attach.Get("stdin")
|
attachStdin = copts.attach.Get("stdin")
|
||||||
@@ -559,7 +562,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
|||||||
return nil, errors.Errorf("--health-retries cannot be negative")
|
return nil, errors.Errorf("--health-retries cannot be negative")
|
||||||
}
|
}
|
||||||
if copts.healthStartPeriod < 0 {
|
if copts.healthStartPeriod < 0 {
|
||||||
return nil, fmt.Errorf("--health-start-period cannot be negative")
|
return nil, errors.New("--health-start-period cannot be negative")
|
||||||
}
|
}
|
||||||
|
|
||||||
healthConfig = &container.HealthConfig{
|
healthConfig = &container.HealthConfig{
|
||||||
@@ -722,7 +725,6 @@ func parseNetworkOpts(copts *containerOptions) (map[string]*networktypes.Endpoin
|
|||||||
)
|
)
|
||||||
|
|
||||||
for i, n := range copts.netMode.Value() {
|
for i, n := range copts.netMode.Value() {
|
||||||
n := n
|
|
||||||
if container.NetworkMode(n.Target).IsUserDefined() {
|
if container.NetworkMode(n.Target).IsUserDefined() {
|
||||||
hasUserDefined = true
|
hasUserDefined = true
|
||||||
} else {
|
} else {
|
||||||
@@ -837,7 +839,7 @@ func convertToStandardNotation(ports []string) ([]string, error) {
|
|||||||
for _, publish := range ports {
|
for _, publish := range ports {
|
||||||
if strings.Contains(publish, "=") {
|
if strings.Contains(publish, "=") {
|
||||||
params := map[string]string{"protocol": "tcp"}
|
params := map[string]string{"protocol": "tcp"}
|
||||||
for _, param := range strings.Split(publish, ",") {
|
for param := range strings.SplitSeq(publish, ",") {
|
||||||
opt := strings.Split(param, "=")
|
opt := strings.Split(param, "=")
|
||||||
if len(opt) < 2 {
|
if len(opt) < 2 {
|
||||||
return optsList, errors.Errorf("invalid publish opts format (should be name=value but got '%s')", param)
|
return optsList, errors.Errorf("invalid publish opts format (should be name=value but got '%s')", param)
|
||||||
@@ -988,7 +990,7 @@ func validateDeviceCgroupRule(val string) (string, error) {
|
|||||||
// validDeviceMode checks if the mode for device is valid or not.
|
// validDeviceMode checks if the mode for device is valid or not.
|
||||||
// Valid mode is a composition of r (read), w (write), and m (mknod).
|
// Valid mode is a composition of r (read), w (write), and m (mknod).
|
||||||
func validDeviceMode(mode string) bool {
|
func validDeviceMode(mode string) bool {
|
||||||
var legalDeviceMode = map[rune]bool{
|
legalDeviceMode := map[rune]bool{
|
||||||
'r': true,
|
'r': true,
|
||||||
'w': true,
|
'w': true,
|
||||||
'm': true,
|
'm': true,
|
||||||
@@ -1006,7 +1008,7 @@ func validDeviceMode(mode string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validateDevice validates a path for devices
|
// validateDevice validates a path for devices
|
||||||
func validateDevice(val string, serverOS string) (string, error) {
|
func validateDevice(val, serverOS string) (string, error) {
|
||||||
switch serverOS {
|
switch serverOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
return validateLinuxPath(val, validDeviceMode)
|
return validateLinuxPath(val, validDeviceMode)
|
||||||
@@ -1067,10 +1069,8 @@ func validateLinuxPath(val string, validator func(string) bool) (string, error)
|
|||||||
// validateAttach validates that the specified string is a valid attach option.
|
// validateAttach validates that the specified string is a valid attach option.
|
||||||
func validateAttach(val string) (string, error) {
|
func validateAttach(val string) (string, error) {
|
||||||
s := strings.ToLower(val)
|
s := strings.ToLower(val)
|
||||||
for _, str := range []string{"stdin", "stdout", "stderr"} {
|
if slices.Contains([]string{"stdin", "stdout", "stderr"}, s) {
|
||||||
if s == str {
|
return s, nil
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR")
|
return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR")
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
// This file is exact copy of https://github.com/docker/cli/blob/9ac8584acfd501c3f4da0e845e3a40ed15c85041/cli/command/container/opts_test.go with:
|
// This file is exact copy of https://github.com/docker/cli/blob/9ac8584acfd501c3f4da0e845e3a40ed15c85041/cli/command/container/opts_test.go with:
|
||||||
// * appended with license information
|
// * appended with license information
|
||||||
// * commented out case 'invalid-mixed-network-types' in test TestParseNetworkConfig
|
// * commented out case 'invalid-mixed-network-types' in test TestParseNetworkConfig
|
||||||
@@ -6,7 +10,7 @@
|
|||||||
// See DOCKER_LICENSE for the full license text.
|
// See DOCKER_LICENSE for the full license text.
|
||||||
//
|
//
|
||||||
|
|
||||||
//nolint:unparam,whitespace,depguard,dupl,gocritic
|
//nolint:depguard,gocritic // verbatim copy from docker/cli tests
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -135,7 +139,6 @@ func TestParseRunAttach(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.input, func(t *testing.T) {
|
t.Run(tc.input, func(t *testing.T) {
|
||||||
config, _ := mustParse(t, tc.input)
|
config, _ := mustParse(t, tc.input)
|
||||||
assert.Equal(t, config.AttachStdin, tc.expected.AttachStdin)
|
assert.Equal(t, config.AttachStdin, tc.expected.AttachStdin)
|
||||||
@@ -191,9 +194,8 @@ func TestParseRunWithInvalidArgs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo // function handles many cases
|
||||||
func TestParseWithVolumes(t *testing.T) {
|
func TestParseWithVolumes(t *testing.T) {
|
||||||
|
|
||||||
// A single volume
|
// A single volume
|
||||||
arr, tryit := setupPlatformVolume([]string{`/tmp`}, []string{`c:\tmp`})
|
arr, tryit := setupPlatformVolume([]string{`/tmp`}, []string{`c:\tmp`})
|
||||||
if config, hostConfig := mustParse(t, tryit); hostConfig.Binds != nil {
|
if config, hostConfig := mustParse(t, tryit); hostConfig.Binds != nil {
|
||||||
@@ -261,14 +263,13 @@ func TestParseWithVolumes(t *testing.T) {
|
|||||||
t.Fatalf("Error parsing %s. Should have a single bind mount and no volumes", arr[0])
|
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
|
// setupPlatformVolume takes two arrays of volume specs - a Unix style
|
||||||
// spec and a Windows style spec. Depending on the platform being unit tested,
|
// spec and a Windows style spec. Depending on the platform being unit tested,
|
||||||
// it returns one of them, along with a volume string that would be passed
|
// it returns one of them, along with a volume string that would be passed
|
||||||
// on the docker CLI (e.g. -v /bar -v /foo).
|
// on the docker CLI (e.g. -v /bar -v /foo).
|
||||||
func setupPlatformVolume(u []string, w []string) ([]string, string) {
|
func setupPlatformVolume(u, w []string) ([]string, string) {
|
||||||
var a []string
|
var a []string
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
a = w
|
a = w
|
||||||
@@ -301,8 +302,8 @@ func TestParseWithMacAddress(t *testing.T) {
|
|||||||
if _, _, _, err := parseRun([]string{invalidMacAddress, "img", "cmd"}); err != nil && err.Error() != "invalidMacAddress is not a valid mac address" {
|
if _, _, _, err := parseRun([]string{invalidMacAddress, "img", "cmd"}); err != nil && err.Error() != "invalidMacAddress is not a valid mac address" {
|
||||||
t.Fatalf("Expected an error with %v mac-address, got %v", invalidMacAddress, err)
|
t.Fatalf("Expected an error with %v mac-address, got %v", invalidMacAddress, err)
|
||||||
}
|
}
|
||||||
if config, _ := mustParse(t, validMacAddress); config.MacAddress != "92:d0:c6:0a:29:33" {
|
if config, _ := mustParse(t, validMacAddress); config.MacAddress != "92:d0:c6:0a:29:33" { //nolint:staticcheck // pre-existing issue from nektos/act
|
||||||
t.Fatalf("Expected the config to have '92:d0:c6:0a:29:33' as MacAddress, got '%v'", config.MacAddress)
|
t.Fatalf("Expected the config to have '92:d0:c6:0a:29:33' as MacAddress, got '%v'", config.MacAddress) //nolint:staticcheck // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +341,7 @@ func TestParseHostname(t *testing.T) {
|
|||||||
hostnameWithDomain := "--hostname=hostname.domainname"
|
hostnameWithDomain := "--hostname=hostname.domainname"
|
||||||
hostnameWithDomainTld := "--hostname=hostname.domainname.tld"
|
hostnameWithDomainTld := "--hostname=hostname.domainname.tld"
|
||||||
for hostname, expectedHostname := range validHostnames {
|
for hostname, expectedHostname := range validHostnames {
|
||||||
if config, _ := mustParse(t, fmt.Sprintf("--hostname=%s", hostname)); config.Hostname != expectedHostname {
|
if config, _ := mustParse(t, "--hostname="+hostname); config.Hostname != expectedHostname {
|
||||||
t.Fatalf("Expected the config to have 'hostname' as %q, got %q", expectedHostname, config.Hostname)
|
t.Fatalf("Expected the config to have 'hostname' as %q, got %q", expectedHostname, config.Hostname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,8 +378,6 @@ func TestParseWithExpose(t *testing.T) {
|
|||||||
invalids := map[string]string{
|
invalids := map[string]string{
|
||||||
":": "invalid port format for --expose: :",
|
":": "invalid port format for --expose: :",
|
||||||
"8080:9090": "invalid port format for --expose: 8080:9090",
|
"8080:9090": "invalid port format for --expose: 8080:9090",
|
||||||
"/tcp": "invalid range format for --expose: /tcp, error: Empty string specified for ports.",
|
|
||||||
"/udp": "invalid range format for --expose: /udp, error: Empty string specified for ports.",
|
|
||||||
"NaN/tcp": `invalid range format for --expose: NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`,
|
"NaN/tcp": `invalid range format for --expose: NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`,
|
||||||
"NaN-NaN/tcp": `invalid range format for --expose: NaN-NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`,
|
"NaN-NaN/tcp": `invalid range format for --expose: NaN-NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`,
|
||||||
"8080-NaN/tcp": `invalid range format for --expose: 8080-NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`,
|
"8080-NaN/tcp": `invalid range format for --expose: 8080-NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`,
|
||||||
@@ -462,7 +461,6 @@ func TestParseDevice(t *testing.T) {
|
|||||||
t.Fatalf("Expected %v, got %v", deviceMapping, hostconfig.Devices)
|
t.Fatalf("Expected %v, got %v", deviceMapping, hostconfig.Devices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseNetworkConfig(t *testing.T) {
|
func TestParseNetworkConfig(t *testing.T) {
|
||||||
@@ -634,7 +632,7 @@ func TestParseModes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// uts ko
|
// uts ko
|
||||||
_, _, _, err = parseRun([]string{"--uts=container:", "img", "cmd"}) //nolint:dogsled
|
_, _, _, err = parseRun([]string{"--uts=container:", "img", "cmd"}) //nolint:dogsled // ignoring multiple returns in test helpers
|
||||||
assert.ErrorContains(t, err, "--uts: invalid UTS mode")
|
assert.ErrorContains(t, err, "--uts: invalid UTS mode")
|
||||||
|
|
||||||
// uts ok
|
// uts ok
|
||||||
@@ -678,7 +676,7 @@ func TestParseRestartPolicy(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for restart, expectedError := range invalids {
|
for restart, expectedError := range invalids {
|
||||||
if _, _, _, err := parseRun([]string{fmt.Sprintf("--restart=%s", restart), "img", "cmd"}); err == nil || err.Error() != expectedError {
|
if _, _, _, err := parseRun([]string{"--restart=" + restart, "img", "cmd"}); err == nil || err.Error() != expectedError {
|
||||||
t.Fatalf("Expected an error with message '%v' for %v, got %v", expectedError, restart, err)
|
t.Fatalf("Expected an error with message '%v' for %v, got %v", expectedError, restart, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -695,7 +693,7 @@ func TestParseRestartPolicy(t *testing.T) {
|
|||||||
|
|
||||||
func TestParseRestartPolicyAutoRemove(t *testing.T) {
|
func TestParseRestartPolicyAutoRemove(t *testing.T) {
|
||||||
expected := "Conflicting options: --restart and --rm"
|
expected := "Conflicting options: --restart and --rm"
|
||||||
_, _, _, err := parseRun([]string{"--rm", "--restart=always", "img", "cmd"}) //nolint:dogsled
|
_, _, _, err := parseRun([]string{"--rm", "--restart=always", "img", "cmd"}) //nolint:dogsled // ignoring multiple returns in test helpers
|
||||||
if err == nil || err.Error() != expected {
|
if err == nil || err.Error() != expected {
|
||||||
t.Fatalf("Expected error %v, but got none", expected)
|
t.Fatalf("Expected error %v, but got none", expected)
|
||||||
}
|
}
|
||||||
@@ -755,7 +753,7 @@ func TestParseLoggingOpts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseEnvfileVariables(t *testing.T) {
|
func TestParseEnvfileVariables(t *testing.T) { //nolint:dupl // pre-existing issue from nektos/act
|
||||||
e := "open nonexistent: no such file or directory"
|
e := "open nonexistent: no such file or directory"
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
e = "open nonexistent: The system cannot find the file specified."
|
e = "open nonexistent: The system cannot find the file specified."
|
||||||
@@ -808,7 +806,7 @@ func TestParseEnvfileVariablesWithBOMUnicode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseLabelfileVariables(t *testing.T) {
|
func TestParseLabelfileVariables(t *testing.T) { //nolint:dupl // pre-existing issue from nektos/act
|
||||||
e := "open nonexistent: no such file or directory"
|
e := "open nonexistent: no such file or directory"
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
e = "open nonexistent: The system cannot find the file specified."
|
e = "open nonexistent: The system cannot find the file specified."
|
||||||
@@ -967,7 +965,6 @@ func TestConvertToStandardNotation(t *testing.T) {
|
|||||||
|
|
||||||
for key, ports := range valid {
|
for key, ports := range valid {
|
||||||
convertedPorts, err := convertToStandardNotation(ports)
|
convertedPorts, err := convertToStandardNotation(ports)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -12,7 +16,7 @@ import (
|
|||||||
|
|
||||||
// ImageExistsLocally returns a boolean indicating if an image with the
|
// ImageExistsLocally returns a boolean indicating if an image with the
|
||||||
// requested name, tag and architecture exists in the local docker image store
|
// requested name, tag and architecture exists in the local docker image store
|
||||||
func ImageExistsLocally(ctx context.Context, imageName string, platform string) (bool, error) {
|
func ImageExistsLocally(ctx context.Context, imageName, platform string) (bool, error) {
|
||||||
cli, err := GetDockerClient(ctx)
|
cli, err := GetDockerClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -35,7 +39,7 @@ func ImageExistsLocally(ctx context.Context, imageName string, platform string)
|
|||||||
|
|
||||||
// RemoveImage removes image from local store, the function is used to run different
|
// RemoveImage removes image from local store, the function is used to run different
|
||||||
// container image architectures
|
// container image architectures
|
||||||
func RemoveImage(ctx context.Context, imageName string, force bool, pruneChildren bool) (bool, error) {
|
func RemoveImage(ctx context.Context, imageName string, force, pruneChildren bool) (bool, error) {
|
||||||
cli, err := GetDockerClient(ctx)
|
cli, err := GetDockerClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -25,17 +29,17 @@ func TestImageExistsLocally(t *testing.T) {
|
|||||||
|
|
||||||
// Test if image exists with specific tag
|
// Test if image exists with specific tag
|
||||||
invalidImageTag, err := ImageExistsLocally(ctx, "library/alpine:this-random-tag-will-never-exist", "linux/amd64")
|
invalidImageTag, err := ImageExistsLocally(ctx, "library/alpine:this-random-tag-will-never-exist", "linux/amd64")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, false, invalidImageTag)
|
assert.Equal(t, false, invalidImageTag) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// Test if image exists with specific architecture (image platform)
|
// Test if image exists with specific architecture (image platform)
|
||||||
invalidImagePlatform, err := ImageExistsLocally(ctx, "alpine:latest", "windows/amd64")
|
invalidImagePlatform, err := ImageExistsLocally(ctx, "alpine:latest", "windows/amd64")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, false, invalidImagePlatform)
|
assert.Equal(t, false, invalidImagePlatform) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// pull an image
|
// pull an image
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
cli.NegotiateAPIVersion(context.Background())
|
cli.NegotiateAPIVersion(context.Background())
|
||||||
|
|
||||||
// Chose alpine latest because it's so small
|
// Chose alpine latest because it's so small
|
||||||
@@ -43,25 +47,25 @@ func TestImageExistsLocally(t *testing.T) {
|
|||||||
readerDefault, err := cli.ImagePull(ctx, "node:16-buster-slim", types.ImagePullOptions{
|
readerDefault, err := cli.ImagePull(ctx, "node:16-buster-slim", types.ImagePullOptions{
|
||||||
Platform: "linux/amd64",
|
Platform: "linux/amd64",
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
defer readerDefault.Close()
|
defer readerDefault.Close()
|
||||||
_, err = io.ReadAll(readerDefault)
|
_, err = io.ReadAll(readerDefault)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
imageDefaultArchExists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/amd64")
|
imageDefaultArchExists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/amd64")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, true, imageDefaultArchExists)
|
assert.Equal(t, true, imageDefaultArchExists) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
// Validate if another architecture platform can be pulled
|
// Validate if another architecture platform can be pulled
|
||||||
readerArm64, err := cli.ImagePull(ctx, "node:16-buster-slim", types.ImagePullOptions{
|
readerArm64, err := cli.ImagePull(ctx, "node:16-buster-slim", types.ImagePullOptions{
|
||||||
Platform: "linux/arm64",
|
Platform: "linux/arm64",
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
defer readerArm64.Close()
|
defer readerArm64.Close()
|
||||||
_, err = io.ReadAll(readerArm64)
|
_, err = io.ReadAll(readerArm64)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
imageArm64Exists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/arm64")
|
imageArm64Exists, err := ImageExistsLocally(ctx, "node:16-buster-slim", "linux/arm64")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, true, imageArm64Exists)
|
assert.Equal(t, true, imageArm64Exists) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -74,7 +78,7 @@ func logDockerResponse(logger logrus.FieldLogger, dockerResponse io.ReadCloser,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeLog(logger logrus.FieldLogger, isError bool, format string, args ...interface{}) {
|
func writeLog(logger logrus.FieldLogger, isError bool, format string, args ...any) {
|
||||||
if isError {
|
if isError {
|
||||||
logger.Errorf(format, args...)
|
logger.Errorf(format, args...)
|
||||||
} else {
|
} else {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2023 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -5,9 +9,9 @@ package container
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/docker/docker/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDockerNetworkCreateExecutor(name string) common.Executor {
|
func NewDockerNetworkCreateExecutor(name string) common.Executor {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -9,11 +13,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
|
"github.com/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/registry"
|
"github.com/docker/docker/api/types/registry"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDockerPullExecutor function to create a run executor for the container
|
// NewDockerPullExecutor function to create a run executor for the container
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -5,7 +9,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config"
|
"github.com/docker/cli/cli/config"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
assert "github.com/stretchr/testify/assert"
|
assert "github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -40,15 +43,15 @@ func TestGetImagePullOptions(t *testing.T) {
|
|||||||
config.SetDir("/non-existent/docker")
|
config.SetDir("/non-existent/docker")
|
||||||
|
|
||||||
options, err := getImagePullOptions(ctx, NewDockerPullExecutorInput{})
|
options, err := getImagePullOptions(ctx, NewDockerPullExecutorInput{})
|
||||||
assert.Nil(t, err, "Failed to create ImagePullOptions")
|
assert.Nil(t, err, "Failed to create ImagePullOptions") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, "", options.RegistryAuth, "RegistryAuth should be empty if no username or password is set")
|
assert.Equal(t, "", options.RegistryAuth, "RegistryAuth should be empty if no username or password is set") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
|
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
|
||||||
Image: "",
|
Image: "",
|
||||||
Username: "username",
|
Username: "username",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
})
|
})
|
||||||
assert.Nil(t, err, "Failed to create ImagePullOptions")
|
assert.Nil(t, err, "Failed to create ImagePullOptions") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9", options.RegistryAuth, "Username and Password should be provided")
|
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9", options.RegistryAuth, "Username and Password should be provided")
|
||||||
|
|
||||||
config.SetDir("testdata/docker-pull-options")
|
config.SetDir("testdata/docker-pull-options")
|
||||||
@@ -56,6 +59,6 @@ func TestGetImagePullOptions(t *testing.T) {
|
|||||||
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
|
options, err = getImagePullOptions(ctx, NewDockerPullExecutorInput{
|
||||||
Image: "nektos/act",
|
Image: "nektos/act",
|
||||||
})
|
})
|
||||||
assert.Nil(t, err, "Failed to create ImagePullOptions")
|
assert.Nil(t, err, "Failed to create ImagePullOptions") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZFxuIiwic2VydmVyYWRkcmVzcyI6Imh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyJ9", options.RegistryAuth, "RegistryAuth should be taken from local docker config")
|
assert.Equal(t, "eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZFxuIiwic2VydmVyYWRkcmVzcyI6Imh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyJ9", options.RegistryAuth, "RegistryAuth should be taken from local docker config")
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -16,6 +20,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
"gitea.com/gitea/act_runner/act/filecollector"
|
||||||
|
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
"github.com/docker/cli/cli/compose/loader"
|
"github.com/docker/cli/cli/compose/loader"
|
||||||
"github.com/docker/cli/cli/connhelper"
|
"github.com/docker/cli/cli/connhelper"
|
||||||
@@ -23,7 +30,6 @@ import (
|
|||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/mount"
|
"github.com/docker/docker/api/types/mount"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
networktypes "github.com/docker/docker/api/types/network"
|
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/pkg/stdcopy"
|
"github.com/docker/docker/pkg/stdcopy"
|
||||||
"github.com/go-git/go-billy/v5/helper/polyfill"
|
"github.com/go-git/go-billy/v5/helper/polyfill"
|
||||||
@@ -36,9 +42,6 @@ import (
|
|||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
"github.com/nektos/act/pkg/filecollector"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewContainer creates a reference to a container
|
// NewContainer creates a reference to a container
|
||||||
@@ -61,7 +64,7 @@ func (cr *containerReference) ConnectToNetwork(name string) common.Executor {
|
|||||||
|
|
||||||
func (cr *containerReference) connectToNetwork(name string, aliases []string) common.Executor {
|
func (cr *containerReference) connectToNetwork(name string, aliases []string) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
return cr.cli.NetworkConnect(ctx, name, cr.input.Name, &networktypes.EndpointSettings{
|
return cr.cli.NetworkConnect(ctx, name, cr.input.Name, &network.EndpointSettings{
|
||||||
Aliases: aliases,
|
Aliases: aliases,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -85,7 +88,7 @@ func supportsContainerImagePlatform(ctx context.Context, cli client.APIClient) b
|
|||||||
return constraint.Check(sv)
|
return constraint.Check(sv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerReference) Create(capAdd []string, capDrop []string) common.Executor {
|
func (cr *containerReference) Create(capAdd, capDrop []string) common.Executor {
|
||||||
return common.
|
return common.
|
||||||
NewInfoExecutor("%sdocker create image=%s platform=%s entrypoint=%+q cmd=%+q network=%+q", logPrefix, cr.input.Image, cr.input.Platform, cr.input.Entrypoint, cr.input.Cmd, cr.input.NetworkMode).
|
NewInfoExecutor("%sdocker create image=%s platform=%s entrypoint=%+q cmd=%+q network=%+q", logPrefix, cr.input.Image, cr.input.Platform, cr.input.Entrypoint, cr.input.Cmd, cr.input.NetworkMode).
|
||||||
Then(
|
Then(
|
||||||
@@ -142,7 +145,7 @@ func (cr *containerReference) Copy(destPath string, files ...*FileEntry) common.
|
|||||||
).IfNot(common.Dryrun)
|
).IfNot(common.Dryrun)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerReference) CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor {
|
func (cr *containerReference) CopyDir(destPath, srcPath string, useGitIgnore bool) common.Executor {
|
||||||
return common.NewPipelineExecutor(
|
return common.NewPipelineExecutor(
|
||||||
common.NewInfoExecutor("%sdocker cp src=%s dst=%s", logPrefix, srcPath, destPath),
|
common.NewInfoExecutor("%sdocker cp src=%s dst=%s", logPrefix, srcPath, destPath),
|
||||||
cr.copyDir(destPath, srcPath, useGitIgnore),
|
cr.copyDir(destPath, srcPath, useGitIgnore),
|
||||||
@@ -158,7 +161,7 @@ func (cr *containerReference) CopyDir(destPath string, srcPath string, useGitIgn
|
|||||||
|
|
||||||
func (cr *containerReference) GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error) {
|
func (cr *containerReference) GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error) {
|
||||||
if common.Dryrun(ctx) {
|
if common.Dryrun(ctx) {
|
||||||
return nil, fmt.Errorf("DRYRUN is not supported in GetContainerArchive")
|
return nil, errors.New("DRYRUN is not supported in GetContainerArchive")
|
||||||
}
|
}
|
||||||
a, _, err := cr.cli.CopyFromContainer(ctx, cr.id, srcPath)
|
a, _, err := cr.cli.CopyFromContainer(ctx, cr.id, srcPath)
|
||||||
return a, err
|
return a, err
|
||||||
@@ -190,7 +193,7 @@ func (cr *containerReference) Remove() common.Executor {
|
|||||||
).IfNot(common.Dryrun)
|
).IfNot(common.Dryrun)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerReference) ReplaceLogWriter(stdout io.Writer, stderr io.Writer) (io.Writer, io.Writer) {
|
func (cr *containerReference) ReplaceLogWriter(stdout, stderr io.Writer) (io.Writer, io.Writer) {
|
||||||
out := cr.input.Stdout
|
out := cr.input.Stdout
|
||||||
err := cr.input.Stderr
|
err := cr.input.Stderr
|
||||||
|
|
||||||
@@ -234,7 +237,7 @@ func GetDockerClient(ctx context.Context) (cli client.APIClient, err error) {
|
|||||||
return cli, nil
|
return cli, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHostInfo(ctx context.Context) (info types.Info, err error) {
|
func GetHostInfo(ctx context.Context) (info types.Info, err error) { //nolint:staticcheck // pre-existing issue from nektos/act
|
||||||
var cli client.APIClient
|
var cli client.APIClient
|
||||||
cli, err = GetDockerClient(ctx)
|
cli, err = GetDockerClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -304,7 +307,7 @@ func (cr *containerReference) find() common.Executor {
|
|||||||
if cr.id != "" {
|
if cr.id != "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
containers, err := cr.cli.ContainerList(ctx, types.ContainerListOptions{
|
containers, err := cr.cli.ContainerList(ctx, types.ContainerListOptions{ //nolint:staticcheck // pre-existing issue from nektos/act
|
||||||
All: true,
|
All: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -332,7 +335,7 @@ func (cr *containerReference) remove() common.Executor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
err := cr.cli.ContainerRemove(ctx, cr.id, types.ContainerRemoveOptions{
|
err := cr.cli.ContainerRemove(ctx, cr.id, types.ContainerRemoveOptions{ //nolint:staticcheck // pre-existing issue from nektos/act
|
||||||
RemoveVolumes: true,
|
RemoveVolumes: true,
|
||||||
Force: true,
|
Force: true,
|
||||||
})
|
})
|
||||||
@@ -429,7 +432,7 @@ func (cr *containerReference) mergeContainerConfigs(ctx context.Context, config
|
|||||||
return config, hostConfig, nil
|
return config, hostConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerReference) create(capAdd []string, capDrop []string) common.Executor {
|
func (cr *containerReference) create(capAdd, capDrop []string) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
if cr.id != "" {
|
if cr.id != "" {
|
||||||
return nil
|
return nil
|
||||||
@@ -682,7 +685,7 @@ func (cr *containerReference) tryReadGID() common.Executor {
|
|||||||
return cr.tryReadID("-g", func(id int) { cr.GID = id })
|
return cr.tryReadID("-g", func(id int) { cr.GID = id })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerReference) waitForCommand(ctx context.Context, isTerminal bool, resp types.HijackedResponse, _ types.IDResponse, _ string, _ string) error {
|
func (cr *containerReference) waitForCommand(ctx context.Context, isTerminal bool, resp types.HijackedResponse, _ types.IDResponse, _, _ string) error {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
|
|
||||||
cmdResponse := make(chan error)
|
cmdResponse := make(chan error)
|
||||||
@@ -753,7 +756,7 @@ func (cr *containerReference) CopyTarStream(ctx context.Context, destPath string
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerReference) copyDir(dstPath string, srcPath string, useGitIgnore bool) common.Executor {
|
func (cr *containerReference) copyDir(dstPath, srcPath string, useGitIgnore bool) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
tarFile, err := os.CreateTemp("", "act")
|
tarFile, err := os.CreateTemp("", "act")
|
||||||
@@ -860,7 +863,7 @@ func (cr *containerReference) copyContent(dstPath string, files ...*FileEntry) c
|
|||||||
|
|
||||||
func (cr *containerReference) attach() common.Executor {
|
func (cr *containerReference) attach() common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
out, err := cr.cli.ContainerAttach(ctx, cr.id, types.ContainerAttachOptions{
|
out, err := cr.cli.ContainerAttach(ctx, cr.id, types.ContainerAttachOptions{ //nolint:staticcheck // pre-existing issue from nektos/act
|
||||||
Stream: true,
|
Stream: true,
|
||||||
Stdout: true,
|
Stdout: true,
|
||||||
Stderr: true,
|
Stderr: true,
|
||||||
@@ -898,7 +901,7 @@ func (cr *containerReference) start() common.Executor {
|
|||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
logger.Debugf("Starting container: %v", cr.id)
|
logger.Debugf("Starting container: %v", cr.id)
|
||||||
|
|
||||||
if err := cr.cli.ContainerStart(ctx, cr.id, types.ContainerStartOptions{}); err != nil {
|
if err := cr.cli.ContainerStart(ctx, cr.id, types.ContainerStartOptions{}); err != nil { //nolint:staticcheck // pre-existing issue from nektos/act
|
||||||
return fmt.Errorf("failed to start container: %w", err)
|
return fmt.Errorf("failed to start container: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,17 +1,21 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
@@ -24,7 +28,7 @@ import (
|
|||||||
func TestDocker(t *testing.T) {
|
func TestDocker(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
client, err := GetDockerClient(ctx)
|
client, err := GetDockerClient(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
dockerBuild := NewDockerBuildExecutor(NewDockerBuildExecutorInput{
|
dockerBuild := NewDockerBuildExecutor(NewDockerBuildExecutorInput{
|
||||||
@@ -33,7 +37,7 @@ func TestDocker(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
err = dockerBuild(ctx)
|
err = dockerBuild(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
cr := &containerReference{
|
cr := &containerReference{
|
||||||
cli: client,
|
cli: client,
|
||||||
@@ -50,7 +54,7 @@ func TestDocker(t *testing.T) {
|
|||||||
|
|
||||||
envExecutor := cr.extractFromImageEnv(&env)
|
envExecutor := cr.extractFromImageEnv(&env)
|
||||||
err = envExecutor(ctx)
|
err = envExecutor(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, map[string]string{
|
assert.Equal(t, map[string]string{
|
||||||
"PATH": "/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:/this/path/does/not/exists/anywhere:/this/either",
|
"PATH": "/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:/this/path/does/not/exists/anywhere:/this/either",
|
||||||
"RANDOM_VAR": "WITH_VALUE",
|
"RANDOM_VAR": "WITH_VALUE",
|
||||||
@@ -81,7 +85,7 @@ func (m *mockDockerClient) ContainerExecInspect(ctx context.Context, execID stri
|
|||||||
return args.Get(0).(types.ContainerExecInspect), args.Error(1)
|
return args.Get(0).(types.ContainerExecInspect), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockDockerClient) CopyToContainer(ctx context.Context, id string, path string, content io.Reader, options types.CopyToContainerOptions) error {
|
func (m *mockDockerClient) CopyToContainer(ctx context.Context, id, path string, content io.Reader, options types.CopyToContainerOptions) error {
|
||||||
args := m.Called(ctx, id, path, content, options)
|
args := m.Called(ctx, id, path, content, options)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
}
|
}
|
||||||
@@ -140,7 +144,7 @@ func TestDockerExecAbort(t *testing.T) {
|
|||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
err := <-channel
|
err := <-channel
|
||||||
assert.ErrorIs(t, err, context.Canceled)
|
assert.ErrorIs(t, err, context.Canceled) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
conn.AssertExpectations(t)
|
conn.AssertExpectations(t)
|
||||||
client.AssertExpectations(t)
|
client.AssertExpectations(t)
|
||||||
@@ -170,7 +174,7 @@ func TestDockerExecFailure(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := cr.exec([]string{""}, map[string]string{}, "user", "workdir")(ctx)
|
err := cr.exec([]string{""}, map[string]string{}, "user", "workdir")(ctx)
|
||||||
assert.Error(t, err, "exit with `FAILURE`: 1")
|
assert.Error(t, err, "exit with `FAILURE`: 1") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
conn.AssertExpectations(t)
|
conn.AssertExpectations(t)
|
||||||
client.AssertExpectations(t)
|
client.AssertExpectations(t)
|
||||||
@@ -203,7 +207,7 @@ func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) {
|
|||||||
|
|
||||||
conn := &mockConn{}
|
conn := &mockConn{}
|
||||||
|
|
||||||
merr := fmt.Errorf("Failure")
|
merr := errors.New("Failure")
|
||||||
|
|
||||||
client := &mockDockerClient{}
|
client := &mockDockerClient{}
|
||||||
client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(merr)
|
client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(merr)
|
||||||
@@ -217,7 +221,7 @@ func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{})
|
err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{})
|
||||||
assert.ErrorIs(t, err, merr)
|
assert.ErrorIs(t, err, merr) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
conn.AssertExpectations(t)
|
conn.AssertExpectations(t)
|
||||||
client.AssertExpectations(t)
|
client.AssertExpectations(t)
|
||||||
@@ -228,7 +232,7 @@ func TestDockerCopyTarStreamErrorInMkdir(t *testing.T) {
|
|||||||
|
|
||||||
conn := &mockConn{}
|
conn := &mockConn{}
|
||||||
|
|
||||||
merr := fmt.Errorf("Failure")
|
merr := errors.New("Failure")
|
||||||
|
|
||||||
client := &mockDockerClient{}
|
client := &mockDockerClient{}
|
||||||
client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(nil)
|
client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(nil)
|
||||||
@@ -242,7 +246,7 @@ func TestDockerCopyTarStreamErrorInMkdir(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{})
|
err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{})
|
||||||
assert.ErrorIs(t, err, merr)
|
assert.ErrorIs(t, err, merr) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
|
|
||||||
conn.AssertExpectations(t)
|
conn.AssertExpectations(t)
|
||||||
client.AssertExpectations(t)
|
client.AssertExpectations(t)
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2024 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -43,8 +47,8 @@ func socketLocation() (string, bool) {
|
|||||||
// indicating that the `daemonPath` is a Docker host URI. If it doesn't, or if the "://" delimiter
|
// indicating that the `daemonPath` is a Docker host URI. If it doesn't, or if the "://" delimiter
|
||||||
// is not found in the `daemonPath`, the function returns false.
|
// is not found in the `daemonPath`, the function returns false.
|
||||||
func isDockerHostURI(daemonPath string) bool {
|
func isDockerHostURI(daemonPath string) bool {
|
||||||
if protoIndex := strings.Index(daemonPath, "://"); protoIndex != -1 {
|
if before, _, ok := strings.Cut(daemonPath, "://"); ok {
|
||||||
scheme := daemonPath[:protoIndex]
|
scheme := before
|
||||||
if strings.IndexFunc(scheme, func(r rune) bool {
|
if strings.IndexFunc(scheme, func(r rune) bool {
|
||||||
return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z')
|
return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z')
|
||||||
}) == -1 {
|
}) == -1 {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2024 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -19,26 +23,26 @@ func TestGetSocketAndHostWithSocket(t *testing.T) {
|
|||||||
CommonSocketLocations = originalCommonSocketLocations
|
CommonSocketLocations = originalCommonSocketLocations
|
||||||
dockerHost := "unix:///my/docker/host.sock"
|
dockerHost := "unix:///my/docker/host.sock"
|
||||||
socketURI := "/path/to/my.socket"
|
socketURI := "/path/to/my.socket"
|
||||||
os.Setenv("DOCKER_HOST", dockerHost)
|
t.Setenv("DOCKER_HOST", dockerHost)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ret, err := GetSocketAndHost(socketURI)
|
ret, err := GetSocketAndHost(socketURI)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, SocketAndHost{socketURI, dockerHost}, ret)
|
assert.Equal(t, SocketAndHost{socketURI, dockerHost}, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSocketAndHostNoSocket(t *testing.T) {
|
func TestGetSocketAndHostNoSocket(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
dockerHost := "unix:///my/docker/host.sock"
|
dockerHost := "unix:///my/docker/host.sock"
|
||||||
os.Setenv("DOCKER_HOST", dockerHost)
|
t.Setenv("DOCKER_HOST", dockerHost)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ret, err := GetSocketAndHost("")
|
ret, err := GetSocketAndHost("")
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, SocketAndHost{dockerHost, dockerHost}, ret)
|
assert.Equal(t, SocketAndHost{dockerHost, dockerHost}, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +57,8 @@ func TestGetSocketAndHostOnlySocket(t *testing.T) {
|
|||||||
ret, err := GetSocketAndHost(socketURI)
|
ret, err := GetSocketAndHost(socketURI)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.NoError(t, err, "Expected no error from GetSocketAndHost")
|
assert.NoError(t, err, "Expected no error from GetSocketAndHost") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, true, defaultSocketFound, "Expected to find default socket")
|
assert.Equal(t, true, defaultSocketFound, "Expected to find default socket") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, socketURI, ret.Socket, "Expected socket to match common location")
|
assert.Equal(t, socketURI, ret.Socket, "Expected socket to match common location")
|
||||||
assert.Equal(t, defaultSocket, ret.Host, "Expected ret.Host to match default socket location")
|
assert.Equal(t, defaultSocket, ret.Host, "Expected ret.Host to match default socket location")
|
||||||
}
|
}
|
||||||
@@ -63,13 +67,13 @@ func TestGetSocketAndHostDontMount(t *testing.T) {
|
|||||||
// Arrange
|
// Arrange
|
||||||
CommonSocketLocations = originalCommonSocketLocations
|
CommonSocketLocations = originalCommonSocketLocations
|
||||||
dockerHost := "unix:///my/docker/host.sock"
|
dockerHost := "unix:///my/docker/host.sock"
|
||||||
os.Setenv("DOCKER_HOST", dockerHost)
|
t.Setenv("DOCKER_HOST", dockerHost)
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ret, err := GetSocketAndHost("-")
|
ret, err := GetSocketAndHost("-")
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, SocketAndHost{"-", dockerHost}, ret)
|
assert.Equal(t, SocketAndHost{"-", dockerHost}, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,8 +87,8 @@ func TestGetSocketAndHostNoHostNoSocket(t *testing.T) {
|
|||||||
ret, err := GetSocketAndHost("")
|
ret, err := GetSocketAndHost("")
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Equal(t, true, found, "Expected a default socket to be found")
|
assert.Equal(t, true, found, "Expected a default socket to be found") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Nil(t, err, "Expected no error from GetSocketAndHost")
|
assert.Nil(t, err, "Expected no error from GetSocketAndHost") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, SocketAndHost{defaultSocket, defaultSocket}, ret, "Expected to match default socket location")
|
assert.Equal(t, SocketAndHost{defaultSocket, defaultSocket}, ret, "Expected to match default socket location")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,11 +97,11 @@ func TestGetSocketAndHostNoHostNoSocket(t *testing.T) {
|
|||||||
// > This happens if neither DOCKER_HOST nor --container-daemon-socket has a value, but socketLocation() returns a URI
|
// > This happens if neither DOCKER_HOST nor --container-daemon-socket has a value, but socketLocation() returns a URI
|
||||||
func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
|
func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
mySocketFile, tmpErr := os.CreateTemp("", "act-*.sock")
|
mySocketFile, tmpErr := os.CreateTemp(t.TempDir(), "act-*.sock")
|
||||||
mySocket := mySocketFile.Name()
|
mySocket := mySocketFile.Name()
|
||||||
unixSocket := "unix://" + mySocket
|
unixSocket := "unix://" + mySocket
|
||||||
defer os.RemoveAll(mySocket)
|
defer os.RemoveAll(mySocket)
|
||||||
assert.NoError(t, tmpErr)
|
assert.NoError(t, tmpErr) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
os.Unsetenv("DOCKER_HOST")
|
os.Unsetenv("DOCKER_HOST")
|
||||||
|
|
||||||
CommonSocketLocations = []string{mySocket}
|
CommonSocketLocations = []string{mySocket}
|
||||||
@@ -108,8 +112,8 @@ func TestGetSocketAndHostNoHostNoSocketDefaultLocation(t *testing.T) {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Equal(t, unixSocket, defaultSocket, "Expected default socket to match common socket location")
|
assert.Equal(t, unixSocket, defaultSocket, "Expected default socket to match common socket location")
|
||||||
assert.Equal(t, true, found, "Expected default socket to be found")
|
assert.Equal(t, true, found, "Expected default socket to be found") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Nil(t, err, "Expected no error from GetSocketAndHost")
|
assert.Nil(t, err, "Expected no error from GetSocketAndHost") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, SocketAndHost{unixSocket, unixSocket}, ret, "Expected to match default socket location")
|
assert.Equal(t, SocketAndHost{unixSocket, unixSocket}, ret, "Expected to match default socket location")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +128,8 @@ func TestGetSocketAndHostNoHostInvalidSocket(t *testing.T) {
|
|||||||
ret, err := GetSocketAndHost(mySocket)
|
ret, err := GetSocketAndHost(mySocket)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Equal(t, false, found, "Expected no default socket to be found")
|
assert.Equal(t, false, found, "Expected no default socket to be found") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, "", defaultSocket, "Expected no default socket to be found")
|
assert.Equal(t, "", defaultSocket, "Expected no default socket to be found") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, SocketAndHost{}, ret, "Expected to match default socket location")
|
assert.Equal(t, SocketAndHost{}, ret, "Expected to match default socket location")
|
||||||
assert.Error(t, err, "Expected an error in invalid state")
|
assert.Error(t, err, "Expected an error in invalid state")
|
||||||
}
|
}
|
||||||
@@ -142,9 +146,9 @@ func TestGetSocketAndHostOnlySocketValidButUnusualLocation(t *testing.T) {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
// Default socket locations
|
// Default socket locations
|
||||||
assert.Equal(t, "", defaultSocket, "Expect default socket location to be empty")
|
assert.Equal(t, "", defaultSocket, "Expect default socket location to be empty") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, false, found, "Expected no default socket to be found")
|
assert.Equal(t, false, found, "Expected no default socket to be found") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
// Sane default
|
// Sane default
|
||||||
assert.Nil(t, err, "Expect no error from GetSocketAndHost")
|
assert.Nil(t, err, "Expect no error from GetSocketAndHost") //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, socketURI, ret.Host, "Expect host to default to unusual socket")
|
assert.Equal(t, socketURI, ret.Host, "Expect host to default to unusual socket")
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2023 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build WITHOUT_DOCKER || !(linux || darwin || windows || netbsd)
|
//go:build WITHOUT_DOCKER || !(linux || darwin || windows || netbsd)
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -6,20 +10,21 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImageExistsLocally returns a boolean indicating if an image with the
|
// ImageExistsLocally returns a boolean indicating if an image with the
|
||||||
// requested name, tag and architecture exists in the local docker image store
|
// requested name, tag and architecture exists in the local docker image store
|
||||||
func ImageExistsLocally(ctx context.Context, imageName string, platform string) (bool, error) {
|
func ImageExistsLocally(ctx context.Context, imageName, platform string) (bool, error) {
|
||||||
return false, errors.New("Unsupported Operation")
|
return false, errors.New("Unsupported Operation")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveImage removes image from local store, the function is used to run different
|
// RemoveImage removes image from local store, the function is used to run different
|
||||||
// container image architectures
|
// container image architectures
|
||||||
func RemoveImage(ctx context.Context, imageName string, force bool, pruneChildren bool) (bool, error) {
|
func RemoveImage(ctx context.Context, imageName string, force, pruneChildren bool) (bool, error) {
|
||||||
return false, errors.New("Unsupported Operation")
|
return false, errors.New("Unsupported Operation")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
||||||
|
|
||||||
package container
|
package container
|
||||||
@@ -5,9 +9,10 @@ package container
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/volume"
|
"github.com/docker/docker/api/types/volume"
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDockerVolumeRemoveExecutor(volumeName string, force bool) common.Executor {
|
func NewDockerVolumeRemoveExecutor(volumeName string, force bool) common.Executor {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import "context"
|
import "context"
|
||||||
@@ -9,7 +13,7 @@ type ExecutionsEnvironment interface {
|
|||||||
GetPathVariableName() string
|
GetPathVariableName() string
|
||||||
DefaultPathVariable() string
|
DefaultPathVariable() string
|
||||||
JoinPathVariable(...string) string
|
JoinPathVariable(...string) string
|
||||||
GetRunnerContext(ctx context.Context) map[string]interface{}
|
GetRunnerContext(ctx context.Context) map[string]any
|
||||||
// On windows PATH and Path are the same key
|
// On windows PATH and Path are the same key
|
||||||
IsEnvironmentCaseInsensitive() bool
|
IsEnvironmentCaseInsensitive() bool
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -15,14 +19,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
|
"gitea.com/gitea/act_runner/act/filecollector"
|
||||||
|
"gitea.com/gitea/act_runner/act/lookpath"
|
||||||
|
|
||||||
"github.com/go-git/go-billy/v5/helper/polyfill"
|
"github.com/go-git/go-billy/v5/helper/polyfill"
|
||||||
"github.com/go-git/go-billy/v5/osfs"
|
"github.com/go-git/go-billy/v5/osfs"
|
||||||
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
|
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
"github.com/nektos/act/pkg/filecollector"
|
|
||||||
"github.com/nektos/act/pkg/lookpath"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type HostEnvironment struct {
|
type HostEnvironment struct {
|
||||||
@@ -35,7 +39,7 @@ type HostEnvironment struct {
|
|||||||
StdOut io.Writer
|
StdOut io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HostEnvironment) Create(_ []string, _ []string) common.Executor {
|
func (e *HostEnvironment) Create(_, _ []string) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -86,7 +90,7 @@ func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, ta
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
return fmt.Errorf("CopyTarStream has been cancelled")
|
return errors.New("CopyTarStream has been cancelled")
|
||||||
}
|
}
|
||||||
if err := cp.WriteFile(ti.Name, ti.FileInfo(), ti.Linkname, tr); err != nil {
|
if err := cp.WriteFile(ti.Name, ti.FileInfo(), ti.Linkname, tr); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -94,7 +98,7 @@ func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, ta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HostEnvironment) CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor {
|
func (e *HostEnvironment) CopyDir(destPath, srcPath string, useGitIgnore bool) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
srcPrefix := filepath.Dir(srcPath)
|
srcPrefix := filepath.Dir(srcPath)
|
||||||
@@ -227,7 +231,7 @@ func (l *localEnv) Getenv(name string) string {
|
|||||||
func lookupPathHost(cmd string, env map[string]string, writer io.Writer) (string, error) {
|
func lookupPathHost(cmd string, env map[string]string, writer io.Writer) (string, error) {
|
||||||
f, err := lookpath.LookPath2(cmd, &localEnv{env: env})
|
f, err := lookpath.LookPath2(cmd, &localEnv{env: env})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := "Cannot find: " + fmt.Sprint(cmd) + " in PATH"
|
err := "Cannot find: " + cmd + " in PATH"
|
||||||
if _, _err := writer.Write([]byte(err + "\n")); _err != nil {
|
if _, _err := writer.Write([]byte(err + "\n")); _err != nil {
|
||||||
return "", fmt.Errorf("%v: %w", err, _err)
|
return "", fmt.Errorf("%v: %w", err, _err)
|
||||||
}
|
}
|
||||||
@@ -346,7 +350,7 @@ func (e *HostEnvironment) exec(ctx context.Context, command []string, cmdline st
|
|||||||
}
|
}
|
||||||
if tty != nil {
|
if tty != nil {
|
||||||
writer.AutoStop = true
|
writer.AutoStop = true
|
||||||
if _, err := tty.Write([]byte("\x04")); err != nil {
|
if _, err := tty.WriteString("\x04"); err != nil {
|
||||||
common.Logger(ctx).Debug("Failed to write EOT")
|
common.Logger(ctx).Debug("Failed to write EOT")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -408,9 +412,10 @@ func (e *HostEnvironment) GetActPath() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (*HostEnvironment) GetPathVariableName() string {
|
func (*HostEnvironment) GetPathVariableName() string {
|
||||||
if runtime.GOOS == "plan9" {
|
switch runtime.GOOS {
|
||||||
|
case "plan9":
|
||||||
return "path"
|
return "path"
|
||||||
} else if runtime.GOOS == "windows" {
|
case "windows":
|
||||||
return "Path" // Actually we need a case insensitive map
|
return "Path" // Actually we need a case insensitive map
|
||||||
}
|
}
|
||||||
return "PATH"
|
return "PATH"
|
||||||
@@ -449,8 +454,8 @@ func goOsToActionOs(os string) string {
|
|||||||
return os
|
return os
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]interface{} {
|
func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]any {
|
||||||
return map[string]interface{}{
|
return map[string]any{
|
||||||
"os": goOsToActionOs(runtime.GOOS),
|
"os": goOsToActionOs(runtime.GOOS),
|
||||||
"arch": goArchToActionArch(runtime.GOARCH),
|
"arch": goArchToActionArch(runtime.GOARCH),
|
||||||
"temp": e.TmpDir,
|
"temp": e.TmpDir,
|
||||||
@@ -458,7 +463,7 @@ func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]interfa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HostEnvironment) ReplaceLogWriter(stdout io.Writer, _ io.Writer) (io.Writer, io.Writer) {
|
func (e *HostEnvironment) ReplaceLogWriter(stdout, _ io.Writer) (io.Writer, io.Writer) {
|
||||||
org := e.StdOut
|
org := e.StdOut
|
||||||
e.StdOut = stdout
|
e.StdOut = stdout
|
||||||
return org, org
|
return org, org
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -16,9 +20,7 @@ import (
|
|||||||
var _ ExecutionsEnvironment = &HostEnvironment{}
|
var _ ExecutionsEnvironment = &HostEnvironment{}
|
||||||
|
|
||||||
func TestCopyDir(t *testing.T) {
|
func TestCopyDir(t *testing.T) {
|
||||||
dir, err := os.MkdirTemp("", "test-host-env-*")
|
dir := t.TempDir()
|
||||||
assert.NoError(t, err)
|
|
||||||
defer os.RemoveAll(dir)
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
e := &HostEnvironment{
|
e := &HostEnvironment{
|
||||||
Path: filepath.Join(dir, "path"),
|
Path: filepath.Join(dir, "path"),
|
||||||
@@ -28,18 +30,16 @@ func TestCopyDir(t *testing.T) {
|
|||||||
StdOut: os.Stdout,
|
StdOut: os.Stdout,
|
||||||
Workdir: path.Join("testdata", "scratch"),
|
Workdir: path.Join("testdata", "scratch"),
|
||||||
}
|
}
|
||||||
_ = os.MkdirAll(e.Path, 0700)
|
_ = os.MkdirAll(e.Path, 0o700)
|
||||||
_ = os.MkdirAll(e.TmpDir, 0700)
|
_ = os.MkdirAll(e.TmpDir, 0o700)
|
||||||
_ = os.MkdirAll(e.ToolCache, 0700)
|
_ = os.MkdirAll(e.ToolCache, 0o700)
|
||||||
_ = os.MkdirAll(e.ActPath, 0700)
|
_ = os.MkdirAll(e.ActPath, 0o700)
|
||||||
err = e.CopyDir(e.Workdir, e.Path, true)(ctx)
|
err := e.CopyDir(e.Workdir, e.Path, true)(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetContainerArchive(t *testing.T) {
|
func TestGetContainerArchive(t *testing.T) {
|
||||||
dir, err := os.MkdirTemp("", "test-host-env-*")
|
dir := t.TempDir()
|
||||||
assert.NoError(t, err)
|
|
||||||
defer os.RemoveAll(dir)
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
e := &HostEnvironment{
|
e := &HostEnvironment{
|
||||||
Path: filepath.Join(dir, "path"),
|
Path: filepath.Join(dir, "path"),
|
||||||
@@ -49,22 +49,22 @@ func TestGetContainerArchive(t *testing.T) {
|
|||||||
StdOut: os.Stdout,
|
StdOut: os.Stdout,
|
||||||
Workdir: path.Join("testdata", "scratch"),
|
Workdir: path.Join("testdata", "scratch"),
|
||||||
}
|
}
|
||||||
_ = os.MkdirAll(e.Path, 0700)
|
_ = os.MkdirAll(e.Path, 0o700)
|
||||||
_ = os.MkdirAll(e.TmpDir, 0700)
|
_ = os.MkdirAll(e.TmpDir, 0o700)
|
||||||
_ = os.MkdirAll(e.ToolCache, 0700)
|
_ = os.MkdirAll(e.ToolCache, 0o700)
|
||||||
_ = os.MkdirAll(e.ActPath, 0700)
|
_ = os.MkdirAll(e.ActPath, 0o700)
|
||||||
expectedContent := []byte("sdde/7sh")
|
expectedContent := []byte("sdde/7sh")
|
||||||
err = os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0600)
|
err := os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0o600)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
archive, err := e.GetContainerArchive(ctx, e.Path)
|
archive, err := e.GetContainerArchive(ctx, e.Path)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
defer archive.Close()
|
defer archive.Close()
|
||||||
reader := tar.NewReader(archive)
|
reader := tar.NewReader(archive)
|
||||||
h, err := reader.Next()
|
h, err := reader.Next()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, "action.yml", h.Name)
|
assert.Equal(t, "action.yml", h.Name)
|
||||||
content, err := io.ReadAll(reader)
|
content, err := io.ReadAll(reader)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err) //nolint:testifylint // pre-existing issue from nektos/act
|
||||||
assert.Equal(t, expectedContent, content)
|
assert.Equal(t, expectedContent, content)
|
||||||
_, err = reader.Next()
|
_, err = reader.Next()
|
||||||
assert.ErrorIs(t, err, io.EOF)
|
assert.ErrorIs(t, err, io.EOF)
|
||||||
+7
-4
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -10,8 +14,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LinuxContainerEnvironmentExtensions struct {
|
type LinuxContainerEnvironmentExtensions struct{}
|
||||||
}
|
|
||||||
|
|
||||||
// Resolves the equivalent host path inside the container
|
// 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
|
// This is required for windows and WSL 2 to translate things like C:\Users\Myproject to /mnt/users/Myproject
|
||||||
@@ -63,8 +66,8 @@ func (*LinuxContainerEnvironmentExtensions) JoinPathVariable(paths ...string) st
|
|||||||
return strings.Join(paths, ":")
|
return strings.Join(paths, ":")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]interface{} {
|
func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]any {
|
||||||
return map[string]interface{}{
|
return map[string]any{
|
||||||
"os": "Linux",
|
"os": "Linux",
|
||||||
"arch": RunnerArch(ctx),
|
"arch": RunnerArch(ctx),
|
||||||
"temp": "/tmp",
|
"temp": "/tmp",
|
||||||
+8
-9
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -31,22 +35,17 @@ func TestContainerPath(t *testing.T) {
|
|||||||
for _, v := range []containerPathJob{
|
for _, v := range []containerPathJob{
|
||||||
{"/mnt/c/Users/act/go/src/github.com/nektos/act", "C:\\Users\\act\\go\\src\\github.com\\nektos\\act\\", ""},
|
{"/mnt/c/Users/act/go/src/github.com/nektos/act", "C:\\Users\\act\\go\\src\\github.com\\nektos\\act\\", ""},
|
||||||
{"/mnt/f/work/dir", `F:\work\dir`, ""},
|
{"/mnt/f/work/dir", `F:\work\dir`, ""},
|
||||||
{"/mnt/c/windows/to/unix", "windows\\to\\unix", fmt.Sprintf("%s\\", rootDrive)},
|
{"/mnt/c/windows/to/unix", "windows\\to\\unix", rootDrive + "\\"},
|
||||||
{fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", fmt.Sprintf("%s\\", rootDrive)},
|
{fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", rootDrive + "\\"},
|
||||||
} {
|
} {
|
||||||
if v.workDir != "" {
|
if v.workDir != "" {
|
||||||
if err := os.Chdir(v.workDir); err != nil {
|
t.Chdir(v.workDir)
|
||||||
log.Error(err)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, v.destinationPath, linuxcontainerext.ToContainerPath(v.sourcePath))
|
assert.Equal(t, v.destinationPath, linuxcontainerext.ToContainerPath(v.sourcePath))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Chdir(cwd); err != nil {
|
t.Chdir(cwd)
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2022 The nektos/act Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -8,7 +12,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"gitea.com/gitea/act_runner/act/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseEnvFile(e Container, srcPath string, env *map[string]string) common.Executor {
|
func parseEnvFile(e Container, srcPath string, env *map[string]string) common.Executor {
|
||||||
File renamed without changes.
File renamed without changes.
Loaded 100 of 1936 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user