Compare commits
235 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1c87699e98 | ||
![]() |
6d10f57eaa | ||
![]() |
64df715d73 | ||
![]() |
b5ce1ccb8a | ||
![]() |
45f9c1f948 | ||
![]() |
6901b83a9d | ||
![]() |
3ee89c08b5 | ||
![]() |
44227666ba | ||
![]() |
521e3f1188 | ||
![]() |
227c2b2dc1 | ||
![]() |
bfc83035a6 | ||
![]() |
95a8d9530e | ||
![]() |
24210fe55d | ||
![]() |
c9265044b5 | ||
![]() |
f1b80e2e99 | ||
![]() |
477e949997 | ||
![]() |
5a14247c19 | ||
![]() |
3068bebfcb | ||
![]() |
a2ce5d9f8b | ||
![]() |
e238532feb | ||
![]() |
f351e7a7b1 | ||
![]() |
f5087573da | ||
![]() |
81422b4515 | ||
![]() |
3f8cadc0fe | ||
![]() |
191259d7c3 | ||
![]() |
de2e4c21aa | ||
![]() |
79f6adc4d2 | ||
![]() |
f3bcb0e57a | ||
![]() |
b34efbce8b | ||
![]() |
6c0527e8f7 | ||
![]() |
7f22a720ad | ||
![]() |
b8ccb30612 | ||
![]() |
055854d1d7 | ||
![]() |
f8b0ccf1a3 | ||
![]() |
279faefa08 | ||
![]() |
eee0b082fb | ||
![]() |
90ff9370c4 | ||
![]() |
811c07711f | ||
![]() |
2d77bc141b | ||
![]() |
35d655c27e | ||
![]() |
aca528a7f7 | ||
![]() |
aaac4fc798 | ||
![]() |
9d10ba9851 | ||
![]() |
5889426664 | ||
![]() |
96c59a3cd1 | ||
![]() |
704c88df32 | ||
![]() |
edd867dc16 | ||
![]() |
44b3b04d2d | ||
![]() |
eb34374d42 | ||
![]() |
68b0850d27 | ||
![]() |
4937ba2f3b | ||
![]() |
f1a9f798e5 | ||
![]() |
5d01a328cb | ||
![]() |
0876532ebe | ||
![]() |
8ccf20cf8a | ||
![]() |
b33e155709 | ||
![]() |
2bcc6d9b8f | ||
![]() |
a3e575f61b | ||
![]() |
6763b761e4 | ||
![]() |
355ec95532 | ||
![]() |
a0df63fe70 | ||
![]() |
54cfdd7065 | ||
![]() |
9aa014ef6f | ||
![]() |
830df0d128 | ||
![]() |
b4aba5f688 | ||
![]() |
c9f8bb6887 | ||
![]() |
e8e288dd7a | ||
![]() |
c178d44f69 | ||
![]() |
342141df3a | ||
![]() |
f4fc4c0247 | ||
![]() |
0f9471302a | ||
![]() |
4ddd8a4ce8 | ||
![]() |
030b1279ad | ||
![]() |
0aed67ae69 | ||
![]() |
113493541c | ||
![]() |
a3b0a48d4f | ||
![]() |
65c9651b1b | ||
![]() |
7696c1b72a | ||
![]() |
ab8346ba3a | ||
![]() |
c97e4d1fe3 | ||
![]() |
1b688b7c5e | ||
![]() |
0fb825f8e7 | ||
![]() |
f6626f09d5 | ||
![]() |
94fcda8483 | ||
![]() |
f7567f3cd7 | ||
![]() |
4a57d4acf9 | ||
![]() |
24b72f5aee | ||
![]() |
9510276a99 | ||
![]() |
228e002565 | ||
![]() |
5ef5a916c7 | ||
![]() |
0658d72b3f | ||
![]() |
0ba115ba67 | ||
![]() |
6c9959d7a9 | ||
![]() |
b76cd576ef | ||
![]() |
8b2242d893 | ||
![]() |
846ff2a616 | ||
![]() |
71149e36fa | ||
![]() |
907588cef5 | ||
![]() |
3f3601e46b | ||
![]() |
67361d1c0e | ||
![]() |
45fe0a6c66 | ||
![]() |
61ebb3b338 | ||
![]() |
2b64f15543 | ||
![]() |
a424406b0f | ||
![]() |
5a4387dd00 | ||
![]() |
37f9f9e48f | ||
![]() |
20915dc1bf | ||
![]() |
eb309b28d2 | ||
![]() |
95ef0da021 | ||
![]() |
76a710058b | ||
![]() |
722c109681 | ||
![]() |
75a2981e5b | ||
![]() |
38e884d973 | ||
![]() |
11270595e9 | ||
![]() |
54b9c53136 | ||
![]() |
d3b8b3bb16 | ||
![]() |
a616fd2a37 | ||
![]() |
6c067bfd76 | ||
![]() |
89e4df134b | ||
![]() |
a05194faa1 | ||
![]() |
3b185b53cd | ||
![]() |
0b93541ffc | ||
![]() |
db9f23de54 | ||
![]() |
6d84004259 | ||
![]() |
b1d9d52b6f | ||
![]() |
4b7b5d564d | ||
![]() |
98b5a0cbe1 | ||
![]() |
db2c3b32d4 | ||
![]() |
5066986c6d | ||
![]() |
b6c15d4aea | ||
![]() |
0c8e1fca49 | ||
![]() |
91b76cb17b | ||
![]() |
82523d1d8e | ||
![]() |
a10469b382 | ||
![]() |
6f8022ab45 | ||
![]() |
3963dfc6f7 | ||
![]() |
bda54ca5fc | ||
![]() |
627ef246c6 | ||
![]() |
93a8d7deae | ||
![]() |
97407545f0 | ||
![]() |
af381c9e0e | ||
![]() |
6aa29e3d44 | ||
![]() |
74d47a30a7 | ||
![]() |
cf47f003fa | ||
![]() |
7d67347fe8 | ||
![]() |
c0fc09ced9 | ||
![]() |
dad7a7d066 | ||
![]() |
d03685a331 | ||
![]() |
66db3633e6 | ||
![]() |
3b716969b9 | ||
![]() |
b911dca56b | ||
![]() |
996982abd3 | ||
![]() |
1008f44ddb | ||
![]() |
8509c33a07 | ||
![]() |
556f0412f7 | ||
![]() |
74708d8c82 | ||
![]() |
3f645405d5 | ||
![]() |
0cb4c70d4f | ||
![]() |
f605161e3f | ||
![]() |
d148278969 | ||
![]() |
e829f9c71c | ||
![]() |
4ef4b2d5cc | ||
![]() |
4e6a202fe5 | ||
![]() |
fe9cc4290e | ||
![]() |
16f4bf7d32 | ||
![]() |
93bced9c7b | ||
![]() |
a90b14b0e4 | ||
![]() |
705f59f3e4 | ||
![]() |
7f5c34890e | ||
![]() |
7e1ddcb5cc | ||
![]() |
f00e9240cd | ||
![]() |
aa0f1facf4 | ||
![]() |
e02e0fc5f5 | ||
![]() |
a7ff3bb917 | ||
![]() |
9774b35d75 | ||
![]() |
1b95689795 | ||
![]() |
f3861e60fc | ||
![]() |
0bacffa87e | ||
![]() |
15e328a8a5 | ||
![]() |
c989385713 | ||
![]() |
80896601aa | ||
![]() |
3382f0b084 | ||
![]() |
9e521434a4 | ||
![]() |
0fae5906ef | ||
![]() |
164e1008e5 | ||
![]() |
feb1a282da | ||
![]() |
f45d0855ad | ||
![]() |
3b24b73988 | ||
![]() |
aa421fa279 | ||
![]() |
5e51d8ed42 | ||
![]() |
5539ef7275 | ||
![]() |
599c75c167 | ||
![]() |
5660e21fb8 | ||
![]() |
7abbd84a8a | ||
![]() |
f1181cc62a | ||
![]() |
a697b9c1ed | ||
![]() |
be2063abf5 | ||
![]() |
8a2d4cb7cb | ||
![]() |
0348074eee | ||
![]() |
4c05530aa3 | ||
![]() |
ed946d0f54 | ||
![]() |
82b6df801f | ||
![]() |
e385811e74 | ||
![]() |
e7076aefb8 | ||
![]() |
4ad4512814 | ||
![]() |
6980165781 | ||
![]() |
eb89a98c6a | ||
![]() |
4f4ec159f0 | ||
![]() |
781606388c | ||
![]() |
9b504f7b47 | ||
![]() |
5f7a7ee355 | ||
![]() |
4a9d9b9e64 | ||
![]() |
5e7b8c201a | ||
![]() |
b3fb495844 | ||
![]() |
3682c4ecb4 | ||
![]() |
9d58769708 | ||
![]() |
ddd2eb7be9 | ||
![]() |
74cb9034e3 | ||
![]() |
82c30f5cf7 | ||
![]() |
cd206e4660 | ||
![]() |
1c20916144 | ||
![]() |
0d5eb12574 | ||
![]() |
cabaab6237 | ||
![]() |
0d199592e8 | ||
![]() |
2359531a9e | ||
![]() |
fcdcf1eb58 | ||
![]() |
77879b09c5 | ||
![]() |
0e1240a92f | ||
![]() |
c4e8c08065 | ||
![]() |
db2213254d | ||
![]() |
fd0596cd15 | ||
![]() |
ba9db84d1a | ||
![]() |
5efba83794 | ||
![]() |
dc45f96f8e | ||
![]() |
0273d9dc2d |
45 changed files with 1341 additions and 330 deletions
84
.forgejo/issue_template/bug-report.yaml
Normal file
84
.forgejo/issue_template/bug-report.yaml
Normal file
|
@ -0,0 +1,84 @@
|
|||
name: 🐛 Bug Report
|
||||
description: Found something you weren't expecting? Report it here!
|
||||
title: "bug: "
|
||||
labels: ["Kind/Bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**NOTE: If your issue is a security concern, please email <security@forgejo.org> (GPG: `A4676E79`) instead of opening a public issue.**
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
- Please speak English, as this is the language all maintainers can speak and write.
|
||||
- Be as clear and concise as possible. A very verbose report is harder to interpret in a concrete way.
|
||||
- Be civil, and follow the [Forgejo Code of Conduct](https://codeberg.org/forgejo/code-of-conduct).
|
||||
- Take a moment to [check that your issue hasn't been reported before](https://code.forgejo.org/forgejo/runner/issues?q=&type=all&labels=19).
|
||||
- type: dropdown
|
||||
id: can-reproduce
|
||||
attributes:
|
||||
label: Can you reproduce the bug on the Forgejo test instance?
|
||||
description: |
|
||||
Please try reproducing your issue at https://dev.next.forgejo.org.
|
||||
It is running the latest development branch and will confirm the problem is not already fixed.
|
||||
If you can reproduce it, provide a URL in the description.
|
||||
options:
|
||||
- "Yes"
|
||||
- "No"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see above).
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: forgejo-ver
|
||||
attributes:
|
||||
label: Forgejo Version
|
||||
description: Forgejo version (or commit reference) of your instance
|
||||
- type: input
|
||||
id: runner-ver
|
||||
attributes:
|
||||
label: Runner Version
|
||||
description: Runner version (or commit reference) of the runner on your instance
|
||||
- type: textarea
|
||||
id: forgejo-run-info
|
||||
attributes:
|
||||
label: How are you running Forgejo?
|
||||
description: |
|
||||
Please include information on whether you built Forgejo yourself, used one of our downloads, or are using some other package.
|
||||
Please also tell us how you are running Forgejo, e.g. if it is being run from a container, a command-line, systemd etc.
|
||||
If you are using a package or systemd tell us what distribution you are using.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: runner-run-info
|
||||
attributes:
|
||||
label: How are you running the Runner?
|
||||
description: |
|
||||
Please include information on whether you built the Runner yourself, used one of our downloads, or are using some other package.
|
||||
Please also tell us how you are running it, e.g. if it is being run from a container, a command-line, systemd etc.
|
||||
If you are using a package or systemd tell us what distribution you are using.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs
|
||||
description: |
|
||||
It's really important to provide pertinent logs. You must give us `DEBUG` level logs.
|
||||
Please read https://forgejo.org/docs/latest/admin/logging-documentation/.
|
||||
|
||||
Please copy and paste your logs here, with any sensitive information (e.g. API keys) removed/hidden.
|
||||
You can wrap your logs in `<details>...</details>` tags so it doesn't take up too much space in the issue.
|
||||
- type: textarea
|
||||
id: workflow
|
||||
attributes:
|
||||
label: Workflow file
|
||||
description: |
|
||||
If the bug occurs in a specific workflow, please provide an example workflow file.
|
||||
If you have linked to a reproduction repository this won't be necessary.
|
26
.forgejo/issue_template/feature-request.yaml
Normal file
26
.forgejo/issue_template/feature-request.yaml
Normal file
|
@ -0,0 +1,26 @@
|
|||
name: 💡 Feature Request
|
||||
description: Got an idea for an improvement to the Forgejo Runner? Suggest it here!
|
||||
title: "feat: "
|
||||
labels: ["Kind/Enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
- Please speak English, as this is the language all maintainers can speak and write.
|
||||
- Be as clear and concise as possible. A very verbose request is harder to interpret in a concrete way.
|
||||
- Be civil, and follow the [Forgejo Code of Conduct](https://codeberg.org/forgejo/code-of-conduct).
|
||||
- Please make sure you are using the latest release of the runner and take a moment to [check that your feature hasn't already been suggested](https://code.forgejo.org/forgejo/runner/issues?q=&type=all).
|
||||
- type: textarea
|
||||
id: needs-benefits
|
||||
attributes:
|
||||
label: Needs and benefits
|
||||
description: As concisely as possible, describe the benefits your feature request will provide or the problems it will try to solve.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: As concisely as possible, describe the feature you would like to see added or the changes you would like to see made to Forgejo.
|
||||
validations:
|
||||
required: true
|
24
.forgejo/labelscompare.py
Normal file
24
.forgejo/labelscompare.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
import json
|
||||
|
||||
expectedLabels = {
|
||||
"maintainer": "contact@forgejo.org",
|
||||
"org.opencontainers.image.authors": "Forgejo",
|
||||
"org.opencontainers.image.url": "https://forgejo.org",
|
||||
"org.opencontainers.image.documentation": "https://forgejo.org/docs/latest/admin/actions/#forgejo-runner",
|
||||
"org.opencontainers.image.source": "https://code.forgejo.org/forgejo/runner",
|
||||
"org.opencontainers.image.version": "1.2.3",
|
||||
"org.opencontainers.image.vendor": "Forgejo",
|
||||
"org.opencontainers.image.licenses": "MIT",
|
||||
"org.opencontainers.image.title": "Forgejo Runner",
|
||||
"org.opencontainers.image.description": "A runner for Forgejo Actions.",
|
||||
}
|
||||
inspect = None
|
||||
with open("./labels.json", "r") as f:
|
||||
inspect = json.load(f)
|
||||
|
||||
assert inspect
|
||||
labels = inspect[0]["Config"]["Labels"]
|
||||
|
||||
for k, v in expectedLabels.items():
|
||||
assert k in labels, f"'{k}' is missing from labels"
|
||||
assert labels[k] == v, f"expected {v} in key {k}, found {labels[k]}"
|
2
.forgejo/testdata/ipv6.yml
vendored
2
.forgejo/testdata/ipv6.yml
vendored
|
@ -4,7 +4,7 @@ jobs:
|
|||
ipv6:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: debian:bookworm
|
||||
image: code.forgejo.org/oci/debian:bookworm
|
||||
steps:
|
||||
- run: |
|
||||
apt update -qq ; apt --quiet install -qq --yes iputils-ping
|
||||
|
|
|
@ -1,22 +1,30 @@
|
|||
name: Integration tests for the release process
|
||||
|
||||
on:
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- go.mod
|
||||
- Dockerfile
|
||||
- .forgejo/workflows/build-release.yml
|
||||
- .forgejo/workflows/build-release-integration.yml
|
||||
branches-ignore:
|
||||
- renovate/** # they are build via PR
|
||||
pull_request:
|
||||
paths:
|
||||
- go.mod
|
||||
- Dockerfile
|
||||
- .forgejo/workflows/build-release.yml
|
||||
- .forgejo/workflows/build-release-integration.yml
|
||||
|
||||
jobs:
|
||||
release-simulation:
|
||||
runs-on: self-hosted
|
||||
runs-on: lxc-bookworm
|
||||
if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-release'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- id: forgejo
|
||||
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
||||
uses: https://code.forgejo.org/actions/setup-forgejo@v2.0.4
|
||||
with:
|
||||
user: root
|
||||
password: admin1234
|
||||
|
@ -79,3 +87,6 @@ jobs:
|
|||
done
|
||||
|
||||
docker pull ${{ steps.forgejo.outputs.host-port }}/root/runner:$version
|
||||
|
||||
docker inspect ${{ steps.forgejo.outputs.host-port}}/root/runner:$version > labels.json
|
||||
python3 .forgejo/labelscompare.py
|
||||
|
|
|
@ -5,22 +5,23 @@
|
|||
# Build the runner binaries and OCI images
|
||||
#
|
||||
# ROLE: forgejo-integration
|
||||
# DOER: release-team
|
||||
# TOKEN: <generated from codeberg.org/release-team>
|
||||
# DOER: forgejo-ci
|
||||
# TOKEN: <generated from https://code.forgejo.org/forgejo-ci>
|
||||
#
|
||||
name: Build release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: 'v*'
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: self-hosted
|
||||
runs-on: lxc-bookworm
|
||||
# root is used for testing, allow it
|
||||
if: secrets.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Increase the verbosity when there are no secrets
|
||||
id: verbose
|
||||
|
@ -35,8 +36,7 @@ jobs:
|
|||
- name: Sanitize the name of the repository
|
||||
id: repository
|
||||
run: |
|
||||
repository="${{ github.repository }}"
|
||||
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
|
||||
echo "value=${GITHUB_REPOSITORY##*/}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: create test TOKEN
|
||||
id: token
|
||||
|
@ -55,8 +55,7 @@ jobs:
|
|||
- name: version from ref_name
|
||||
id: tag-version
|
||||
run: |
|
||||
version="${{ github.ref_name }}"
|
||||
version=${version##*v}
|
||||
version=${GITHUB_REF_NAME##*v}
|
||||
echo "value=$version" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: release notes
|
||||
|
@ -72,13 +71,14 @@ jobs:
|
|||
|
||||
- name: build without TOKEN
|
||||
if: ${{ secrets.TOKEN == '' }}
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v1
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v5
|
||||
with:
|
||||
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
||||
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||
repository: "${{ steps.repository.outputs.value }}"
|
||||
doer: root
|
||||
tag-version: "${{ steps.tag-version.outputs.value }}"
|
||||
sha: "${{ github.sha }}"
|
||||
release-version: "${{ steps.tag-version.outputs.value }}"
|
||||
token: ${{ steps.token.outputs.value }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
release-notes: "${{ steps.release-notes.outputs.value }}"
|
||||
|
@ -88,13 +88,14 @@ jobs:
|
|||
|
||||
- name: build with TOKEN
|
||||
if: ${{ secrets.TOKEN != '' }}
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v1
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v5
|
||||
with:
|
||||
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
||||
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||
repository: "${{ steps.repository.outputs.value }}"
|
||||
doer: "${{ secrets.DOER }}"
|
||||
tag-version: "${{ steps.tag-version.outputs.value }}"
|
||||
sha: "${{ github.sha }}"
|
||||
release-version: "${{ steps.tag-version.outputs.value }}"
|
||||
token: "${{ secrets.TOKEN }}"
|
||||
platforms: linux/amd64,linux/arm64
|
||||
release-notes: "${{ steps.release-notes.outputs.value }}"
|
||||
|
|
|
@ -8,9 +8,11 @@ on:
|
|||
jobs:
|
||||
cascade:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||
if: vars.CASCADE != 'no'
|
||||
steps:
|
||||
- uses: actions/cascading-pr@v1
|
||||
- uses: https://code.forgejo.org/actions/cascading-pr@v2.2.0
|
||||
with:
|
||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||
origin-repo: forgejo/runner
|
||||
|
|
|
@ -7,9 +7,10 @@ on:
|
|||
|
||||
jobs:
|
||||
example-docker-compose:
|
||||
runs-on: self-hosted
|
||||
if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-experimental' && github.repository_owner != 'forgejo-release'
|
||||
runs-on: lxc-bookworm
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install docker
|
||||
run: |
|
||||
|
@ -20,12 +21,8 @@ jobs:
|
|||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
apt-get update -qq
|
||||
apt-get install -qq -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin=2.20.2-1~debian.11~bullseye
|
||||
apt-get install -qq -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
docker version
|
||||
#
|
||||
# docker compose is prone to non backward compatible changes, pin it
|
||||
#
|
||||
apt-get install -qq -y docker-compose-plugin=2.20.2-1~debian.11~bullseye
|
||||
docker compose version
|
||||
|
||||
- name: run the example
|
||||
|
@ -34,11 +31,18 @@ jobs:
|
|||
cd examples/docker-compose
|
||||
secret=$(openssl rand -hex 20)
|
||||
sed -i -e "s/{SHARED_SECRET}/$secret/" compose-forgejo-and-runner.yml
|
||||
cli="docker compose --progress quiet -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml"
|
||||
cli="docker compose --progress quiet -f compose-forgejo-and-runner.yml"
|
||||
#
|
||||
# Launch
|
||||
# Launch Forgejo & the runner
|
||||
#
|
||||
$cli up -d
|
||||
for delay in $(seq 60) ; do test -f /srv/runner-data/.runner && break ; sleep 30 ; done
|
||||
test -f /srv/runner-data/.runner
|
||||
#
|
||||
# Run the demo workflow
|
||||
#
|
||||
cli="$cli -f compose-demo-workflow.yml"
|
||||
$cli up -d demo-workflow
|
||||
#
|
||||
# Wait for the demo workflow to complete
|
||||
#
|
||||
|
@ -49,13 +53,14 @@ jobs:
|
|||
grep --quiet "$success" /tmp/out && break
|
||||
grep --quiet "$failure" /tmp/out && break
|
||||
$cli ps --all
|
||||
tail /tmp/out
|
||||
sleep 10
|
||||
$cli logs --tail=20 runner-daemon demo-workflow
|
||||
sleep 30
|
||||
done
|
||||
tail /tmp/out
|
||||
grep --quiet "$success" /tmp/out
|
||||
$cli logs runner-daemon > /tmp/runner.log
|
||||
grep --quiet 'Start image=code.forgejo.org/oci/node:20-bookworm' /tmp/runner.log
|
||||
|
||||
- name: docker compose logs
|
||||
- name: full docker compose logs
|
||||
if: always()
|
||||
run: |
|
||||
cd examples/docker-compose
|
||||
|
|
|
@ -13,37 +13,35 @@
|
|||
# GPG_PRIVATE_KEY: <XYZ>
|
||||
# GPG_PASSPHRASE: <ABC>
|
||||
#
|
||||
name: pubish
|
||||
name: publish
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: 'v*'
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: self-hosted
|
||||
runs-on: lxc-bookworm
|
||||
if: secrets.DOER != '' && secrets.FORGEJO != '' && secrets.TO_OWNER != '' && secrets.FROM_OWNER != '' && secrets.TOKEN != ''
|
||||
steps:
|
||||
- name: install the certificate authority
|
||||
if: secrets.ROLE == 'forgejo-release'
|
||||
run: |
|
||||
apt-get install -qq -y wget
|
||||
wget --no-check-certificate -O /usr/local/share/ca-certificates/enough.crt https://forgejo.octopuce.forgejo.org/forgejo/enough/raw/branch/main/certs/2023-05-13/ca.crt
|
||||
update-ca-certificates --fresh
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: copy & sign
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v1
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v5.2.1
|
||||
with:
|
||||
forgejo: ${{ secrets.FORGEJO }}
|
||||
from-forgejo: ${{ secrets.FORGEJO }}
|
||||
to-forgejo: ${{ secrets.FORGEJO }}
|
||||
from-owner: ${{ secrets.FROM_OWNER }}
|
||||
to-owner: ${{ secrets.TO_OWNER }}
|
||||
repo: "runner"
|
||||
release-notes: "See https://code.forgejo.org/forgejo/runner/src/branch/main/RELEASE-NOTES.md#{ANCHOR}"
|
||||
ref-name: ${{ github.ref_name }}
|
||||
sha: ${{ github.sha }}
|
||||
container-suffixes: " "
|
||||
doer: ${{ secrets.DOER }}
|
||||
token: ${{ secrets.TOKEN }}
|
||||
from-token: ${{ secrets.TOKEN }}
|
||||
to-doer: ${{ secrets.DOER }}
|
||||
to-token: ${{ secrets.TOKEN }}
|
||||
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
||||
verbose: ${{ secrets.VERBOSE }}
|
||||
|
|
|
@ -11,7 +11,7 @@ env:
|
|||
FORGEJO_ADMIN_PASSWORD: 'admin1234'
|
||||
FORGEJO_RUNNER_SECRET: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
|
||||
FORGEJO_SCRIPT: |
|
||||
/bin/s6-svscan /etc/s6 & sleep 10 ; su -c "forgejo admin user create --admin --username $FORGEJO_ADMIN_USER --password $FORGEJO_ADMIN_PASSWORD --email root@example.com" git && su -c "forgejo forgejo-cli actions register --labels docker --name therunner --secret $FORGEJO_RUNNER_SECRET" git && sleep infinity
|
||||
/bin/s6-svscan /etc/s6 & sleep 10 ; su -c "forgejo admin user create --admin --username $FORGEJO_ADMIN_USER --password $FORGEJO_ADMIN_PASSWORD --email root@example.com" git && su -c "forgejo forgejo-cli actions register --labels docker --name therunner --secret $FORGEJO_RUNNER_SECRET" git && sleep infinity
|
||||
GOPROXY: https://goproxy.io,direct
|
||||
|
||||
jobs:
|
||||
|
@ -19,10 +19,12 @@ jobs:
|
|||
name: build and test
|
||||
if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-experimental' && github.repository_owner != 'forgejo-release'
|
||||
runs-on: docker
|
||||
container:
|
||||
image: 'code.forgejo.org/oci/ci:1'
|
||||
|
||||
services:
|
||||
forgejo:
|
||||
image: codeberg.org/forgejo/forgejo:1.21
|
||||
image: codeberg.org/forgejo/forgejo:9
|
||||
env:
|
||||
FORGEJO__security__INSTALL_LOCK: "true"
|
||||
FORGEJO__log__LEVEL: "debug"
|
||||
|
@ -36,12 +38,22 @@ jobs:
|
|||
- ${{ env.FORGEJO_SCRIPT }}
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.21'
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: validate go version
|
||||
run: |
|
||||
set -ex
|
||||
toolchain=$(grep -oP '(?<=toolchain ).+' go.mod)
|
||||
version=$(go version | cut -d' ' -f3)
|
||||
if [ "$toolchain" != "$version" ]; then
|
||||
echo "go version mismatch: $toolchain <> $version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- run: make vet
|
||||
|
||||
- run: make build
|
||||
|
@ -53,9 +65,9 @@ jobs:
|
|||
|
||||
- name: check the forgejo server is responding
|
||||
run: |
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq jq curl
|
||||
test $FORGEJO_ADMIN_USER = $(curl -sS http://$FORGEJO_ADMIN_USER:$FORGEJO_ADMIN_PASSWORD@$FORGEJO_HOST_PORT/api/v1/user | jq --raw-output .login)
|
||||
sleep 10 # matches the sleep 10 in the bootstrap of the Forgejo instance
|
||||
# in case of a slow machine, give it time to bootstrap
|
||||
retry --delay=10 --times=6 bash -c 'test $FORGEJO_ADMIN_USER = $(curl -sS http://$FORGEJO_ADMIN_USER:$FORGEJO_ADMIN_PASSWORD@$FORGEJO_HOST_PORT/api/v1/user | jq --raw-output .login)'
|
||||
|
||||
- run: make FORGEJO_URL=http://$FORGEJO_HOST_PORT test
|
||||
|
||||
|
@ -63,7 +75,7 @@ jobs:
|
|||
needs: [build-and-tests]
|
||||
name: runner exec tests
|
||||
if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-experimental' && github.repository_owner != 'forgejo-release'
|
||||
runs-on: self-hosted
|
||||
runs-on: lxc-bookworm
|
||||
|
||||
steps:
|
||||
|
||||
|
|
50
.github/workflows/build-release.yml
vendored
Normal file
50
.github/workflows/build-release.yml
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
# This workflow will build a Windows binary for each architecture and upload it as an artifact.
|
||||
# If the push is a tag, it will create a release with the binaries attached.
|
||||
# This build is currently supported on https://github.com/Crown0815/forgejo-runner-windows
|
||||
|
||||
name: Build release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: 'v*'
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{matrix.architecture}}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
architecture: ['386', amd64, arm, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build for ${{matrix.architecture}}
|
||||
run: |
|
||||
env GOOS=windows GOARCH=${{matrix.architecture}} \
|
||||
go build \
|
||||
-ldflags "-s -w -X gitea.com/gitea/act_runner/internal/pkg/ver.version=${{ github.ref_name }}" \
|
||||
-o forgejo-runner-windows-${{matrix.architecture}}.exe
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: forgejo-runner-windows-${{matrix.architecture}}
|
||||
path: forgejo-runner-windows-${{matrix.architecture}}.exe
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: github.event_name == 'push' && github.ref_type == 'tag'
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: .
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ github.ref_name }}
|
||||
files: forgejo-runner-windows-*/forgejo-runner-windows-*.exe
|
||||
draft: false
|
||||
prerelease: ${{ contains(github.ref, 'beta') || contains(github.ref, 'alpha') }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
fail_on_unmatched_files: true
|
||||
body: See [original release notes](https://code.forgejo.org/forgejo/runner/releases/tag/${{ github.ref_name }}).
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -12,3 +12,6 @@ coverage.txt
|
|||
__debug_bin
|
||||
# gorelease binary folder
|
||||
dist
|
||||
|
||||
# Jetbrains IDE
|
||||
.idea
|
||||
|
|
20
Dockerfile
20
Dockerfile
|
@ -1,6 +1,6 @@
|
|||
FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/tonistiigi/xx AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21-alpine3.18 as build-env
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 AS build-env
|
||||
|
||||
#
|
||||
# Transparently cross compile for the target platform
|
||||
|
@ -19,13 +19,23 @@ WORKDIR /srv
|
|||
|
||||
RUN make clean && make build
|
||||
|
||||
FROM docker.io/library/alpine:3.18
|
||||
LABEL maintainer="contact@forgejo.org"
|
||||
|
||||
FROM code.forgejo.org/oci/alpine:3.20
|
||||
ARG RELEASE_VERSION
|
||||
RUN apk add --no-cache git bash
|
||||
|
||||
COPY --from=build-env /srv/forgejo-runner /bin/forgejo-runner
|
||||
|
||||
LABEL maintainer="contact@forgejo.org" \
|
||||
org.opencontainers.image.authors="Forgejo" \
|
||||
org.opencontainers.image.url="https://forgejo.org" \
|
||||
org.opencontainers.image.documentation="https://forgejo.org/docs/latest/admin/actions/#forgejo-runner" \
|
||||
org.opencontainers.image.source="https://code.forgejo.org/forgejo/runner" \
|
||||
org.opencontainers.image.version="${RELEASE_VERSION}" \
|
||||
org.opencontainers.image.vendor="Forgejo" \
|
||||
org.opencontainers.image.licenses="MIT" \
|
||||
org.opencontainers.image.title="Forgejo Runner" \
|
||||
org.opencontainers.image.description="A runner for Forgejo Actions."
|
||||
|
||||
ENV HOME=/data
|
||||
|
||||
USER 1000:1000
|
||||
|
|
2
Makefile
2
Makefile
|
@ -7,7 +7,7 @@ GO ?= go
|
|||
SHASUM ?= shasum -a 256
|
||||
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||
XGO_VERSION := go-1.18.x
|
||||
XGO_VERSION := go-1.21.x
|
||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
|
||||
|
||||
LINUX_ARCHS ?= linux/amd64,linux/arm64
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
A daemon that connects to a Forgejo instance and runs jobs for continous integration. The [installation and usage instructions](https://forgejo.org/docs/next/admin/actions/) are part of the Forgejo documentation.
|
||||
|
||||
# Reporting bugs
|
||||
|
||||
When filing a bug in [the issue tracker](https://code.forgejo.org/forgejo/runner/issues), it is very helpful to propose a pull request [in the end-to-end tests](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions) repository that adds a reproducer. It will fail the CI and unambiguously demonstrate that the problem exists. In most cases it is enough to add a workflow ([see the echo example](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-echo)). For more complicated cases it is also possible to add a runner config file as well as shell scripts to setup and teardown the test case ([see the service example](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-service)).
|
||||
|
||||
# Hacking
|
||||
|
||||
The Forgejo runner depends on [a fork of ACT](https://code.forgejo.org/forgejo/act) and is a dependency of the [setup-forgejo action](https://code.forgejo.org/actions/setup-forgejo). See [the full dependency graph](https://code.forgejo.org/actions/cascading-pr/#forgejo-dependencies) for a global view.
|
||||
|
@ -51,7 +55,7 @@ A Forgejo instance is launched with:
|
|||
```shell
|
||||
cd setup-forgejo
|
||||
./forgejo.sh setup
|
||||
firefox http://$(cat forgejo-ip):3000
|
||||
firefox $(cat forgejo-url)
|
||||
```
|
||||
|
||||
The user is `root` with password `admin1234`. The runner is registered with:
|
||||
|
@ -59,7 +63,7 @@ The user is `root` with password `admin1234`. The runner is registered with:
|
|||
```
|
||||
cd setup-forgejo
|
||||
docker exec --user 1000 forgejo forgejo actions generate-runner-token > forgejo-runner-token
|
||||
../runner/forgejo-runner register --no-interactive --instance "http://$(cat forgejo-ip):3000/" --name runner --token $(cat forgejo-runner-token) --labels docker:docker://node:16-bullseye,self-hosted:host://-self-hosted,lxc:lxc://debian:bullseye
|
||||
../runner/forgejo-runner register --no-interactive --instance "$(cat forgejo-url)" --name runner --token $(cat forgejo-runner-token) --labels docker:docker://node:20-bullseye,self-hosted:host://-self-hosted,lxc:lxc://debian:bullseye
|
||||
```
|
||||
|
||||
And launched with:
|
||||
|
|
|
@ -1,5 +1,86 @@
|
|||
# Release Notes
|
||||
|
||||
## 6.0.0
|
||||
|
||||
* Security: the container options a job is allowed to specify are limited to a [predefined allow list](https://forgejo.org/docs/next/user/actions/#jobsjob_idcontaineroptions).
|
||||
|
||||
## 5.0.4
|
||||
|
||||
* Define FORGEJO_TOKEN as an alias to GITHUB_TOKEN
|
||||
|
||||
## 5.0.3
|
||||
|
||||
* [Fixes a regression](https://code.forgejo.org/forgejo/runner/pulls/354) that was introduced in version 5.0.0 by which it was no longer possible to mount the docker socket in each container by specifying `[container].docker_host = ""`. This is now implemented when `[container].docker_host = "automount"` is specified.
|
||||
|
||||
## 5.0.2
|
||||
|
||||
* Fixes a regression that was introduced in version 5.0.0 by which [skipped jobs were marked as failed instead](https://code.forgejo.org/forgejo/act/pulls/67). The workaround is to change the job log level to debug `[log].job_level: debug`.
|
||||
|
||||
## 5.0.1
|
||||
|
||||
* Security: the `/opt/hostedtoolcache` directory is now unique to each job instead of being shared to avoid a risk of corruption. It is still advertised in the `RUNNER_TOOL_CACHE` environment variable. Custom container images can be built to pre-populate this directory with frequently used tools and some actions (such as `setup-go`) will benefit from that.
|
||||
|
||||
## 5.0.0
|
||||
|
||||
* Breaking change: the default configuration for `docker_host` is changed to [not mounting the docker server socket](https://code.forgejo.org/forgejo/runner/pulls/305) even when no configuration file is provided.
|
||||
* [Add job_level logging option to config](https://code.forgejo.org/forgejo/runner/pulls/299) to make the logging level of jobs configurable. Change default from "trace" to "info".
|
||||
* [Don't log job output when debug logging is not enabled](https://code.forgejo.org/forgejo/runner/pulls/303). This reduces the default amount of log output of the runner.
|
||||
|
||||
## 4.0.1
|
||||
|
||||
* Do not panic when [the number of arguments of a function evaluated in an expression is incorect](https://code.forgejo.org/forgejo/act/pulls/59/files).
|
||||
|
||||
## 4.0.0
|
||||
|
||||
* Breaking change: fix the default configuration for `docker_host` is changed to [not mounting the docker server socket](https://code.forgejo.org/forgejo/runner/pulls/305).
|
||||
* [Remove debug information from the setup of a workflow](https://code.forgejo.org/forgejo/runner/pulls/297).
|
||||
* Fix [crash in some cases when the YAML structure is not as expected](https://code.forgejo.org/forgejo/runner/issues/267).
|
||||
|
||||
## 3.5.1
|
||||
|
||||
* Fix [CVE-2024-24557](https://nvd.nist.gov/vuln/detail/CVE-2024-24557)
|
||||
* [Add report_interval option to config](https://code.forgejo.org/forgejo/runner/pulls/220) to allow setting the interval of status and log reports
|
||||
|
||||
## 3.5.0
|
||||
|
||||
* [Allow graceful shutdowns](https://code.forgejo.org/forgejo/runner/pulls/202): when receiving a signal (INT or TERM) wait for running jobs to complete (up to shutdown_timeout).
|
||||
* [Fix label declaration](https://code.forgejo.org/forgejo/runner/pulls/176): Runner in daemon mode now takes labels found in config.yml into account when declaration was successful.
|
||||
* [Fix the docker compose example](https://code.forgejo.org/forgejo/runner/pulls/175) to workaround the race on labels.
|
||||
* [Fix the kubernetes dind example](https://code.forgejo.org/forgejo/runner/pulls/169).
|
||||
* [Rewrite ::group:: and ::endgroup:: commands like github](https://code.forgejo.org/forgejo/runner/pulls/183).
|
||||
* [Added opencontainers labels to the image](https://code.forgejo.org/forgejo/runner/pulls/195)
|
||||
* [Upgrade the default container to node:20](https://code.forgejo.org/forgejo/runner/pulls/203)
|
||||
|
||||
## 3.4.1
|
||||
|
||||
* Fixes a regression introduced in 3.4.0 by which a job with no image explicitly set would
|
||||
[be bound to the host](https://code.forgejo.org/forgejo/runner/issues/165)
|
||||
network instead of a custom network (empty string in the configuration file).
|
||||
|
||||
## 3.4.0
|
||||
|
||||
Although this version is able to run [actions/upload-artifact@v4](https://code.forgejo.org/actions/upload-artifact/src/tag/v4) and [actions/download-artifact@v4](https://code.forgejo.org/actions/download-artifact/src/tag/v4), these actions will fail because it does not run against GitHub.com. A fork of those two actions with this check disabled is made available at:
|
||||
|
||||
* https://code.forgejo.org/forgejo/upload-artifact/src/tag/v4
|
||||
* https://code.forgejo.org/forgejo/download-artifact/src/tag/v4
|
||||
|
||||
and they can be used as shown in [an example from the end-to-end test suite](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-artifacts-v4/.forgejo/workflows/test.yml).
|
||||
|
||||
* When running against codeberg.org, the default poll frequency is 30s instead of 2s.
|
||||
* Fix compatibility issue with actions/{upload,download}-artifact@v4.
|
||||
* Upgrade ACT v1.20.0 which brings:
|
||||
* `[container].options` from the config file is exposed in containers created by the workflows
|
||||
* the expressions in the value of `jobs.<job-id>.runs-on` are evaluated
|
||||
* fix a bug causing the evaluated expression of `jobs.<job-id>.runs-on` to fail if it was an array
|
||||
* mount `act-toolcache:/opt/hostedtoolcache` instead of `act-toolcache:/toolcache`
|
||||
* a few improvements to the readability of the error messages displayed in the logs
|
||||
* `amd64` can be used instead of `x86_64` and `arm64` intead of `aarch64` when specifying the architecture
|
||||
* fixed YAML parsing bugs preventing dispatch workflows to be parsed correctly
|
||||
* add support for `runs-on.labels` which is equivalent to `runs-on` followed by a list of labels
|
||||
* the expressions in the service `ports` and `volumes` values are evaluated
|
||||
* network aliases are only supported when the network is user specified, not when it is provided by the runner
|
||||
* If `[runner].insecure` is true in the configuration, insecure cloning actions is allowed
|
||||
|
||||
## 3.3.0
|
||||
|
||||
* Support IPv6 with addresses from a private range and NAT for
|
||||
|
|
18
contrib/forgejo-runner.service
Normal file
18
contrib/forgejo-runner.service
Normal file
|
@ -0,0 +1,18 @@
|
|||
[Unit]
|
||||
Description=Forgejo Runner
|
||||
Documentation=https://forgejo.org/docs/latest/admin/actions/
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
ExecStart=forgejo-runner daemon
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
|
||||
# This user and working directory must already exist
|
||||
User=runner
|
||||
WorkingDirectory=/home/runner
|
||||
Restart=on-failure
|
||||
TimeoutSec=0
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -13,10 +13,19 @@ rm -fr /srv/runner-data /srv/forgejo-data
|
|||
secret=$(openssl rand -hex 20)
|
||||
sed -i -e "s/{SHARED_SECRET}/$secret/" compose-forgejo-and-runner.yml
|
||||
docker compose -f compose-forgejo-and-runner.yml up -d
|
||||
docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml up demo-workflow
|
||||
firefox http://0.0.0.0:8080/root/test/actions/runs/1 # login root, password {ROOT_PASSWORD}
|
||||
```
|
||||
|
||||
Visit http://0.0.0.0:8080/admin/actions/runners with login `root` and password `{ROOT_PASSWORD}` and see the runner is registered with the label `docker`.
|
||||
|
||||
> NOTE: the `Your ROOT_URL in app.ini is "http://localhost:3000/", it's unlikely matching the site you are visiting.` message is a warning that can be ignored in the context of this example.
|
||||
|
||||
```sh
|
||||
docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml up demo-workflow
|
||||
```
|
||||
|
||||
Visit http://0.0.0.0:8080/root/test/actions/runs/1 and see that the job ran.
|
||||
|
||||
|
||||
### Running
|
||||
|
||||
Create a shared secret with:
|
||||
|
@ -34,12 +43,12 @@ Replace {ROOT_PASSWORD} with a secure password in
|
|||
[compose-forgejo-and-runner.yml](compose-forgejo-and-runner.yml).
|
||||
|
||||
```sh
|
||||
docker-compose -f compose-forgejo-and-runner.yml up
|
||||
docker compose -f compose-forgejo-and-runner.yml up
|
||||
Creating docker-compose_docker-in-docker_1 ... done
|
||||
Creating docker-compose_forgejo_1 ... done
|
||||
Creating docker-compose_runner-register_1 ... done
|
||||
...
|
||||
docker-in-docker_1 | time="2023-08-24T10:22:15.023338461Z" level=warning msg="WARNING: API is accessible on http://0.0.0.0:2375
|
||||
docker-in-docker_1 | time="2023-08-24T10:22:15.023338461Z" level=warning msg="WARNING: API is accessible on http://0.0.0.0:2376
|
||||
...
|
||||
forgejo_1 | 2023/08/24 10:22:14 ...s/graceful/server.go:75:func1() [D] Starting server on tcp:0.0.0.0:3000 (PID: 19)
|
||||
...
|
||||
|
@ -51,19 +60,21 @@ runner-daemon_1 | time="2023-08-24T10:22:16Z" level=info msg="Starting runne
|
|||
To login the Forgejo instance:
|
||||
|
||||
* URL: http://0.0.0.0:8080
|
||||
* user: root
|
||||
* password: {ROOT_PASSWORD}
|
||||
* user: `root`
|
||||
* password: `{ROOT_PASSWORD}`
|
||||
|
||||
`Forgejo Actions` is enabled by default when creating a repository.
|
||||
|
||||
## Tests workflow
|
||||
|
||||
The `compose-demo-workflow.yml` compose file runs a demo workflow to
|
||||
verify the `Forgejo runner` can pick up a task from the Forgejo instance
|
||||
The `compose-demo-workflow.yml` compose file runs two demo workflows:
|
||||
* one to verify the `Forgejo runner` can pick up a task from the Forgejo instance
|
||||
and run it to completion.
|
||||
* one to verify docker can be run inside the `Forgejo runner` container.
|
||||
|
||||
A new repository is created in root/test with the following workflow
|
||||
in `.forgejo/workflows/demo.yml`:
|
||||
A new repository is created in root/test with the following workflows:
|
||||
|
||||
#### `.forgejo/workflows/demo.yml`:
|
||||
|
||||
```yaml
|
||||
on: [push]
|
||||
|
@ -74,6 +85,17 @@ jobs:
|
|||
- run: echo All Good
|
||||
```
|
||||
|
||||
#### `.forgejo/workflows/demo_docker.yml`
|
||||
|
||||
```yaml
|
||||
on: [push]
|
||||
jobs:
|
||||
test_docker:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- run: docker info
|
||||
```
|
||||
|
||||
A wait loop expects the status of the check associated with the
|
||||
commit in Forgejo to show "success" to assert the workflow was run.
|
||||
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
# Copyright 2023 The Forgejo Authors.
|
||||
# Copyright 2024 The Forgejo Authors.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
demo-workflow:
|
||||
image: alpine:3.18
|
||||
image: code.forgejo.org/oci/alpine:3.19
|
||||
links:
|
||||
- forgejo
|
||||
depends_on:
|
||||
runner-register:
|
||||
condition: service_completed_successfully
|
||||
command: >-
|
||||
sh -ec '
|
||||
apk add --quiet git curl jq ;
|
||||
|
@ -20,6 +15,7 @@ services:
|
|||
git init --initial-branch=main ;
|
||||
mkdir -p .forgejo/workflows ;
|
||||
echo "{ on: [push], jobs: { test: { runs-on: docker, steps: [ {uses: actions/checkout@v4}, { run: echo All Good } ] } } }" > .forgejo/workflows/demo.yml ;
|
||||
echo "{ on: [push], jobs: { test_docker: { runs-on: ubuntu-22.04, steps: [ { run: docker info } ] } } }" > .forgejo/workflows/demo_docker.yml ;
|
||||
git add . ;
|
||||
git config user.email root@example.com ;
|
||||
git config user.name username ;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2023 The Forgejo Authors.
|
||||
# Copyright 2024 The Forgejo Authors.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
#
|
||||
|
@ -14,29 +14,34 @@
|
|||
# Replace {ROOT_PASSWORD} with a secure password
|
||||
#
|
||||
|
||||
version: "3"
|
||||
volumes:
|
||||
docker_certs:
|
||||
|
||||
services:
|
||||
|
||||
docker-in-docker:
|
||||
image: docker:dind
|
||||
image: code.forgejo.org/oci/docker:dind
|
||||
hostname: docker # Must set hostname as TLS certificates are only valid for docker or localhost
|
||||
privileged: true
|
||||
command: [ "dockerd", "-H", "tcp://0.0.0.0:2375", "--tls=false" ]
|
||||
environment:
|
||||
DOCKER_TLS_CERTDIR: /certs
|
||||
DOCKER_HOST: docker-in-docker
|
||||
volumes:
|
||||
- docker_certs:/certs
|
||||
|
||||
forgejo:
|
||||
image: codeberg.org/forgejo/forgejo:1.20.4-1
|
||||
image: codeberg.org/forgejo/forgejo:1.21
|
||||
command: >-
|
||||
bash -c '
|
||||
/bin/s6-svscan /etc/s6 &
|
||||
sleep 10 ;
|
||||
su -c "forgejo forgejo-cli actions register --secret {SHARED_SECRET} --labels docker --version 3.0.1" git ;
|
||||
su -c "forgejo forgejo-cli actions register --secret {SHARED_SECRET}" git ;
|
||||
su -c "forgejo admin user create --admin --username root --password {ROOT_PASSWORD} --email root@example.com" git ;
|
||||
sleep infinity
|
||||
'
|
||||
environment:
|
||||
FORGEJO__security__INSTALL_LOCK: "true"
|
||||
FORGEJO__log__LEVEL: "debug"
|
||||
FORGEJO__actions__ENABLED: "true"
|
||||
FORGEJO__repository__ENABLE_PUSH_CREATE_USER: "true"
|
||||
FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE: "false"
|
||||
FORGEJO__repository__DEFAULT_REPO_UNITS: "repo.code,repo.actions"
|
||||
|
@ -46,37 +51,43 @@ services:
|
|||
- 8080:3000
|
||||
|
||||
runner-register:
|
||||
image: code.forgejo.org/forgejo/runner:3.0.1
|
||||
image: code.forgejo.org/forgejo/runner:3.4.1
|
||||
links:
|
||||
- docker-in-docker
|
||||
- forgejo
|
||||
environment:
|
||||
DOCKER_HOST: tcp://docker-in-docker:2375
|
||||
DOCKER_HOST: tcp://docker-in-docker:2376
|
||||
volumes:
|
||||
- /srv/runner-data:/data
|
||||
user: 0:0
|
||||
command: >-
|
||||
bash -ec '
|
||||
while : ; do
|
||||
forgejo-runner create-runner-file --instance http://forgejo:3000 --name runner --secret {SHARED_SECRET} && break ;
|
||||
forgejo-runner create-runner-file --connect --instance http://forgejo:3000 --name runner --secret {SHARED_SECRET} && break ;
|
||||
sleep 1 ;
|
||||
done ;
|
||||
sed -i -e "s|\"labels\": null|\"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]|" .runner ;
|
||||
forgejo-runner generate-config > config.yml ;
|
||||
sed -i -e "s|network: .*|network: host|" config.yml ;
|
||||
sed -i -e "s|labels: \[\]|labels: \[\"docker:docker://alpine:3.18\"\]|" config.yml ;
|
||||
sed -i -e "s|^ envs:$$| envs:\n DOCKER_HOST: tcp://docker:2376\n DOCKER_TLS_VERIFY: 1\n DOCKER_CERT_PATH: /certs/client|" config.yml ;
|
||||
sed -i -e "s|^ options:| options: -v /certs/client:/certs/client|" config.yml ;
|
||||
sed -i -e "s| valid_volumes: \[\]$$| valid_volumes:\n - /certs/client|" config.yml ;
|
||||
chown -R 1000:1000 /data
|
||||
'
|
||||
|
||||
runner-daemon:
|
||||
image: code.forgejo.org/forgejo/runner:3.0.1
|
||||
image: code.forgejo.org/forgejo/runner:3.4.1
|
||||
links:
|
||||
- docker-in-docker
|
||||
- forgejo
|
||||
environment:
|
||||
DOCKER_HOST: tcp://docker-in-docker:2375
|
||||
depends_on:
|
||||
runner-register:
|
||||
condition: service_completed_successfully
|
||||
DOCKER_HOST: tcp://docker:2376
|
||||
DOCKER_CERT_PATH: /certs/client
|
||||
DOCKER_TLS_VERIFY: "1"
|
||||
volumes:
|
||||
- /srv/runner-data:/data
|
||||
command: "forgejo-runner --config config.yml daemon"
|
||||
- docker_certs:/certs
|
||||
command: >-
|
||||
bash -c '
|
||||
while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done
|
||||
'
|
||||
|
|
|
@ -48,7 +48,7 @@ spec:
|
|||
- name: RUNNER_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: forgejo-runner-secret
|
||||
name: runner-secret
|
||||
key: token
|
||||
- name: FORGEJO_INSTANCE_URL
|
||||
value: http://forgejo-http.forgejo.svc.cluster.local:3000
|
||||
|
|
83
go.mod
83
go.mod
|
@ -1,23 +1,25 @@
|
|||
module gitea.com/gitea/act_runner
|
||||
|
||||
go 1.21
|
||||
go 1.23
|
||||
|
||||
toolchain go1.23.4
|
||||
|
||||
require (
|
||||
code.gitea.io/actions-proto-go v0.3.1
|
||||
code.gitea.io/gitea-vet v0.2.3-0.20230113022436-2b1561217fa5
|
||||
github.com/avast/retry-go/v4 v4.5.0
|
||||
github.com/bufbuild/connect-go v1.10.0
|
||||
github.com/docker/docker v24.0.6+incompatible
|
||||
github.com/google/uuid v1.3.0
|
||||
code.gitea.io/actions-proto-go v0.4.0
|
||||
code.gitea.io/gitea-vet v0.2.3
|
||||
connectrpc.com/connect v1.17.0
|
||||
github.com/avast/retry-go/v4 v4.6.0
|
||||
github.com/docker/docker v25.0.7+incompatible
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/mattn/go-isatty v0.0.19
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/nektos/act v0.2.49
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/term v0.13.0
|
||||
golang.org/x/time v0.3.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
golang.org/x/term v0.26.0
|
||||
golang.org/x/time v0.8.0
|
||||
google.golang.org/protobuf v1.36.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gotest.tools/v3 v3.5.1
|
||||
)
|
||||
|
@ -28,27 +30,30 @@ require (
|
|||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/containerd/containerd v1.7.3 // indirect
|
||||
github.com/creack/pty v1.1.18 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/containerd/containerd v1.7.13 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/creack/pty v1.1.21 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/distribution/reference v0.5.0 // indirect
|
||||
github.com/docker/cli v24.0.6+incompatible // indirect
|
||||
github.com/docker/cli v25.0.3+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.9.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.11.0 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
|
@ -56,41 +61,45 @@ require (
|
|||
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.16.7 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/buildkit v0.12.2 // indirect
|
||||
github.com/moby/buildkit v0.13.2 // indirect
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/user v0.1.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/opencontainers/runc v1.1.8 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rhysd/actionlint v1.6.26 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/rhysd/actionlint v1.6.27 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/skeema/knownhosts v1.2.0 // indirect
|
||||
github.com/skeema/knownhosts v1.2.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.5.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
go.etcd.io/bbolt v1.3.7 // indirect
|
||||
golang.org/x/crypto v0.13.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.15.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
go.etcd.io/bbolt v1.3.9 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/mod v0.13.0 // indirect
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/tools v0.14.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.19.0
|
||||
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.22.2
|
||||
|
|
211
go.sum
211
go.sum
|
@ -1,13 +1,15 @@
|
|||
code.forgejo.org/forgejo/act v1.19.0 h1:XAKJ9Z5zRlmb6rF11oa/VesoKmOSaW3sTykfWrgtmK4=
|
||||
code.forgejo.org/forgejo/act v1.19.0/go.mod h1:YthlRq0FUQIzgfJ3ZWvCvVq3I3VsC9s2NYQ9b2Uxccs=
|
||||
code.gitea.io/actions-proto-go v0.3.1 h1:PMyiQtBKb8dNnpEO2R5rcZdXSis+UQZVo/SciMtR1aU=
|
||||
code.gitea.io/actions-proto-go v0.3.1/go.mod h1:00ys5QDo1iHN1tHNvvddAcy2W/g+425hQya1cCSvq9A=
|
||||
code.gitea.io/gitea-vet v0.2.3-0.20230113022436-2b1561217fa5 h1:daBEK2GQeqGikJESctP5Cu1i33z5ztAD4kyQWiw185M=
|
||||
code.gitea.io/gitea-vet v0.2.3-0.20230113022436-2b1561217fa5/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
||||
code.forgejo.org/forgejo/act v1.22.2 h1:gcHugOaLCtZvLnw070MiCjwVLKoSTVomd8waGsYQHKg=
|
||||
code.forgejo.org/forgejo/act v1.22.2/go.mod h1:+PcvJ9iv+NTFeJSh79ra9Jbk9l0vvyA9D9me5/dbxYM=
|
||||
code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
|
||||
code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
||||
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
|
||||
code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
||||
connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk=
|
||||
connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
|
@ -15,28 +17,29 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0
|
|||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek=
|
||||
github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM=
|
||||
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
|
||||
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
|
||||
github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg=
|
||||
github.com/avast/retry-go/v4 v4.5.0/go.mod h1:7hLEXp0oku2Nir2xBAsg0PTphp9z71bN5Aq1fboC3+I=
|
||||
github.com/bufbuild/connect-go v1.10.0 h1:QAJ3G9A1OYQW2Jbk3DeoJbkCxuKArrvZgDt47mjdTbg=
|
||||
github.com/bufbuild/connect-go v1.10.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8=
|
||||
github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA=
|
||||
github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o=
|
||||
github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/containerd/containerd v1.7.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is=
|
||||
github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
|
||||
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -44,48 +47,57 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY=
|
||||
github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6/EsX/6284=
|
||||
github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
|
||||
github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v25.0.7+incompatible h1:PQhcun5/OF7p0mZlDu3ud9APyyJi01R6/7hrBymWhhQ=
|
||||
github.com/docker/docker v25.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
|
||||
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
||||
github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY=
|
||||
github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
|
||||
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
|
@ -102,8 +114,8 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4
|
|||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
|
@ -111,25 +123,25 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/buildkit v0.12.2 h1:B7guBgY6sfk4dBlv/ORUxyYlp0UojYaYyATgtNwSCXc=
|
||||
github.com/moby/buildkit v0.12.2/go.mod h1:adB4y0SxxX8trnrY+oEulb48ODLqPO6pKMF0ppGcCoI=
|
||||
github.com/moby/buildkit v0.13.2 h1:nXNszM4qD9E7QtG7bFWPnDI1teUQFQglBzon/IU3SzI=
|
||||
github.com/moby/buildkit v0.13.2/go.mod h1:2cyVOv9NoHM7arphK9ZfHIWKn9YVZRFd1wXB8kKmEzY=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI=
|
||||
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
|
||||
github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
|
||||
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
|
@ -138,8 +150,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
|||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
|
||||
github.com/opencontainers/runc v1.1.8 h1:zICRlc+C1XzivLc3nzE+cbJV4LIi8tib6YG0MqC6OqA=
|
||||
github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
|
@ -148,11 +158,11 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rhysd/actionlint v1.6.26 h1:zi7jPZf3Ks14gCXYAAL47uBziyFlX7+Xwilqhexct9g=
|
||||
github.com/rhysd/actionlint v1.6.26/go.mod h1:TIj1DlCgtYLOv5CH9wCK+WJTOr1qAdnFzkGi0IgSCO4=
|
||||
github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw=
|
||||
github.com/rhysd/actionlint v1.6.27/go.mod h1:m2nFUjAnOrxCMXuOMz9evYBRCLUsMnKY2IJl/N5umbk=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
|
@ -163,26 +173,21 @@ github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NF
|
|||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM=
|
||||
github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
|
||||
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0=
|
||||
github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a h1:oIi7H/bwFUYKYhzKbHc+3MvHRWqhQwXVB4LweLMiVy0=
|
||||
github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a/go.mod h1:iSvujNDmpZ6eQX+bg/0X3lF7LEmZ8N77g2a/J/+Zt2U=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
|
@ -199,8 +204,24 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
|
||||
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I=
|
||||
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
@ -208,14 +229,14 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
@ -226,15 +247,15 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -253,15 +274,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -269,10 +290,10 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
|
@ -280,15 +301,21 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"os"
|
||||
|
||||
pingv1 "code.gitea.io/actions-proto-go/ping/v1"
|
||||
"github.com/bufbuild/connect-go"
|
||||
"connectrpc.com/connect"
|
||||
gouuid "github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -38,7 +38,7 @@ func createRunnerFileCmd(ctx context.Context, configFile *string) *cobra.Command
|
|||
cmd.Flags().BoolVar(&argsVar.Connect, "connect", false, "tries to connect to the instance using the secret (Forgejo v1.21 instance or greater)")
|
||||
cmd.Flags().StringVar(&argsVar.InstanceAddr, "instance", "", "Forgejo instance address")
|
||||
cmd.MarkFlagRequired("instance")
|
||||
cmd.Flags().StringVar(&argsVar.Secret, "secret", "", "secret shared with the Frogejo instance via forgejo-cli actions register")
|
||||
cmd.Flags().StringVar(&argsVar.Secret, "secret", "", "secret shared with the Forgejo instance via forgejo-cli actions register")
|
||||
cmd.MarkFlagRequired("secret")
|
||||
cmd.Flags().StringVar(&argsVar.Name, "name", "", "Runner name")
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@ import (
|
|||
"testing"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"connectrpc.com/connect"
|
||||
"gitea.com/gitea/act_runner/internal/pkg/client"
|
||||
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||
"gitea.com/gitea/act_runner/internal/pkg/ver"
|
||||
"github.com/bufbuild/connect-go"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/bufbuild/connect-go"
|
||||
"connectrpc.com/connect"
|
||||
"github.com/mattn/go-isatty"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -45,6 +45,8 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command,
|
|||
return fmt.Errorf("failed to load registration file: %w", err)
|
||||
}
|
||||
|
||||
cfg.Tune(reg.Address)
|
||||
|
||||
lbls := reg.Labels
|
||||
if len(cfg.Runner.Labels) > 0 {
|
||||
lbls = cfg.Runner.Labels
|
||||
|
@ -71,11 +73,8 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command,
|
|||
if err := envcheck.CheckIfDockerRunning(ctx, dockerSocketPath); err != nil {
|
||||
return err
|
||||
}
|
||||
// if dockerSocketPath passes the check, override DOCKER_HOST with dockerSocketPath
|
||||
os.Setenv("DOCKER_HOST", dockerSocketPath)
|
||||
// empty cfg.Container.DockerHost means act_runner need to find an available docker host automatically
|
||||
// and assign the path to cfg.Container.DockerHost
|
||||
if cfg.Container.DockerHost == "" {
|
||||
if cfg.Container.DockerHost == "automount" {
|
||||
cfg.Container.DockerHost = dockerSocketPath
|
||||
}
|
||||
// check the scheme, if the scheme is not npipe or unix
|
||||
|
@ -101,14 +100,15 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command,
|
|||
resp, err := runner.Declare(ctx, ls.Names())
|
||||
if err != nil && connect.CodeOf(err) == connect.CodeUnimplemented {
|
||||
// Gitea instance is older version. skip declare step.
|
||||
log.Warn("Because the Forgejo instance is an old version, skip declare labels and version.")
|
||||
log.Warn("Because the Forgejo instance is an old version, skipping declaring the labels and version.")
|
||||
} else if err != nil {
|
||||
log.WithError(err).Error("fail to invoke Declare")
|
||||
return err
|
||||
} else {
|
||||
log.Infof("runner: %s, with version: %s, with labels: %v, declare successfully",
|
||||
log.Infof("runner: %s, with version: %s, with labels: %v, declared successfully",
|
||||
resp.Msg.Runner.Name, resp.Msg.Runner.Version, resp.Msg.Runner.Labels)
|
||||
// if declare successfully, override the labels in the.runner file with valid labels in the config file (if specified)
|
||||
// if declared successfully, override the labels in the.runner file with valid labels in the config file (if specified)
|
||||
runner.Update(ctx, ls)
|
||||
reg.Labels = ls.ToStrings()
|
||||
if err := config.SaveRegistration(cfg.Runner.File, reg); err != nil {
|
||||
return fmt.Errorf("failed to save runner config: %w", err)
|
||||
|
@ -117,8 +117,18 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command,
|
|||
|
||||
poller := poll.New(cfg, cli, runner)
|
||||
|
||||
poller.Poll(ctx)
|
||||
go poller.Poll()
|
||||
|
||||
<-ctx.Done()
|
||||
log.Infof("runner: %s shutdown initiated, waiting [runner].shutdown_timeout=%s for running jobs to complete before shutting down", resp.Msg.Runner.Name, cfg.Runner.ShutdownTimeout)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), cfg.Runner.ShutdownTimeout)
|
||||
defer cancel()
|
||||
|
||||
err = poller.Shutdown(ctx)
|
||||
if err != nil {
|
||||
log.Warnf("runner: %s cancelled in progress jobs during shutdown", resp.Msg.Runner.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +183,7 @@ var commonSocketPaths = []string{
|
|||
|
||||
func getDockerSocketPath(configDockerHost string) (string, error) {
|
||||
// a `-` means don't mount the docker socket to job containers
|
||||
if configDockerHost != "" && configDockerHost != "-" {
|
||||
if configDockerHost != "automount" && configDockerHost != "-" {
|
||||
return configDockerHost, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -418,7 +418,9 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command
|
|||
|
||||
config.Env["ACT_EXEC"] = "true"
|
||||
|
||||
if t := config.Secrets["GITEA_TOKEN"]; t != "" {
|
||||
if t := config.Secrets["FORGEJO_TOKEN"]; t != "" {
|
||||
config.Token = t
|
||||
} else if t := config.Secrets["GITEA_TOKEN"]; t != "" {
|
||||
config.Token = t
|
||||
} else if t := config.Secrets["GITHUB_TOKEN"]; t != "" {
|
||||
config.Token = t
|
||||
|
@ -486,7 +488,7 @@ func loadExecCmd(ctx context.Context) *cobra.Command {
|
|||
execCmd.PersistentFlags().BoolVarP(&execArg.noSkipCheckout, "no-skip-checkout", "", false, "Do not skip actions/checkout")
|
||||
execCmd.PersistentFlags().BoolVarP(&execArg.debug, "debug", "d", false, "enable debug log")
|
||||
execCmd.PersistentFlags().BoolVarP(&execArg.dryrun, "dryrun", "n", false, "dryrun mode")
|
||||
execCmd.PersistentFlags().StringVarP(&execArg.image, "image", "i", "node:16-bullseye", "docker image to use")
|
||||
execCmd.PersistentFlags().StringVarP(&execArg.image, "image", "i", "node:20-bullseye", "Docker image to use. Use \"-self-hosted\" to run directly on the host.")
|
||||
execCmd.PersistentFlags().StringVarP(&execArg.network, "network", "", "", "Specify the network to which the container will connect")
|
||||
execCmd.PersistentFlags().BoolVarP(&execArg.enableIPv6, "enable-ipv6", "6", false, "Create network with IPv6 enabled.")
|
||||
execCmd.PersistentFlags().StringVarP(&execArg.githubInstance, "gitea-instance", "", "", "Gitea instance to use.")
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
|
||||
pingv1 "code.gitea.io/actions-proto-go/ping/v1"
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/bufbuild/connect-go"
|
||||
"connectrpc.com/connect"
|
||||
"github.com/mattn/go-isatty"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -91,7 +91,7 @@ const (
|
|||
)
|
||||
|
||||
var defaultLabels = []string{
|
||||
"docker:docker://node:16-bullseye",
|
||||
"docker:docker://node:20-bullseye",
|
||||
}
|
||||
|
||||
type registerInputs struct {
|
||||
|
@ -176,7 +176,7 @@ func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *co
|
|||
}
|
||||
|
||||
if validateLabels(r.Labels) != nil {
|
||||
log.Infoln("Invalid labels, please input again, leave blank to use the default labels (for example, ubuntu-20.04:docker://node:16-bullseye,ubuntu-18.04:docker://node:16-buster,linux_arm:host)")
|
||||
log.Infoln("Invalid labels, please input again, leave blank to use the default labels (for example, ubuntu-20.04:docker://node:20-bookworm,ubuntu-18.04:docker://node:20-bookworm)")
|
||||
return StageInputLabels
|
||||
}
|
||||
return StageWaitingForRegistration
|
||||
|
@ -240,7 +240,7 @@ func printStageHelp(stage registerStage) {
|
|||
hostname, _ := os.Hostname()
|
||||
log.Infof("Enter the runner name (if set empty, use hostname: %s):\n", hostname)
|
||||
case StageInputLabels:
|
||||
log.Infoln("Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-20.04:docker://node:16-bullseye,ubuntu-18.04:docker://node:16-buster,linux_arm:host):")
|
||||
log.Infoln("Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-20.04:docker://node:20-bookworm,ubuntu-18.04:docker://node:20-bookworm):")
|
||||
case StageWaitingForRegistration:
|
||||
log.Infoln("Waiting for registration...")
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"sync/atomic"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/bufbuild/connect-go"
|
||||
"connectrpc.com/connect"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
|
@ -20,49 +20,100 @@ import (
|
|||
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||
)
|
||||
|
||||
type Poller struct {
|
||||
const PollerID = "PollerID"
|
||||
|
||||
type Poller interface {
|
||||
Poll()
|
||||
Shutdown(ctx context.Context) error
|
||||
}
|
||||
|
||||
type poller struct {
|
||||
client client.Client
|
||||
runner *run.Runner
|
||||
runner run.RunnerInterface
|
||||
cfg *config.Config
|
||||
tasksVersion atomic.Int64 // tasksVersion used to store the version of the last task fetched from the Gitea.
|
||||
|
||||
pollingCtx context.Context
|
||||
shutdownPolling context.CancelFunc
|
||||
|
||||
jobsCtx context.Context
|
||||
shutdownJobs context.CancelFunc
|
||||
|
||||
done chan any
|
||||
}
|
||||
|
||||
func New(cfg *config.Config, client client.Client, runner *run.Runner) *Poller {
|
||||
return &Poller{
|
||||
client: client,
|
||||
runner: runner,
|
||||
cfg: cfg,
|
||||
}
|
||||
func New(cfg *config.Config, client client.Client, runner run.RunnerInterface) Poller {
|
||||
return (&poller{}).init(cfg, client, runner)
|
||||
}
|
||||
|
||||
func (p *Poller) Poll(ctx context.Context) {
|
||||
func (p *poller) init(cfg *config.Config, client client.Client, runner run.RunnerInterface) Poller {
|
||||
pollingCtx, shutdownPolling := context.WithCancel(context.Background())
|
||||
|
||||
jobsCtx, shutdownJobs := context.WithCancel(context.Background())
|
||||
|
||||
done := make(chan any)
|
||||
|
||||
p.client = client
|
||||
p.runner = runner
|
||||
p.cfg = cfg
|
||||
|
||||
p.pollingCtx = pollingCtx
|
||||
p.shutdownPolling = shutdownPolling
|
||||
|
||||
p.jobsCtx = jobsCtx
|
||||
p.shutdownJobs = shutdownJobs
|
||||
p.done = done
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *poller) Poll() {
|
||||
limiter := rate.NewLimiter(rate.Every(p.cfg.Runner.FetchInterval), 1)
|
||||
wg := &sync.WaitGroup{}
|
||||
for i := 0; i < p.cfg.Runner.Capacity; i++ {
|
||||
wg.Add(1)
|
||||
go p.poll(ctx, wg, limiter)
|
||||
go p.poll(i, wg, limiter)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// signal the poller is finished
|
||||
close(p.done)
|
||||
}
|
||||
|
||||
func (p *Poller) poll(ctx context.Context, wg *sync.WaitGroup, limiter *rate.Limiter) {
|
||||
func (p *poller) Shutdown(ctx context.Context) error {
|
||||
p.shutdownPolling()
|
||||
|
||||
select {
|
||||
case <-p.done:
|
||||
log.Trace("all jobs are complete")
|
||||
return nil
|
||||
|
||||
case <-ctx.Done():
|
||||
log.Trace("forcing the jobs to shutdown")
|
||||
p.shutdownJobs()
|
||||
<-p.done
|
||||
log.Trace("all jobs have been shutdown")
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *poller) poll(id int, wg *sync.WaitGroup, limiter *rate.Limiter) {
|
||||
log.Infof("[poller %d] launched", id)
|
||||
defer wg.Done()
|
||||
for {
|
||||
if err := limiter.Wait(ctx); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
log.WithError(err).Debug("limiter wait failed")
|
||||
}
|
||||
if err := limiter.Wait(p.pollingCtx); err != nil {
|
||||
log.Infof("[poller %d] shutdown", id)
|
||||
return
|
||||
}
|
||||
task, ok := p.fetchTask(ctx)
|
||||
task, ok := p.fetchTask(p.pollingCtx)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
p.runTaskWithRecover(ctx, task)
|
||||
p.runTaskWithRecover(p.jobsCtx, task)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Poller) runTaskWithRecover(ctx context.Context, task *runnerv1.Task) {
|
||||
func (p *poller) runTaskWithRecover(ctx context.Context, task *runnerv1.Task) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err := fmt.Errorf("panic: %v", r)
|
||||
|
@ -75,7 +126,7 @@ func (p *Poller) runTaskWithRecover(ctx context.Context, task *runnerv1.Task) {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *Poller) fetchTask(ctx context.Context) (*runnerv1.Task, bool) {
|
||||
func (p *poller) fetchTask(ctx context.Context) (*runnerv1.Task, bool) {
|
||||
reqCtx, cancel := context.WithTimeout(ctx, p.cfg.Runner.FetchTimeout)
|
||||
defer cancel()
|
||||
|
||||
|
@ -85,10 +136,15 @@ func (p *Poller) fetchTask(ctx context.Context) (*runnerv1.Task, bool) {
|
|||
TasksVersion: v,
|
||||
}))
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
log.Trace("deadline exceeded")
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to fetch task")
|
||||
if errors.Is(err, context.Canceled) {
|
||||
log.WithError(err).Debugf("shutdown, fetch task canceled")
|
||||
} else {
|
||||
log.WithError(err).Error("failed to fetch task")
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
|
263
internal/app/poll/poller_test.go
Normal file
263
internal/app/poll/poller_test.go
Normal file
|
@ -0,0 +1,263 @@
|
|||
// Copyright The Forgejo Authors.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package poll
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
|
||||
"code.gitea.io/actions-proto-go/ping/v1/pingv1connect"
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"code.gitea.io/actions-proto-go/runner/v1/runnerv1connect"
|
||||
"gitea.com/gitea/act_runner/internal/pkg/config"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type mockPoller struct {
|
||||
poller
|
||||
}
|
||||
|
||||
func (o *mockPoller) Poll() {
|
||||
o.poller.Poll()
|
||||
}
|
||||
|
||||
type mockClient struct {
|
||||
pingv1connect.PingServiceClient
|
||||
runnerv1connect.RunnerServiceClient
|
||||
|
||||
sleep time.Duration
|
||||
cancel bool
|
||||
err error
|
||||
noTask bool
|
||||
}
|
||||
|
||||
func (o mockClient) Address() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (o mockClient) Insecure() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *mockClient) FetchTask(ctx context.Context, req *connect.Request[runnerv1.FetchTaskRequest]) (*connect.Response[runnerv1.FetchTaskResponse], error) {
|
||||
if o.sleep > 0 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Trace("fetch task done")
|
||||
return nil, context.DeadlineExceeded
|
||||
case <-time.After(o.sleep):
|
||||
log.Trace("slept")
|
||||
return nil, fmt.Errorf("unexpected")
|
||||
}
|
||||
}
|
||||
if o.cancel {
|
||||
return nil, context.Canceled
|
||||
}
|
||||
if o.err != nil {
|
||||
return nil, o.err
|
||||
}
|
||||
task := &runnerv1.Task{}
|
||||
if o.noTask {
|
||||
task = nil
|
||||
o.noTask = false
|
||||
}
|
||||
|
||||
return connect.NewResponse(&runnerv1.FetchTaskResponse{
|
||||
Task: task,
|
||||
TasksVersion: int64(1),
|
||||
}), nil
|
||||
}
|
||||
|
||||
type mockRunner struct {
|
||||
cfg *config.Runner
|
||||
log chan string
|
||||
panics bool
|
||||
err error
|
||||
}
|
||||
|
||||
func (o *mockRunner) Run(ctx context.Context, task *runnerv1.Task) error {
|
||||
o.log <- "runner starts"
|
||||
if o.panics {
|
||||
log.Trace("panics")
|
||||
o.log <- "runner panics"
|
||||
o.panics = false
|
||||
panic("whatever")
|
||||
}
|
||||
if o.err != nil {
|
||||
log.Trace("error")
|
||||
o.log <- "runner error"
|
||||
err := o.err
|
||||
o.err = nil
|
||||
return err
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Trace("shutdown")
|
||||
o.log <- "runner shutdown"
|
||||
return nil
|
||||
case <-time.After(o.cfg.Timeout):
|
||||
log.Trace("after")
|
||||
o.log <- "runner timeout"
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setTrace(t *testing.T) {
|
||||
t.Helper()
|
||||
log.SetReportCaller(true)
|
||||
log.SetLevel(log.TraceLevel)
|
||||
}
|
||||
|
||||
func TestPoller_New(t *testing.T) {
|
||||
p := New(&config.Config{}, &mockClient{}, &mockRunner{})
|
||||
assert.NotNil(t, p)
|
||||
}
|
||||
|
||||
func TestPoller_Runner(t *testing.T) {
|
||||
setTrace(t)
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
timeout time.Duration
|
||||
noTask bool
|
||||
panics bool
|
||||
err error
|
||||
expected string
|
||||
contextTimeout time.Duration
|
||||
}{
|
||||
{
|
||||
name: "Simple",
|
||||
timeout: 10 * time.Second,
|
||||
expected: "runner shutdown",
|
||||
},
|
||||
{
|
||||
name: "Panics",
|
||||
timeout: 10 * time.Second,
|
||||
panics: true,
|
||||
expected: "runner panics",
|
||||
},
|
||||
{
|
||||
name: "Error",
|
||||
timeout: 10 * time.Second,
|
||||
err: fmt.Errorf("ERROR"),
|
||||
expected: "runner error",
|
||||
},
|
||||
{
|
||||
name: "PollTaskError",
|
||||
timeout: 10 * time.Second,
|
||||
noTask: true,
|
||||
expected: "runner shutdown",
|
||||
},
|
||||
{
|
||||
name: "ShutdownTimeout",
|
||||
timeout: 1 * time.Second,
|
||||
contextTimeout: 1 * time.Minute,
|
||||
expected: "runner timeout",
|
||||
},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
runnerLog := make(chan string, 3)
|
||||
configRunner := config.Runner{
|
||||
FetchInterval: 1,
|
||||
Capacity: 1,
|
||||
Timeout: testCase.timeout,
|
||||
}
|
||||
p := &mockPoller{}
|
||||
p.init(
|
||||
&config.Config{
|
||||
Runner: configRunner,
|
||||
},
|
||||
&mockClient{
|
||||
noTask: testCase.noTask,
|
||||
},
|
||||
&mockRunner{
|
||||
cfg: &configRunner,
|
||||
log: runnerLog,
|
||||
panics: testCase.panics,
|
||||
err: testCase.err,
|
||||
})
|
||||
go p.Poll()
|
||||
assert.Equal(t, "runner starts", <-runnerLog)
|
||||
var ctx context.Context
|
||||
var cancel context.CancelFunc
|
||||
if testCase.contextTimeout > 0 {
|
||||
ctx, cancel = context.WithTimeout(context.Background(), testCase.contextTimeout)
|
||||
defer cancel()
|
||||
} else {
|
||||
ctx, cancel = context.WithCancel(context.Background())
|
||||
cancel()
|
||||
}
|
||||
p.Shutdown(ctx)
|
||||
<-p.done
|
||||
assert.Equal(t, testCase.expected, <-runnerLog)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoller_Fetch(t *testing.T) {
|
||||
setTrace(t)
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
noTask bool
|
||||
sleep time.Duration
|
||||
err error
|
||||
cancel bool
|
||||
success bool
|
||||
}{
|
||||
{
|
||||
name: "Success",
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
name: "Timeout",
|
||||
sleep: 100 * time.Millisecond,
|
||||
},
|
||||
{
|
||||
name: "Canceled",
|
||||
cancel: true,
|
||||
},
|
||||
{
|
||||
name: "NoTask",
|
||||
noTask: true,
|
||||
},
|
||||
{
|
||||
name: "Error",
|
||||
err: fmt.Errorf("random error"),
|
||||
},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
configRunner := config.Runner{
|
||||
FetchTimeout: 1 * time.Millisecond,
|
||||
}
|
||||
p := &mockPoller{}
|
||||
p.init(
|
||||
&config.Config{
|
||||
Runner: configRunner,
|
||||
},
|
||||
&mockClient{
|
||||
sleep: testCase.sleep,
|
||||
cancel: testCase.cancel,
|
||||
noTask: testCase.noTask,
|
||||
err: testCase.err,
|
||||
},
|
||||
&mockRunner{},
|
||||
)
|
||||
task, ok := p.fetchTask(context.Background())
|
||||
if testCase.success {
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, task)
|
||||
} else {
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, task)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
24
internal/app/run/logging.go
Normal file
24
internal/app/run/logging.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package run
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NullLogger is used to create a new JobLogger to discard logs. This
|
||||
// will prevent these logs from being logged to the stdout, but
|
||||
// forward them to the Reporter via its hook.
|
||||
type NullLogger struct{}
|
||||
|
||||
// WithJobLogger creates a new logrus.Logger that will discard all logs.
|
||||
func (n NullLogger) WithJobLogger() *log.Logger {
|
||||
logger := log.New()
|
||||
logger.SetOutput(io.Discard)
|
||||
logger.SetLevel(log.TraceLevel)
|
||||
|
||||
return logger
|
||||
}
|
|
@ -13,7 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/bufbuild/connect-go"
|
||||
"connectrpc.com/connect"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/nektos/act/pkg/artifactcache"
|
||||
"github.com/nektos/act/pkg/common"
|
||||
|
@ -41,6 +41,10 @@ type Runner struct {
|
|||
runningTasks sync.Map
|
||||
}
|
||||
|
||||
type RunnerInterface interface {
|
||||
Run(ctx context.Context, task *runnerv1.Task) error
|
||||
}
|
||||
|
||||
func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) *Runner {
|
||||
ls := labels.Labels{}
|
||||
for _, v := range reg.Labels {
|
||||
|
@ -81,6 +85,7 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client)
|
|||
// set artifact gitea api
|
||||
artifactGiteaAPI := strings.TrimSuffix(cli.Address(), "/") + "/api/actions_pipeline/"
|
||||
envs["ACTIONS_RUNTIME_URL"] = artifactGiteaAPI
|
||||
envs["ACTIONS_RESULTS_URL"] = strings.TrimSuffix(cli.Address(), "/")
|
||||
|
||||
// Set specific environments to distinguish between Gitea and GitHub
|
||||
envs["GITEA_ACTIONS"] = "true"
|
||||
|
@ -104,7 +109,7 @@ func (r *Runner) Run(ctx context.Context, task *runnerv1.Task) error {
|
|||
|
||||
ctx, cancel := context.WithTimeout(ctx, r.cfg.Runner.Timeout)
|
||||
defer cancel()
|
||||
reporter := report.NewReporter(ctx, cancel, r.client, task)
|
||||
reporter := report.NewReporter(ctx, cancel, r.client, task, r.cfg.Runner.ReportInterval)
|
||||
var runErr error
|
||||
defer func() {
|
||||
lastWords := ""
|
||||
|
@ -163,14 +168,20 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||
RepositoryOwner: taskContext["repository_owner"].GetStringValue(),
|
||||
RetentionDays: taskContext["retention_days"].GetStringValue(),
|
||||
}
|
||||
if t := task.Secrets["GITEA_TOKEN"]; t != "" {
|
||||
if t := task.Secrets["FORGEJO_TOKEN"]; t != "" {
|
||||
preset.Token = t
|
||||
} else if t := task.Secrets["GITEA_TOKEN"]; t != "" {
|
||||
preset.Token = t
|
||||
} else if t := task.Secrets["GITHUB_TOKEN"]; t != "" {
|
||||
preset.Token = t
|
||||
}
|
||||
|
||||
// use task token to action api token
|
||||
r.envs["ACTIONS_RUNTIME_TOKEN"] = preset.Token
|
||||
giteaRuntimeToken := taskContext["gitea_runtime_token"].GetStringValue()
|
||||
if giteaRuntimeToken == "" {
|
||||
// use task token to action api token for previous Gitea Server Versions
|
||||
giteaRuntimeToken = preset.Token
|
||||
}
|
||||
r.envs["ACTIONS_RUNTIME_TOKEN"] = giteaRuntimeToken
|
||||
|
||||
eventJSON, err := json.Marshal(preset.Event)
|
||||
if err != nil {
|
||||
|
@ -182,6 +193,13 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||
maxLifetime = time.Until(deadline)
|
||||
}
|
||||
|
||||
var inputs map[string]string
|
||||
if preset.EventName == "workflow_dispatch" {
|
||||
if inputsRaw, ok := preset.Event["inputs"]; ok {
|
||||
inputs, _ = inputsRaw.(map[string]string)
|
||||
}
|
||||
}
|
||||
|
||||
runnerConfig := &runner.Config{
|
||||
// On Linux, Workdir will be like "/<parent_directory>/<owner>/<repo>"
|
||||
// On Windows, Workdir will be like "\<parent_directory>\<owner>\<repo>"
|
||||
|
@ -201,7 +219,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||
NoSkipCheckout: true,
|
||||
PresetGitHubContext: preset,
|
||||
EventJSON: string(eventJSON),
|
||||
ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id),
|
||||
ContainerNamePrefix: fmt.Sprintf("FORGEJO-ACTIONS-TASK-%d", task.Id),
|
||||
ContainerMaxLifetime: maxLifetime,
|
||||
ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network),
|
||||
ContainerNetworkEnableIPv6: r.cfg.Container.EnableIPv6,
|
||||
|
@ -212,6 +230,17 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||
PlatformPicker: r.labels.PickPlatform,
|
||||
Vars: task.Vars,
|
||||
ValidVolumes: r.cfg.Container.ValidVolumes,
|
||||
InsecureSkipTLS: r.cfg.Runner.Insecure,
|
||||
Inputs: inputs,
|
||||
}
|
||||
|
||||
if r.cfg.Log.JobLevel != "" {
|
||||
level, err := log.ParseLevel(r.cfg.Log.JobLevel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runnerConfig.JobLoggerLevel = &level
|
||||
}
|
||||
|
||||
rr, err := runner.New(runnerConfig)
|
||||
|
@ -225,6 +254,10 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||
// add logger recorders
|
||||
ctx = common.WithLoggerHook(ctx, reporter)
|
||||
|
||||
if !log.IsLevelEnabled(log.DebugLevel) {
|
||||
ctx = runner.WithJobLoggerFactory(ctx, NullLogger{})
|
||||
}
|
||||
|
||||
execErr := executor(ctx)
|
||||
reporter.SetOutputs(job.Outputs)
|
||||
return execErr
|
||||
|
@ -236,3 +269,7 @@ func (r *Runner) Declare(ctx context.Context, labels []string) (*connect.Respons
|
|||
Labels: labels,
|
||||
}))
|
||||
}
|
||||
|
||||
func (r *Runner) Update(ctx context.Context, labels labels.Labels) {
|
||||
r.labels = labels
|
||||
}
|
||||
|
|
37
internal/app/run/runner_test.go
Normal file
37
internal/app/run/runner_test.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package run
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"gitea.com/gitea/act_runner/internal/pkg/labels"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLabelUpdate(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ls := labels.Labels{}
|
||||
|
||||
initialLabel, err := labels.Parse("testlabel:docker://alpine")
|
||||
assert.NoError(t, err)
|
||||
ls = append(ls, initialLabel)
|
||||
|
||||
newLs := labels.Labels{}
|
||||
|
||||
newLabel, err := labels.Parse("next label:host")
|
||||
assert.NoError(t, err)
|
||||
newLs = append(newLs, initialLabel)
|
||||
newLs = append(newLs, newLabel)
|
||||
|
||||
runner := Runner{
|
||||
labels: ls,
|
||||
}
|
||||
|
||||
assert.Contains(t, runner.labels, initialLabel)
|
||||
assert.NotContains(t, runner.labels, newLabel)
|
||||
|
||||
runner.Update(ctx, newLs)
|
||||
|
||||
assert.Contains(t, runner.labels, initialLabel)
|
||||
assert.Contains(t, runner.labels, newLabel)
|
||||
}
|
|
@ -19,7 +19,7 @@ func Test_generateWorkflow(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
assert func(t *testing.T, wf *model.Workflow)
|
||||
assert func(t *testing.T, wf *model.Workflow, err error)
|
||||
want1 string
|
||||
wantErr bool
|
||||
}{
|
||||
|
@ -56,19 +56,41 @@ jobs:
|
|||
},
|
||||
},
|
||||
},
|
||||
assert: func(t *testing.T, wf *model.Workflow) {
|
||||
assert: func(t *testing.T, wf *model.Workflow, err error) {
|
||||
assert.DeepEqual(t, wf.GetJob("job9").Needs(), []string{"job1", "job2"})
|
||||
},
|
||||
want1: "job9",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid YAML syntax in top level env but wrong value type",
|
||||
args: args{
|
||||
task: &runnerv1.Task{
|
||||
WorkflowPayload: []byte(`
|
||||
on: push
|
||||
|
||||
env:
|
||||
value: {{ }}
|
||||
`),
|
||||
},
|
||||
},
|
||||
assert: func(t *testing.T, wf *model.Workflow, err error) {
|
||||
require.Nil(t, wf)
|
||||
assert.ErrorContains(t, err, "cannot unmarshal")
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, got1, err := generateWorkflow(tt.args.task)
|
||||
require.NoError(t, err)
|
||||
tt.assert(t, got)
|
||||
assert.Equal(t, got1, tt.want1)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, got1, tt.want1)
|
||||
}
|
||||
tt.assert(t, got, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
"code.gitea.io/actions-proto-go/ping/v1/pingv1connect"
|
||||
"code.gitea.io/actions-proto-go/runner/v1/runnerv1connect"
|
||||
"github.com/bufbuild/connect-go"
|
||||
"connectrpc.com/connect"
|
||||
)
|
||||
|
||||
func getHTTPClient(endpoint string, insecure bool) *http.Client {
|
||||
|
|
|
@ -5,7 +5,7 @@ package mocks
|
|||
import (
|
||||
context "context"
|
||||
|
||||
connect "github.com/bufbuild/connect-go"
|
||||
connect "connectrpc.com/connect"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
# Example configuration file, it's safe to copy this as the default config file without any modification.
|
||||
|
||||
# You don't have to copy this file to your instance,
|
||||
# just run `./act_runner generate-config > config.yaml` to generate a config file.
|
||||
# just run `forgejo-runner generate-config > config.yaml` to generate a config file.
|
||||
|
||||
log:
|
||||
# The level of logging, can be trace, debug, info, warn, error, fatal
|
||||
level: info
|
||||
# The level of logging for jobs, can be trace, debug, info, earn, error, fatal
|
||||
job_level: info
|
||||
|
||||
runner:
|
||||
# Where to store the registration result.
|
||||
|
@ -23,16 +25,24 @@ runner:
|
|||
# Please note that the Forgejo instance also has a timeout (3h by default) for the job.
|
||||
# So the job could be stopped by the Forgejo instance if it's timeout is shorter than this.
|
||||
timeout: 3h
|
||||
# Whether skip verifying the TLS certificate of the Forgejo instance.
|
||||
# The timeout for the runner to wait for running jobs to finish when
|
||||
# shutting down because a TERM or INT signal has been received. Any
|
||||
# running jobs that haven't finished after this timeout will be
|
||||
# cancelled.
|
||||
# If unset or zero the jobs will be cancelled immediately.
|
||||
shutdown_timeout: 3h
|
||||
# Whether skip verifying the TLS certificate of the instance.
|
||||
insecure: false
|
||||
# The timeout for fetching the job from the Forgejo instance.
|
||||
fetch_timeout: 5s
|
||||
# The interval for fetching the job from the Forgejo instance.
|
||||
fetch_interval: 2s
|
||||
# The interval for reporting the job status and logs to the Forgejo instance.
|
||||
report_interval: 1s
|
||||
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
|
||||
# Like: ["macos-arm64:host", "ubuntu-latest:docker://node:16-bullseye", "ubuntu-22.04:docker://node:16-bullseye"]
|
||||
# Like: ["macos-arm64:host", "ubuntu-latest:docker://node:20-bookworm", "ubuntu-22.04:docker://node:20-bookworm"]
|
||||
# If it's empty when registering, it will ask for inputting labels.
|
||||
# If it's empty when execute `deamon`, will use labels in `.runner` file.
|
||||
# If it's empty when executing the `daemon`, it will use labels in the `.runner` file.
|
||||
labels: []
|
||||
|
||||
cache:
|
||||
|
@ -49,8 +59,8 @@ cache:
|
|||
# 0 means to use a random available port.
|
||||
port: 0
|
||||
# The external cache server URL. Valid only when enable is true.
|
||||
# If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself.
|
||||
# The URL should generally end with "/".
|
||||
# If it's specified, it will be used to set the ACTIONS_CACHE_URL environment variable. The URL should generally end with "/".
|
||||
# Otherwise it will be set to the the URL of the internal cache server.
|
||||
external_server: ""
|
||||
|
||||
container:
|
||||
|
@ -79,10 +89,10 @@ container:
|
|||
# - '**'
|
||||
valid_volumes: []
|
||||
# overrides the docker client host with the specified one.
|
||||
# If it's empty, act_runner will find an available docker host automatically.
|
||||
# If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers.
|
||||
# If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work.
|
||||
docker_host: ""
|
||||
# If "-" or "", an available docker host will automatically be found.
|
||||
# If "automount", an available docker host will automatically be found and mounted in the job container (e.g. /var/run/docker.sock).
|
||||
# Otherwise the specified docker host will be used and an error will be returned if it doesn't work.
|
||||
docker_host: "-"
|
||||
# Pull docker image(s) even if already present
|
||||
force_pull: false
|
||||
|
||||
|
|
|
@ -16,20 +16,23 @@ import (
|
|||
|
||||
// Log represents the configuration for logging.
|
||||
type Log struct {
|
||||
Level string `yaml:"level"` // Level indicates the logging level.
|
||||
Level string `yaml:"level"` // Level indicates the logging level.
|
||||
JobLevel string `yaml:"job_level"` // JobLevel indicates the job logging level.
|
||||
}
|
||||
|
||||
// Runner represents the configuration for the runner.
|
||||
type Runner struct {
|
||||
File string `yaml:"file"` // File specifies the file path for the runner.
|
||||
Capacity int `yaml:"capacity"` // Capacity specifies the capacity of the runner.
|
||||
Envs map[string]string `yaml:"envs"` // Envs stores environment variables for the runner.
|
||||
EnvFile string `yaml:"env_file"` // EnvFile specifies the path to the file containing environment variables for the runner.
|
||||
Timeout time.Duration `yaml:"timeout"` // Timeout specifies the duration for runner timeout.
|
||||
Insecure bool `yaml:"insecure"` // Insecure indicates whether the runner operates in an insecure mode.
|
||||
FetchTimeout time.Duration `yaml:"fetch_timeout"` // FetchTimeout specifies the timeout duration for fetching resources.
|
||||
FetchInterval time.Duration `yaml:"fetch_interval"` // FetchInterval specifies the interval duration for fetching resources.
|
||||
Labels []string `yaml:"labels"` // Labels specifies the labels of the runner. Labels are declared on each startup
|
||||
File string `yaml:"file"` // File specifies the file path for the runner.
|
||||
Capacity int `yaml:"capacity"` // Capacity specifies the capacity of the runner.
|
||||
Envs map[string]string `yaml:"envs"` // Envs stores environment variables for the runner.
|
||||
EnvFile string `yaml:"env_file"` // EnvFile specifies the path to the file containing environment variables for the runner.
|
||||
Timeout time.Duration `yaml:"timeout"` // Timeout specifies the duration for runner timeout.
|
||||
ShutdownTimeout time.Duration `yaml:"shutdown_timeout"` // ShutdownTimeout specifies the duration to wait for running jobs to complete during a shutdown of the runner.
|
||||
Insecure bool `yaml:"insecure"` // Insecure indicates whether the runner operates in an insecure mode.
|
||||
FetchTimeout time.Duration `yaml:"fetch_timeout"` // FetchTimeout specifies the timeout duration for fetching resources.
|
||||
FetchInterval time.Duration `yaml:"fetch_interval"` // FetchInterval specifies the interval duration for fetching resources.
|
||||
ReportInterval time.Duration `yaml:"report_interval"` // ReportInterval specifies the interval duration for reporting status and logs of a running job.
|
||||
Labels []string `yaml:"labels"` // Labels specify the labels of the runner. Labels are declared on each startup
|
||||
}
|
||||
|
||||
// Cache represents the configuration for caching.
|
||||
|
@ -68,6 +71,16 @@ type Config struct {
|
|||
Host Host `yaml:"host"` // Host represents the configuration for the host.
|
||||
}
|
||||
|
||||
// Tune the config settings accordingly to the Forgejo instance that will be used.
|
||||
func (c *Config) Tune(instanceURL string) {
|
||||
if instanceURL == "https://codeberg.org" {
|
||||
if c.Runner.FetchInterval < 30*time.Second {
|
||||
log.Info("The runner is configured to be used by a public instance, fetch interval is set to 30 seconds.")
|
||||
c.Runner.FetchInterval = 30 * time.Second
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LoadDefault returns the default configuration.
|
||||
// If file is not empty, it will be used to load the configuration.
|
||||
func LoadDefault(file string) (*Config, error) {
|
||||
|
@ -89,6 +102,9 @@ func LoadDefault(file string) (*Config, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("read env file %q: %w", cfg.Runner.EnvFile, err)
|
||||
}
|
||||
if cfg.Runner.Envs == nil {
|
||||
cfg.Runner.Envs = map[string]string{}
|
||||
}
|
||||
for k, v := range envs {
|
||||
cfg.Runner.Envs[k] = v
|
||||
}
|
||||
|
@ -98,6 +114,9 @@ func LoadDefault(file string) (*Config, error) {
|
|||
if cfg.Log.Level == "" {
|
||||
cfg.Log.Level = "info"
|
||||
}
|
||||
if cfg.Log.JobLevel == "" {
|
||||
cfg.Log.JobLevel = "info"
|
||||
}
|
||||
if cfg.Runner.File == "" {
|
||||
cfg.Runner.File = ".runner"
|
||||
}
|
||||
|
@ -130,6 +149,13 @@ func LoadDefault(file string) (*Config, error) {
|
|||
if cfg.Runner.FetchInterval <= 0 {
|
||||
cfg.Runner.FetchInterval = 2 * time.Second
|
||||
}
|
||||
if cfg.Runner.ReportInterval <= 0 {
|
||||
cfg.Runner.ReportInterval = time.Second
|
||||
}
|
||||
|
||||
if cfg.Container.DockerHost == "" {
|
||||
cfg.Container.DockerHost = "-"
|
||||
}
|
||||
|
||||
// although `container.network_mode` will be deprecated, but we have to be compatible with it for now.
|
||||
if cfg.Container.NetworkMode != "" && cfg.Container.Network == "" {
|
||||
|
|
45
internal/pkg/config/config_test.go
Normal file
45
internal/pkg/config/config_test.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConfigTune(t *testing.T) {
|
||||
c := &Config{
|
||||
Runner: Runner{},
|
||||
}
|
||||
|
||||
t.Run("Public instance tuning", func(t *testing.T) {
|
||||
c.Runner.FetchInterval = 60 * time.Second
|
||||
c.Tune("https://codeberg.org")
|
||||
assert.EqualValues(t, 60*time.Second, c.Runner.FetchInterval)
|
||||
|
||||
c.Runner.FetchInterval = 2 * time.Second
|
||||
c.Tune("https://codeberg.org")
|
||||
assert.EqualValues(t, 30*time.Second, c.Runner.FetchInterval)
|
||||
})
|
||||
|
||||
t.Run("Non-public instance tuning", func(t *testing.T) {
|
||||
c.Runner.FetchInterval = 60 * time.Second
|
||||
c.Tune("https://example.com")
|
||||
assert.EqualValues(t, 60*time.Second, c.Runner.FetchInterval)
|
||||
|
||||
c.Runner.FetchInterval = 2 * time.Second
|
||||
c.Tune("https://codeberg.com")
|
||||
assert.EqualValues(t, 2*time.Second, c.Runner.FetchInterval)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDefaultSettings(t *testing.T) {
|
||||
config, err := LoadDefault("")
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, config.Container.DockerHost, "-")
|
||||
assert.EqualValues(t, config.Log.JobLevel, "info")
|
||||
}
|
|
@ -13,10 +13,7 @@ import (
|
|||
func CheckIfDockerRunning(ctx context.Context, configDockerHost string) error {
|
||||
opts := []client.Opt{
|
||||
client.FromEnv,
|
||||
}
|
||||
|
||||
if configDockerHost != "" {
|
||||
opts = append(opts, client.WithHost(configDockerHost))
|
||||
client.WithHost(configDockerHost),
|
||||
}
|
||||
|
||||
cli, err := client.NewClientWithOpts(opts...)
|
||||
|
@ -27,7 +24,7 @@ func CheckIfDockerRunning(ctx context.Context, configDockerHost string) error {
|
|||
|
||||
_, err = cli.Ping(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot ping the docker daemon, does it running? %w", err)
|
||||
return fmt.Errorf("cannot ping the docker daemon. is it running? %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -56,7 +56,6 @@ func (l Labels) PickPlatform(runsOn []string) string {
|
|||
switch label.Schema {
|
||||
case SchemeDocker:
|
||||
// "//" will be ignored
|
||||
// TODO maybe we should use 'ubuntu-18.04:docker:node:16-buster' instead
|
||||
platforms[label.Name] = strings.TrimPrefix(label.Arg, "//")
|
||||
case SchemeHost:
|
||||
platforms[label.Name] = "-self-hosted"
|
||||
|
@ -83,7 +82,7 @@ func (l Labels) PickPlatform(runsOn []string) string {
|
|||
// So the runner receives a task with a label that the runner doesn't have,
|
||||
// it happens when the user have edited the label of the runner in the web UI.
|
||||
// TODO: it may be not correct, what if the runner is used as host mode only?
|
||||
return "node:16-bullseye"
|
||||
return "node:20-bullseye"
|
||||
}
|
||||
|
||||
func (l Labels) Names() []string {
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
"time"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"connectrpc.com/connect"
|
||||
retry "github.com/avast/retry-go/v4"
|
||||
"github.com/bufbuild/connect-go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
@ -29,10 +29,11 @@ type Reporter struct {
|
|||
client client.Client
|
||||
clientM sync.Mutex
|
||||
|
||||
logOffset int
|
||||
logRows []*runnerv1.LogRow
|
||||
logReplacer *strings.Replacer
|
||||
oldnew []string
|
||||
logOffset int
|
||||
logRows []*runnerv1.LogRow
|
||||
logReplacer *strings.Replacer
|
||||
oldnew []string
|
||||
reportInterval time.Duration
|
||||
|
||||
state *runnerv1.TaskState
|
||||
stateMu sync.RWMutex
|
||||
|
@ -42,21 +43,25 @@ type Reporter struct {
|
|||
stopCommandEndToken string
|
||||
}
|
||||
|
||||
func NewReporter(ctx context.Context, cancel context.CancelFunc, client client.Client, task *runnerv1.Task) *Reporter {
|
||||
func NewReporter(ctx context.Context, cancel context.CancelFunc, client client.Client, task *runnerv1.Task, reportInterval time.Duration) *Reporter {
|
||||
var oldnew []string
|
||||
if v := task.Context.Fields["token"].GetStringValue(); v != "" {
|
||||
oldnew = append(oldnew, v, "***")
|
||||
}
|
||||
if v := task.Context.Fields["gitea_runtime_token"].GetStringValue(); v != "" {
|
||||
oldnew = append(oldnew, v, "***")
|
||||
}
|
||||
for _, v := range task.Secrets {
|
||||
oldnew = append(oldnew, v, "***")
|
||||
}
|
||||
|
||||
rv := &Reporter{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
client: client,
|
||||
oldnew: oldnew,
|
||||
logReplacer: strings.NewReplacer(oldnew...),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
client: client,
|
||||
oldnew: oldnew,
|
||||
reportInterval: reportInterval,
|
||||
logReplacer: strings.NewReplacer(oldnew...),
|
||||
state: &runnerv1.TaskState{
|
||||
Id: task.Id,
|
||||
},
|
||||
|
@ -111,6 +116,9 @@ func (r *Reporter) Fire(entry *log.Entry) error {
|
|||
for _, s := range r.state.Steps {
|
||||
if s.Result == runnerv1.Result_RESULT_UNSPECIFIED {
|
||||
s.Result = runnerv1.Result_RESULT_CANCELLED
|
||||
if jobResult == runnerv1.Result_RESULT_SKIPPED {
|
||||
s.Result = runnerv1.Result_RESULT_SKIPPED
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +182,7 @@ func (r *Reporter) RunDaemon() {
|
|||
_ = r.ReportLog(false)
|
||||
_ = r.ReportState()
|
||||
|
||||
time.AfterFunc(time.Second, r.RunDaemon)
|
||||
time.AfterFunc(r.reportInterval, r.RunDaemon)
|
||||
}
|
||||
|
||||
func (r *Reporter) Logf(format string, a ...interface{}) {
|
||||
|
@ -386,12 +394,13 @@ func (r *Reporter) handleCommand(originalContent, command, parameters, value str
|
|||
// Not implemented yet, so just return the original content.
|
||||
return &originalContent
|
||||
case "group":
|
||||
// Returning the original content, because I think the frontend
|
||||
// will use it when rendering the output.
|
||||
return &originalContent
|
||||
// Rewriting into ##[] syntax which the frontend understands
|
||||
content := "##[group]" + value
|
||||
return &content
|
||||
case "endgroup":
|
||||
// Ditto
|
||||
return &originalContent
|
||||
content := "##[endgroup]"
|
||||
return &content
|
||||
case "stop-commands":
|
||||
r.stopCommandEndToken = value
|
||||
return nil
|
||||
|
@ -418,7 +427,7 @@ func (r *Reporter) parseLogRow(entry *log.Entry) *runnerv1.LogRow {
|
|||
|
||||
return &runnerv1.LogRow{
|
||||
Time: timestamppb.New(entry.Time),
|
||||
Content: content,
|
||||
Content: strings.ToValidUTF8(content, "?"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,10 @@ import (
|
|||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
connect_go "github.com/bufbuild/connect-go"
|
||||
connect_go "connectrpc.com/connect"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
@ -96,8 +97,8 @@ func TestReporter_parseLogRow(t *testing.T) {
|
|||
"::endgroup::",
|
||||
},
|
||||
[]string{
|
||||
"::group::",
|
||||
"::endgroup::",
|
||||
"##[group]",
|
||||
"##[endgroup]",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -173,7 +174,7 @@ func TestReporter_Fire(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
reporter := NewReporter(ctx, cancel, client, &runnerv1.Task{
|
||||
Context: taskCtx,
|
||||
})
|
||||
}, time.Second)
|
||||
defer func() {
|
||||
assert.NoError(t, reporter.Close(""))
|
||||
}()
|
||||
|
|
12
renovate.json
Normal file
12
renovate.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["local>forgejo/renovate-config"],
|
||||
"prConcurrentLimit": 1,
|
||||
"packageRules": [
|
||||
{
|
||||
"description": "Disable nektos/act, it's replaced",
|
||||
"matchDepNames": ["github.com/nektos/act"],
|
||||
"enabled": false
|
||||
}
|
||||
]
|
||||
}
|
67
scripts/systemd.md
Normal file
67
scripts/systemd.md
Normal file
|
@ -0,0 +1,67 @@
|
|||
# Forgejo Runner with systemd User Services
|
||||
|
||||
It is possible to use systemd's user services together with
|
||||
[podman](https://podman.io/) to run `forgejo-runner` using a normal user
|
||||
account without any privileges and automatically start on boot.
|
||||
|
||||
This was last tested on Fedora 39 on 2024-02-19, but should work elsewhere as
|
||||
well.
|
||||
|
||||
Place the `forgejo-runner` binary in `/usr/local/bin/forgejo-runner` and make
|
||||
sure it can be executed (`chmod +x /usr/local/bin/forgejo-runner`).
|
||||
|
||||
Install and enable `podman` as a user service:
|
||||
|
||||
```bash
|
||||
$ sudo dnf -y install podman
|
||||
```
|
||||
|
||||
You *may* need to reboot your system after installing `podman` as it
|
||||
modifies some system configuration(s) that may need to be activated. Without
|
||||
rebooting the system my runner errored out when trying to set firewall rules, a
|
||||
reboot fixed it.
|
||||
|
||||
Enable `podman` as a user service:
|
||||
|
||||
```
|
||||
$ systemctl --user start podman.socket
|
||||
$ systemctl --user enable podman.socket
|
||||
```
|
||||
|
||||
Make sure processes remain after your user account logs out:
|
||||
|
||||
```bash
|
||||
$ loginctl enable-linger
|
||||
```
|
||||
|
||||
Create the file `/etc/systemd/user/forgejo-runner.service` with the following
|
||||
content:
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Forgejo Runner
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/forgejo-runner daemon
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
Now activate it as a user service:
|
||||
|
||||
```bash
|
||||
$ systemctl --user daemon-reload
|
||||
$ systemctl --user start forgejo-runner
|
||||
$ systemctl --user enable forgejo-runner
|
||||
```
|
||||
|
||||
To see/follow the log of `forgejo-runner`:
|
||||
|
||||
```bash
|
||||
$ journalctl -f -t forgejo-runner
|
||||
```
|
||||
|
||||
If you reboot your system, all should come back automatically.
|
Loading…
Reference in a new issue