Compare commits
198 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 | ||
![]() |
b96f044905 | ||
![]() |
d7e471a392 | ||
![]() |
f3ac0def98 | ||
![]() |
45c67b92f6 | ||
![]() |
09669f13cf | ||
![]() |
e38ba5e7db | ||
![]() |
77ce39c2d3 | ||
![]() |
52b952be0f | ||
![]() |
700a6de5bc | ||
![]() |
d22ee0fb8e | ||
![]() |
7db5a7f8d9 | ||
![]() |
863fb9c760 | ||
![]() |
1139bb7d12 | ||
![]() |
330199c532 | ||
![]() |
f6eadb933a | ||
![]() |
346c7af6a9 | ||
![]() |
63f4a6f746 | ||
![]() |
fd83ce5964 | ||
![]() |
c31664dce4 | ||
![]() |
409d49bcc4 | ||
![]() |
5407eeb50d | ||
![]() |
e934c2a70d | ||
![]() |
cca6cc9bea | ||
![]() |
9b05b16463 | ||
![]() |
cf2608d1ea | ||
![]() |
92cd7c8e19 | ||
![]() |
6d77918ad1 | ||
![]() |
f0dc5e90a0 | ||
![]() |
a9c4dbe512 | ||
![]() |
eea67757f2 | ||
![]() |
d668f23d4f | ||
![]() |
0136b86ab7 | ||
![]() |
9a965f0d41 | ||
![]() |
1e9af8efba | ||
![]() |
d2f408d683 | ||
![]() |
1917d803a8 | ||
![]() |
7e9d43667b | ||
![]() |
83572c5c71 | ||
![]() |
0863f48c7e | ||
![]() |
d4bcd15847 | ||
![]() |
62db322759 | ||
![]() |
9efc297f1f | ||
![]() |
b5b83fd62b | ||
![]() |
a441c04a13 | ||
![]() |
7b73082ea2 | ||
![]() |
b3f32e59af | ||
![]() |
513a5eb80e | ||
![]() |
9cb0716425 | ||
![]() |
bf11dac848 | ||
![]() |
e8448e3807 | ||
![]() |
29fff564cd | ||
![]() |
924748200e | ||
![]() |
8de0ce42b9 | ||
![]() |
716eca31e9 | ||
![]() |
00da0ada8b | ||
![]() |
d608ad6210 | ||
![]() |
bbc80cb926 | ||
![]() |
70f6c8bf21 | ||
![]() |
b6bc471f38 | ||
![]() |
8e93b0e8e8 | ||
![]() |
a379783994 | ||
![]() |
b1bfa4968e | ||
![]() |
d556450664 | ||
![]() |
830ad470aa | ||
![]() |
7bf25c2559 | ||
![]() |
294912488c | ||
![]() |
9d79a0b92d | ||
![]() |
b9e3e5b62d | ||
![]() |
8d49cc7e27 | ||
![]() |
deefb19f21 | ||
![]() |
f2743b28da | ||
![]() |
a6bb88d7c1 | ||
![]() |
6f26e40f80 | ||
![]() |
e87b34bdc6 | ||
![]() |
c5f53958be | ||
![]() |
fd6764ac8e | ||
![]() |
64137dcfb7 | ||
![]() |
b0aaffb661 |
51 changed files with 1736 additions and 817 deletions
16
.forgejo/cascading-pr-setup-forgejo
Executable file
16
.forgejo/cascading-pr-setup-forgejo
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
setup_forgejo=$1
|
||||
setup_forgejo_pr=$2
|
||||
runner=$3
|
||||
runner_pr=$4
|
||||
|
||||
url=$(jq --raw-output .head.repo.html_url < $runner_pr)
|
||||
test "$url" != null
|
||||
branch=$(jq --raw-output .head.ref < $runner_pr)
|
||||
test "$branch" != null
|
||||
cd $setup_forgejo
|
||||
./utils/upgrade-runner.sh $url @$branch
|
||||
date > last-upgrade
|
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]}"
|
11
.forgejo/testdata/ipv6.yml
vendored
Normal file
11
.forgejo/testdata/ipv6.yml
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
on: push
|
||||
jobs:
|
||||
ipv6:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: code.forgejo.org/oci/debian:bookworm
|
||||
steps:
|
||||
- run: |
|
||||
apt update -qq ; apt --quiet install -qq --yes iputils-ping
|
||||
ping -c 1 -6 ::1
|
90
.forgejo/workflows/build-release-integration.yml
Normal file
90
.forgejo/workflows/build-release-integration.yml
Normal file
|
@ -0,0 +1,90 @@
|
|||
name: Integration tests for the release process
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- go.mod
|
||||
- Dockerfile
|
||||
- .forgejo/workflows/build-release.yml
|
||||
- .forgejo/workflows/build-release-integration.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- go.mod
|
||||
- Dockerfile
|
||||
- .forgejo/workflows/build-release.yml
|
||||
- .forgejo/workflows/build-release-integration.yml
|
||||
|
||||
jobs:
|
||||
release-simulation:
|
||||
runs-on: self-hosted
|
||||
if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-release'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- id: forgejo
|
||||
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
||||
with:
|
||||
user: root
|
||||
password: admin1234
|
||||
image-version: 1.20
|
||||
lxc-ip-prefix: 10.0.9
|
||||
|
||||
- name: publish
|
||||
run: |
|
||||
set -x
|
||||
|
||||
version=1.2.3
|
||||
cat > /etc/docker/daemon.json <<EOF
|
||||
{
|
||||
"insecure-registries" : ["${{ steps.forgejo.outputs.host-port }}"]
|
||||
}
|
||||
EOF
|
||||
systemctl restart docker
|
||||
|
||||
dir=$(mktemp -d)
|
||||
trap "rm -fr $dir" EXIT
|
||||
|
||||
url=http://root:admin1234@${{ steps.forgejo.outputs.host-port }}
|
||||
export FORGEJO_RUNNER_LOGS="${{ steps.forgejo.outputs.runner-logs }}"
|
||||
|
||||
#
|
||||
# Create a new project with the runner and the release workflow only
|
||||
#
|
||||
rsync -a --exclude .git ./ $dir/
|
||||
rm $(find $dir/.forgejo/workflows/*.yml | grep -v build-release.yml)
|
||||
forgejo-test-helper.sh push $dir $url root runner
|
||||
sha=$(forgejo-test-helper.sh branch_tip $url root/runner main)
|
||||
|
||||
#
|
||||
# Push a tag to trigger the release workflow and wait for it to complete
|
||||
#
|
||||
forgejo-curl.sh api_json --data-raw '{"tag_name": "v'$version'", "target": "'$sha'"}' $url/api/v1/repos/root/runner/tags
|
||||
LOOPS=180 forgejo-test-helper.sh wait_success "$url" root/runner $sha
|
||||
|
||||
#
|
||||
# uncomment to see the logs even when everything is reported to be working ok
|
||||
#
|
||||
#cat $FORGEJO_RUNNER_LOGS
|
||||
|
||||
#
|
||||
# Minimal sanity checks. e2e test is for the setup-forgejo action
|
||||
#
|
||||
for arch in amd64 arm64 ; do
|
||||
binary=forgejo-runner-$version-linux-$arch
|
||||
for suffix in '' '.xz' ; do
|
||||
curl --fail -L -sS $url/root/runner/releases/download/v$version/$binary$suffix > $binary$suffix
|
||||
if test "$suffix" = .xz ; then
|
||||
unxz --keep $binary$suffix
|
||||
fi
|
||||
chmod +x $binary
|
||||
./$binary --version | grep $version
|
||||
curl --fail -L -sS $url/root/runner/releases/download/v$version/$binary$suffix.sha256 > $binary$suffix.sha256
|
||||
shasum -a 256 --check $binary$suffix.sha256
|
||||
rm $binary$suffix
|
||||
done
|
||||
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
|
|
@ -1,6 +1,16 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# https://code.forgejo.org/forgejo/runner
|
||||
#
|
||||
# Build the runner binaries and OCI images
|
||||
#
|
||||
# ROLE: forgejo-integration
|
||||
# DOER: forgejo-ci
|
||||
# TOKEN: <generated from https://code.forgejo.org/forgejo-ci>
|
||||
#
|
||||
name: Build release
|
||||
|
||||
on:
|
||||
on:
|
||||
push:
|
||||
tags: 'v*'
|
||||
|
||||
|
@ -8,126 +18,86 @@ jobs:
|
|||
release:
|
||||
runs-on: self-hosted
|
||||
# root is used for testing, allow it
|
||||
if: github.repository_owner == 'forgejo-integration' || github.repository_owner == 'root'
|
||||
if: secrets.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- id: verbose
|
||||
- name: Increase the verbosity when there are no secrets
|
||||
id: verbose
|
||||
run: |
|
||||
# if there are no secrets, be verbose
|
||||
if test -z "${{ secrets.TOKEN }}"; then
|
||||
value=true
|
||||
else
|
||||
value=false
|
||||
fi
|
||||
echo "value=$value" >> "$GITHUB_OUTPUT"
|
||||
echo "shell=set -x" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- id: registry
|
||||
|
||||
- name: Sanitize the name of the repository
|
||||
id: repository
|
||||
run: |
|
||||
${{ steps.verbose.outputs.shell }}
|
||||
echo "value=${GITHUB_REPOSITORY##*/}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: create test TOKEN
|
||||
id: token
|
||||
if: ${{ secrets.TOKEN == '' }}
|
||||
run: |
|
||||
apt-get -qq install -y jq
|
||||
url="${{ env.GITHUB_SERVER_URL }}"
|
||||
hostport=${url##http*://}
|
||||
hostport=${hostport%%/}
|
||||
echo "host-port=${hostport}" >> "$GITHUB_OUTPUT"
|
||||
if ! [[ $url =~ ^http:// ]] ; then
|
||||
exit 0
|
||||
fi
|
||||
doer=root
|
||||
api=http://$doer:admin1234@$hostport/api/v1/users/$doer/tokens
|
||||
curl -sS -X DELETE $api/release
|
||||
token=$(curl -sS -X POST -H 'Content-Type: application/json' --data-raw '{"name": "release", "scopes": ["all"]}' $api | jq --raw-output .sha1)
|
||||
echo "value=${token}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: version from ref_name
|
||||
id: tag-version
|
||||
run: |
|
||||
version=${GITHUB_REF_NAME##*v}
|
||||
echo "value=$version" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: release notes
|
||||
id: release-notes
|
||||
run: |
|
||||
anchor=${{ steps.tag-version.outputs.value }}
|
||||
anchor=${anchor//./-}
|
||||
cat >> "$GITHUB_OUTPUT" <<EOF
|
||||
insecure=true
|
||||
buildx-config<<ENDVAR
|
||||
[registry."${hostport}"]
|
||||
http = true
|
||||
value<<ENDVAR
|
||||
See https://code.forgejo.org/forgejo/runner/src/branch/main/RELEASE-NOTES.md#$anchor
|
||||
ENDVAR
|
||||
EOF
|
||||
|
||||
- id: secrets
|
||||
run: |
|
||||
token="${{ secrets.TOKEN }}"
|
||||
doer="${{ secrets.DOER }}"
|
||||
if test -z "$token"; then
|
||||
apt-get -qq install -y jq
|
||||
doer=root
|
||||
api=http://$doer:admin1234@${{ steps.registry.outputs.host-port }}/api/v1/users/$doer/tokens
|
||||
curl -sS -X DELETE $api/release
|
||||
token=$(curl -sS -X POST -H 'Content-Type: application/json' --data-raw '{"name": "release", "scopes": ["all"]}' $api | jq --raw-output .sha1)
|
||||
fi
|
||||
echo "token=${token}" >> "$GITHUB_OUTPUT"
|
||||
echo "doer=${doer}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: allow docker pull/push to forgejo
|
||||
if: ${{ steps.registry.outputs.insecure }}
|
||||
run: |-
|
||||
mkdir /etc/docker
|
||||
cat > /etc/docker/daemon.json <<EOF
|
||||
{
|
||||
"insecure-registries" : ["${{ steps.registry.outputs.host-port }}"],
|
||||
"bip": "172.26.0.1/16"
|
||||
}
|
||||
EOF
|
||||
|
||||
- run: |
|
||||
echo deb http://deb.debian.org/debian bullseye-backports main | tee /etc/apt/sources.list.d/backports.list && apt-get -qq update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -qq -y -t bullseye-backports docker.io
|
||||
|
||||
- uses: https://github.com/docker/setup-buildx-action@v2
|
||||
with:
|
||||
config-inline: |
|
||||
${{ steps.registry.outputs.buildx-config }}
|
||||
|
||||
- run: |
|
||||
token="${{ steps.secrets.outputs.token }}" ; test -z "$token" && token="${{ secrets.TOKEN }}"
|
||||
doer="${{ steps.secrets.outputs.doer }}" ; test -z "$doer" && doer="${{ secrets.DOER }}"
|
||||
BASE64_AUTH=`echo -n "$doer:$token" | base64`
|
||||
mkdir -p ~/.docker
|
||||
echo "{\"auths\": {\"$CI_REGISTRY\": {\"auth\": \"$BASE64_AUTH\"}}}" > ~/.docker/config.json
|
||||
env:
|
||||
CI_REGISTRY: "${{ env.GITHUB_SERVER_URL }}${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||
|
||||
- id: build
|
||||
run: |
|
||||
${{ steps.verbose.outputs.shell }}
|
||||
tag="${{ github.ref_name }}"
|
||||
tag=${tag##*v}
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
echo "image=${{ steps.registry.outputs.host-port }}/${{ github.repository }}:${tag}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: https://github.com/docker/build-push-action@v4
|
||||
# workaround until https://github.com/docker/build-push-action/commit/d8823bfaed2a82c6f5d4799a2f8e86173c461aba is in @v4 or @v5 is released
|
||||
env:
|
||||
ACTIONS_RUNTIME_TOKEN: ''
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.build.outputs.image }}
|
||||
|
||||
- run: |
|
||||
${{ steps.verbose.outputs.shell }}
|
||||
mkdir -p release
|
||||
for arch in amd64 arm64; do
|
||||
docker create --platform linux/$arch --name runner ${{ steps.build.outputs.image }}
|
||||
docker cp runner:/bin/forgejo-runner release/forgejo-runner-$arch
|
||||
shasum -a 256 < release/forgejo-runner-$arch | cut -f1 -d ' ' > release/forgejo-runner-$arch.sha256
|
||||
docker rm runner
|
||||
done
|
||||
|
||||
- name: publish release (when TOKEN secret is NOT set)
|
||||
- name: build without TOKEN
|
||||
if: ${{ secrets.TOKEN == '' }}
|
||||
uses: https://code.forgejo.org/actions/forgejo-release@v1
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v5
|
||||
with:
|
||||
direction: upload
|
||||
release-dir: release
|
||||
release-notes: "RELEASE-NOTES#${{ steps.build.outputs.tag }}"
|
||||
token: ${{ steps.secrets.outputs.token }}
|
||||
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
||||
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||
repository: "${{ steps.repository.outputs.value }}"
|
||||
doer: root
|
||||
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 }}"
|
||||
binary-name: forgejo-runner
|
||||
binary-path: /bin/forgejo-runner
|
||||
verbose: ${{ steps.verbose.outputs.value }}
|
||||
|
||||
- name: publish release (when TOKEN secret is set)
|
||||
- name: build with TOKEN
|
||||
if: ${{ secrets.TOKEN != '' }}
|
||||
uses: https://code.forgejo.org/actions/forgejo-release@v1
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v5
|
||||
with:
|
||||
direction: upload
|
||||
release-dir: release
|
||||
release-notes: "RELEASE-NOTES#${{ steps.build.outputs.tag }}"
|
||||
token: ${{ secrets.TOKEN }}
|
||||
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
||||
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||
repository: "${{ steps.repository.outputs.value }}"
|
||||
doer: "${{ secrets.DOER }}"
|
||||
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 }}"
|
||||
binary-name: forgejo-runner
|
||||
binary-path: /bin/forgejo-runner
|
||||
verbose: ${{ steps.verbose.outputs.value }}
|
||||
|
|
25
.forgejo/workflows/cascade-setup-forgejo.yml
Normal file
25
.forgejo/workflows/cascade-setup-forgejo.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- closed
|
||||
jobs:
|
||||
cascade:
|
||||
runs-on: docker
|
||||
if: vars.CASCADE != 'no'
|
||||
steps:
|
||||
- uses: actions/cascading-pr@v1
|
||||
with:
|
||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||
origin-repo: forgejo/runner
|
||||
origin-token: ${{ secrets.CASCADING_PR_ORIGIN }}
|
||||
origin-pr: ${{ github.event.pull_request.number }}
|
||||
destination-url: ${{ env.GITHUB_SERVER_URL }}
|
||||
destination-repo: actions/setup-forgejo
|
||||
destination-fork-repo: cascading-pr/setup-forgejo
|
||||
destination-branch: main
|
||||
destination-token: ${{ secrets.CASCADING_PR_DESTINATION }}
|
||||
close-merge: true
|
||||
update: .forgejo/cascading-pr-setup-forgejo
|
70
.forgejo/workflows/example-docker-compose.yml
Normal file
70
.forgejo/workflows/example-docker-compose.yml
Normal file
|
@ -0,0 +1,70 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
example-docker-compose:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install docker
|
||||
run: |
|
||||
apt-get update -qq
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get install -qq -y ca-certificates curl gnupg
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
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
|
||||
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
|
||||
run: |
|
||||
set -x
|
||||
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"
|
||||
#
|
||||
# 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
|
||||
#
|
||||
success='DEMO WORKFLOW SUCCESS'
|
||||
failure='DEMO WORKFLOW FAILURE'
|
||||
for delay in $(seq 60) ; do
|
||||
$cli logs demo-workflow > /tmp/out
|
||||
grep --quiet "$success" /tmp/out && break
|
||||
grep --quiet "$failure" /tmp/out && break
|
||||
$cli ps --all
|
||||
$cli logs --tail=20 runner-daemon demo-workflow
|
||||
sleep 30
|
||||
done
|
||||
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: full docker compose logs
|
||||
if: always()
|
||||
run: |
|
||||
cd examples/docker-compose
|
||||
docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml logs
|
|
@ -1,59 +0,0 @@
|
|||
name: Integration tests for the release process
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- go.mod
|
||||
- Dockerfile
|
||||
- .forgejo/workflows/release.yml
|
||||
- .forgejo/workflows/integration.yml
|
||||
|
||||
jobs:
|
||||
release-simulation:
|
||||
runs-on: self-hosted
|
||||
if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-experimental' && github.repository_owner != 'forgejo-release'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- id: forgejo
|
||||
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
||||
with:
|
||||
user: root
|
||||
password: admin1234
|
||||
image-version: 1.19
|
||||
lxc-ip-prefix: 10.0.9
|
||||
|
||||
- name: publish the runner release
|
||||
run: |
|
||||
set -x
|
||||
|
||||
dir=$(mktemp -d)
|
||||
trap "rm -fr $dir" EXIT
|
||||
|
||||
url=http://root:admin1234@${{ steps.forgejo.outputs.host-port }}
|
||||
export FORGEJO_RUNNER_LOGS="${{ steps.forgejo.outputs.runner-logs }}"
|
||||
|
||||
#
|
||||
# Create a new project with the runner and the release workflow only
|
||||
#
|
||||
rsync -a --exclude .git ./ $dir/
|
||||
rm $(find $dir/.forgejo/workflows/*.yml | grep -v release.yml)
|
||||
forgejo-test-helper.sh push $dir $url root runner |& tee $dir/pushed
|
||||
eval $(grep '^sha=' < $dir/pushed)
|
||||
|
||||
#
|
||||
# Push a tag to trigger the release workflow and wait for it to complete
|
||||
#
|
||||
forgejo-test-helper.sh api POST $url repos/root/runner/tags ${{ steps.forgejo.outputs.token }} --data-raw '{"tag_name": "v1.2.3", "target": "'$sha'"}'
|
||||
LOOPS=180 forgejo-test-helper.sh wait_success "$url" root/runner $sha
|
||||
|
||||
#
|
||||
# Minimal sanity checks. e2e test is for the setup-forgejo action
|
||||
# and the infrastructure playbook.
|
||||
#
|
||||
curl -L -sS $url/root/runner/releases/download/v1.2.3/forgejo-runner-amd64 > forgejo-runner
|
||||
chmod +x forgejo-runner
|
||||
./forgejo-runner --version | grep 1.2.3
|
||||
curl -L -sS $url/root/runner/releases/download/v1.2.3/forgejo-runner-amd64.sha256 > forgejo-runner.one
|
||||
shasum -a 256 < forgejo-runner | cut -f1 -d ' ' > forgejo-runner.two
|
||||
diff forgejo-runner.one forgejo-runner.two
|
|
@ -1,40 +0,0 @@
|
|||
name: Publish release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: 'v*'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: self-hosted
|
||||
if: github.repository_owner == 'forgejo-release' && secrets.TOKEN != ''
|
||||
steps:
|
||||
|
||||
- name: install the certificate authority
|
||||
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
|
||||
|
||||
- name: download release
|
||||
uses: https://code.forgejo.org/actions/forgejo-release@v1
|
||||
with:
|
||||
url: https://code.forgejo.org
|
||||
repo: forgejo-integration/runner
|
||||
direction: download
|
||||
release-dir: release
|
||||
download-retry: 60
|
||||
token: ${{ secrets.TOKEN }}
|
||||
|
||||
- name: upload release
|
||||
uses: https://code.forgejo.org/actions/forgejo-release@v1
|
||||
with:
|
||||
url: https://code.forgejo.org
|
||||
repo: forgejo/runner
|
||||
direction: upload
|
||||
release-dir: release
|
||||
release-notes: "RELEASE-NOTES"
|
||||
token: ${{ secrets.TOKEN }}
|
||||
gpg-private-key: ${{ secrets.GPG }}
|
|
@ -1,43 +0,0 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
name: copy container images from integration to the destination organization
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: 'v*'
|
||||
|
||||
jobs:
|
||||
builder:
|
||||
runs-on: self-hosted
|
||||
if: github.repository_owner == 'forgejo-release' && secrets.TOKEN != ''
|
||||
steps:
|
||||
|
||||
- name: apt-get install docker.io
|
||||
run: |
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -qq -y docker.io
|
||||
|
||||
- name: login code.forgejo.org
|
||||
uses: https://github.com/docker/login-action@v2
|
||||
with:
|
||||
registry: code.forgejo.org
|
||||
username: ${{ secrets.DOER }}
|
||||
password: ${{ secrets.TOKEN }}
|
||||
|
||||
- id: tag
|
||||
run: |
|
||||
tag="${{ github.ref_name }}"
|
||||
tag=${tag##*v}
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: https://code.forgejo.org/forgejo/forgejo-container-image@v1
|
||||
env:
|
||||
VERIFY: 'false'
|
||||
with:
|
||||
url: https://code.forgejo.org
|
||||
destination-owner: forgejo
|
||||
owner: forgejo-integration
|
||||
suffixes: ' '
|
||||
project: runner
|
||||
tag: ${{ steps.tag.outputs.tag }}
|
||||
doer: ${{ secrets.DOER }}
|
||||
token: ${{ secrets.TOKEN }}
|
||||
verbose: true
|
42
.forgejo/workflows/publish-release.yml
Normal file
42
.forgejo/workflows/publish-release.yml
Normal file
|
@ -0,0 +1,42 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# https://forgejo.octopuce.forgejo.org/forgejo-release/runner
|
||||
#
|
||||
# Copies & sign a release from code.forgejo.org/forgejo-integration/runner to code.forgejo.org/forgejo/runner
|
||||
#
|
||||
# ROLE: forgejo-release
|
||||
# FORGEJO: https://code.forgejo.org
|
||||
# FROM_OWNER: forgejo-integration
|
||||
# TO_OWNER: forgejo
|
||||
# DOER: release-team
|
||||
# TOKEN: <generated from codeberg.org/release-team>
|
||||
# GPG_PRIVATE_KEY: <XYZ>
|
||||
# GPG_PASSPHRASE: <ABC>
|
||||
#
|
||||
name: publish
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: 'v*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: self-hosted
|
||||
if: secrets.DOER != '' && secrets.FORGEJO != '' && secrets.TO_OWNER != '' && secrets.FROM_OWNER != '' && secrets.TOKEN != ''
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: copy & sign
|
||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v1
|
||||
with:
|
||||
forgejo: ${{ secrets.FORGEJO }}
|
||||
from-owner: ${{ secrets.FROM_OWNER }}
|
||||
to-owner: ${{ secrets.TO_OWNER }}
|
||||
repo: "runner"
|
||||
ref-name: ${{ github.ref_name }}
|
||||
container-suffixes: " "
|
||||
doer: ${{ secrets.DOER }}
|
||||
token: ${{ secrets.TOKEN }}
|
||||
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
||||
verbose: ${{ secrets.VERBOSE }}
|
|
@ -1,7 +1,9 @@
|
|||
name: checks
|
||||
on:
|
||||
- pull_request
|
||||
- push
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
FORGEJO_HOST_PORT: 'forgejo:3000'
|
||||
|
@ -13,14 +15,14 @@ env:
|
|||
GOPROXY: https://goproxy.io,direct
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: check and test
|
||||
build-and-tests:
|
||||
name: build and test
|
||||
if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-experimental' && github.repository_owner != 'forgejo-release'
|
||||
runs-on: docker
|
||||
|
||||
services:
|
||||
forgejo:
|
||||
image: codeberg.org/forgejo-integration/forgejo:1.20.0-4-rc2
|
||||
image: codeberg.org/forgejo/forgejo:1.21
|
||||
env:
|
||||
FORGEJO__security__INSTALL_LOCK: "true"
|
||||
FORGEJO__log__LEVEL: "debug"
|
||||
|
@ -38,17 +40,69 @@ jobs:
|
|||
with:
|
||||
go-version: '1.21'
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- run: make vet
|
||||
|
||||
- run: make build
|
||||
|
||||
- uses: https://code.forgejo.org/actions/upload-artifact@v3
|
||||
with:
|
||||
name: forgejo-runner
|
||||
path: forgejo-runner
|
||||
|
||||
- name: check the forgejo server is responding
|
||||
run: |
|
||||
set -x
|
||||
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)
|
||||
|
||||
- run: make FORGEJO_URL=http://$FORGEJO_HOST_PORT test
|
||||
|
||||
runner-exec-tests:
|
||||
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
|
||||
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: https://code.forgejo.org/actions/download-artifact@v3
|
||||
with:
|
||||
name: forgejo-runner
|
||||
|
||||
- name: install docker
|
||||
run: |
|
||||
mkdir /etc/docker
|
||||
cat > /etc/docker/daemon.json <<EOF
|
||||
{
|
||||
"ipv6": true,
|
||||
"experimental": true,
|
||||
"ip6tables": true,
|
||||
"fixed-cidr-v6": "fd05:d0ca:1::/64",
|
||||
"default-address-pools": [
|
||||
{
|
||||
"base": "172.19.0.0/16",
|
||||
"size": 24
|
||||
},
|
||||
{
|
||||
"base": "fd05:d0ca:2::/104",
|
||||
"size": 112
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
apt --quiet install --yes -qq docker.io
|
||||
|
||||
- name: forgejo-runner exec --enable-ipv6
|
||||
run: |
|
||||
set -x
|
||||
chmod +x forgejo-runner
|
||||
./forgejo-runner exec --enable-ipv6 --workflows .forgejo/testdata/ipv6.yml
|
||||
if ./forgejo-runner exec --workflows .forgejo/testdata/ipv6.yml >& /tmp/out ; then
|
||||
cat /tmp/out
|
||||
echo "IPv6 not enabled, should fail"
|
||||
exit 1
|
||||
fi
|
||||
|
|
45
Dockerfile
45
Dockerfile
|
@ -1,16 +1,47 @@
|
|||
FROM golang:1.21-alpine3.18 as builder
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/tonistiigi/xx AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.21-alpine3.19 as build-env
|
||||
|
||||
#
|
||||
# Transparently cross compile for the target platform
|
||||
#
|
||||
COPY --from=xx / /
|
||||
ARG TARGETPLATFORM
|
||||
RUN apk --no-cache add clang lld
|
||||
RUN xx-apk --no-cache add gcc musl-dev
|
||||
RUN xx-go --wrap
|
||||
|
||||
# Do not remove `git` here, it is required for getting runner version when executing `make build`
|
||||
RUN apk add --no-cache make git
|
||||
RUN apk add --no-cache build-base git
|
||||
|
||||
COPY . /srv
|
||||
WORKDIR /srv
|
||||
|
||||
RUN make clean && make build
|
||||
|
||||
FROM alpine:3.18
|
||||
RUN apk add --no-cache git bash tini
|
||||
FROM code.forgejo.org/oci/alpine:3.19
|
||||
ARG RELEASE_VERSION
|
||||
RUN apk add --no-cache git bash
|
||||
|
||||
COPY --from=builder /srv/forgejo-runner /bin/forgejo-runner
|
||||
COPY scripts/run.sh /opt/act/run.sh
|
||||
COPY --from=build-env /srv/forgejo-runner /bin/forgejo-runner
|
||||
|
||||
ENTRYPOINT ["/sbin/tini","--","/opt/act/run.sh"]
|
||||
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
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
VOLUME ["/data"]
|
||||
|
||||
CMD ["/bin/forgejo-runner"]
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
FROM golang:1.21-alpine3.18 as builder
|
||||
# Do not remove `git` here, it is required for getting runner version when executing `make build`
|
||||
RUN apk add --no-cache make git
|
||||
|
||||
COPY . /opt/src/forgejo-runner
|
||||
WORKDIR /opt/src/forgejo-runner
|
||||
|
||||
RUN make clean && make build
|
||||
|
||||
FROM docker:dind-rootless
|
||||
USER root
|
||||
RUN apk add --no-cache \
|
||||
git bash supervisor
|
||||
|
||||
COPY --from=builder /opt/src/forgejo-runner/forgejo-runner /usr/local/bin/forgejo-runner
|
||||
COPY /scripts/supervisord.conf /etc/supervisord.conf
|
||||
COPY /scripts/run.sh /opt/act/run.sh
|
||||
COPY /scripts/rootless.sh /opt/act/rootless.sh
|
||||
|
||||
RUN mkdir /data \
|
||||
&& chown rootless:rootless /data
|
||||
|
||||
USER rootless
|
||||
ENTRYPOINT ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
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
|
||||
|
|
56
README.md
56
README.md
|
@ -2,52 +2,15 @@
|
|||
|
||||
**WARNING:** this is [alpha release quality](https://en.wikipedia.org/wiki/Software_release_life_cycle#Alpha) code and should not be considered secure enough to deploy in production.
|
||||
|
||||
A daemon that connects to a Forgejo instance and runs jobs for continous integration. The high level [installation instructions](https://forgejo.org/docs/next/admin/actions/) are part of the Forgejo documentation.
|
||||
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.
|
||||
|
||||
# Configuration
|
||||
# Reporting bugs
|
||||
|
||||
Display the usage with `forgejo-runner --help`.
|
||||
|
||||
For more information on the configuration file, see the [commented example](internal/pkg/config/config.example.yaml).
|
||||
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). Together they provide a development environment with end to end testing. Each repository also has some unit testing that can be used to quickly detect the simplest mistakes such as a failure to compile or static code checking failures (vulnerability, lint, etc.).
|
||||
|
||||
Assuming the modifications to the [Forgejo runner](https://code.forgejo.org/forgejo/runner) are pushed to a fork in a branch named `wip-runner-change`, a pull request will verify it compiles and the binary is sane (running `forgejo-runner --version`). It will not verify that it is able to properly run jobs when connected to a live Forgejo instance.
|
||||
|
||||
For end to end testing, a branch should be pushed to a fork of the [setup-forgejo action](https://code.forgejo.org/actions/setup-forgejo) with a [modification to the tests](https://code.forgejo.org/actions/setup-forgejo/src/commit/ae7f03683b7b05c7d9c6aaeacaf27843de0366a4/.forgejo/workflows/integration.yml#L10-L19), similar to:
|
||||
|
||||
```yaml
|
||||
#
|
||||
# Uncomment the following for a shortcut to debugging the Forgejo runner.
|
||||
# It will build the runner from a designated repository and branch instead of
|
||||
# downloading it from a canonical release.
|
||||
#
|
||||
./forgejo-test-helper.sh build_runner https://code.forgejo.org/earl-warren/runner wip-runner-change
|
||||
```
|
||||
|
||||
Where https://code.forgejo.org/earl-warren/runner is the URL of the Forgejo runner fork and `wip-runner-change` is the branch where the changes under test were pushed. When they do the `wip-runner-change` branch can be discarded.
|
||||
|
||||
The runner can be released by merging the `wip-runner-change` branch and by pushing a new tag, for instance `v10.2.3`. For more information see the [documentation that details this release process](https://forgejo.org/docs/next/developer/RELEASE/#forgejo-runner-publication) in the Forgejo infrastructure. Once published, the [setup-forgejo](https://code.forgejo.org/actions/setup-forgejo/) action can be updated to default to this latest version knowing it already passed integration tests.
|
||||
|
||||
## ACT
|
||||
|
||||
Assuming the modifications to [ACT](https://code.forgejo.org/forgejo/act) are pushed to a fork in a branch named `wip-act-change`, a pull request will verify it compiles. It will not verify that the Forgejo runner can compile with it.
|
||||
|
||||
For verifying it is compatible with the Forgejo runner, a branch should be pushed to a fork of the [Forgejo runner](https://code.forgejo.org/forgejo/runner) (for instance `wip-runner-change`) that uses the ACT version under test in `wip-act-change` by modifying `go.mod` to contain something like the following and running `go mod tidy`:
|
||||
|
||||
```
|
||||
replace github.com/nektos/act => code.forgejo.org/earl-warren/act wip-act-change
|
||||
```
|
||||
|
||||
Where https://code.forgejo.org/earl-warren/act is the URL of the ACT fork and `wip-act-change` is the branch where the changes under test were pushed. It will not verify that it is able to properly run jobs when connected to a live Forgejo instance. The `wip-runner-change` branch must, in turn, be tested as explained above. When the Forgejo runner modified to include the changes in the `wip-act-change` branch pass the end to end test of the `setup-forgejo` action, it is ready to be released.
|
||||
|
||||
ACT can be released by merging the `wip-act-change` branch and by pushing a new tag, for instance `v48.8.20`. Once published, the Forgejo runner can be updated to default to this latest version knowing it already passed end to end tests with something like:
|
||||
|
||||
```
|
||||
replace github.com/nektos/act => code.forgejo.org/forgejo/act v48.8.20
|
||||
```
|
||||
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.
|
||||
|
||||
## Local debug
|
||||
|
||||
|
@ -90,8 +53,9 @@ cd runner ; rm -f forgejo-runner ; make forgejo-runner
|
|||
A Forgejo instance is launched with:
|
||||
|
||||
```shell
|
||||
cd setup-forgejo ; ./forgejo.sh setup
|
||||
firefox http://$(cat forgejo-ip):3000
|
||||
cd setup-forgejo
|
||||
./forgejo.sh setup
|
||||
firefox $(cat forgejo-url)
|
||||
```
|
||||
|
||||
The user is `root` with password `admin1234`. The runner is registered with:
|
||||
|
@ -99,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
|
||||
../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:
|
||||
|
@ -114,7 +78,9 @@ create a network that cannot reach the forgejo instance.
|
|||
|
||||
### Try a sample workflow
|
||||
|
||||
From the Forgejo web interface, create a repository and add the following to `.forgejo/workflows/try.yaml`. It will launch the job and the result can be observed from the `actions` tab.
|
||||
From the Forgejo web interface, create a repository and add the
|
||||
following to `.forgejo/workflows/try.yaml`. It will launch the job and
|
||||
the result can be observed from the `actions` tab.
|
||||
|
||||
```yaml
|
||||
on: [push]
|
||||
|
|
|
@ -1,9 +1,102 @@
|
|||
# Release Notes
|
||||
|
||||
## v2.4.0
|
||||
## 3.5.2
|
||||
|
||||
* 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
|
||||
docker:// with --enable-ipv6 and [container].enable_ipv6
|
||||
lxc:// always
|
||||
|
||||
## 3.2.0
|
||||
|
||||
* Support LXC container capabilities via `lxc:lxc://debian:bookworm:k8s` or `lxc:lxc://debian:bookworm:docker lxc k8s`
|
||||
* Update ACT v1.16.0 to resolve a [race condition when bootstraping LXC templates](https://code.forgejo.org/forgejo/act/pulls/23)
|
||||
|
||||
## 3.1.0
|
||||
|
||||
The `self-hosted` label that was hardwired to be a LXC container
|
||||
running `debian:bullseye` was reworked and documented ([user guide](https://forgejo.org/docs/next/user/actions/#jobsjob_idruns-on) and [admin guide](https://forgejo.org/docs/next/admin/actions/#labels-and-runs-on)).
|
||||
|
||||
There now are two different schemes: `lxc://` for LXC containers and
|
||||
`host://` for running directly on the host.
|
||||
|
||||
* Support the `host://` scheme for running directly on the host.
|
||||
* Support the `lxc://` scheme in labels
|
||||
* Update [code.forgejo.org/forgejo/act v1.14.0](https://code.forgejo.org/forgejo/act/pulls/19) to implement both self-hosted and LXC schemes
|
||||
|
||||
## 3.0.3
|
||||
|
||||
* Update [code.forgejo.org/forgejo/act v1.13.0](https://code.forgejo.org/forgejo/runner/pulls/106) to keep up with github.com/nektos/act
|
||||
|
||||
## 3.0.2
|
||||
|
||||
* Update [code.forgejo.org/forgejo/act v1.12.0](https://code.forgejo.org/forgejo/runner/pulls/106) to upgrade the node installed in the LXC container to node20
|
||||
|
||||
## 3.0.1
|
||||
|
||||
* Update [code.forgejo.org/forgejo/act v1.11.0](https://code.forgejo.org/forgejo/runner/pulls/86) to resolve a bug preventing actions based on node20 from running, such as [checkout@v4](https://code.forgejo.org/actions/checkout/src/tag/v4).
|
||||
|
||||
## 3.0.0
|
||||
|
||||
* Publish a rootless OCI image
|
||||
* Refactor the release process
|
||||
|
||||
## 2.5.0
|
||||
|
||||
* Update [code.forgejo.org/forgejo/act v1.10.0](https://code.forgejo.org/forgejo/runner/pulls/71)
|
||||
|
||||
## 2.4.0
|
||||
|
||||
* Update [code.forgejo.org/forgejo/act v1.9.0](https://code.forgejo.org/forgejo/runner/pulls/64)
|
||||
|
||||
## v2.3.0
|
||||
## 2.3.0
|
||||
|
||||
* Add support for [offline registration](https://forgejo.org/docs/next/admin/actions/#offline-registration).
|
||||
|
|
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
|
|
@ -1,12 +1,10 @@
|
|||
# Usage Examples for `act_runner`
|
||||
This directory contains a collection of usage and deployment examples.
|
||||
|
||||
Welcome to our collection of usage and deployment examples specifically designed for Gitea setups. Whether you're a beginner or an experienced user, you'll find practical resources here that you can directly apply to enhance your Gitea experience. We encourage you to contribute your own insights and knowledge to make this collection even more comprehensive and valuable.
|
||||
Workflow examples can be found [in the documentation](https://forgejo.org/docs/next/user/actions/)
|
||||
and in the [sources of the setup-forgejo](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata) action.
|
||||
|
||||
| Section | Description |
|
||||
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [`docker`](docker) | This section provides you with scripts and instructions tailored for running containers on a workstation or server where Docker is installed. It simplifies the process of setting up and managing your Gitea deployment using Docker. |
|
||||
| [`docker-compose`](docker-compose) | In this section, you'll discover examples demonstrating how to utilize docker-compose to efficiently handle your Gitea deployments. It offers a straightforward approach to managing multiple containerized components of your Gitea setup. |
|
||||
| [`kubernetes`](kubernetes) | If you're utilizing Kubernetes clusters for your infrastructure, this section is specifically designed for you. It presents examples and guidelines for configuring Gitea deployments within Kubernetes clusters, enabling you to leverage the scalability and flexibility of Kubernetes. |
|
||||
| [`vm`](vm) | This section is dedicated to examples that assist you in setting up Gitea on virtual or physical servers. Whether you're working with virtual machines or physical hardware, you'll find helpful resources to guide you through the deployment process. |
|
||||
|
||||
We hope these resources provide you with valuable insights and solutions for your Gitea setup. Feel free to explore, contribute, and adapt these examples to suit your specific requirements.
|
||||
| [`docker`](docker) | using the host docker server by mounting the socket |
|
||||
| [`docker-compose`](docker-compose) | all in one docker-compose with the Forgejo server, the runner and docker in docker |
|
||||
| [`kubernetes`](kubernetes) | a sample deployment for the Forgejo runner |
|
||||
|
|
|
@ -1,20 +1,113 @@
|
|||
### Running `act_runner` using `docker-compose`
|
||||
## Docker compose with docker-in-docker
|
||||
|
||||
```yml
|
||||
...
|
||||
gitea:
|
||||
image: gitea/gitea
|
||||
...
|
||||
The `compose-forgejo-and-runner.yml` compose file runs a Forgejo
|
||||
instance and registers a `Forgejo runner`. A docker server is also
|
||||
launched within a container (using
|
||||
[dind](https://hub.docker.com/_/docker/tags?name=dind)) and will be
|
||||
used by the `Forgejo runner` to execute the workflows.
|
||||
|
||||
runner:
|
||||
image: gitea/act_runner
|
||||
restart: always
|
||||
depends_on:
|
||||
- gitea
|
||||
volumes:
|
||||
- ./data/act_runner:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- GITEA_INSTANCE_URL=<instance url>
|
||||
- GITEA_RUNNER_REGISTRATION_TOKEN=<registration token>
|
||||
### Quick start
|
||||
|
||||
```sh
|
||||
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
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
openssl rand -hex 20
|
||||
```
|
||||
|
||||
Replace all occurences of {SHARED_SECRET} in
|
||||
[compose-forgejo-and-runner.yml](compose-forgejo-and-runner.yml).
|
||||
|
||||
> **NOTE:** a token obtained from the Forgejo web interface cannot be used as a shared secret.
|
||||
|
||||
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
|
||||
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: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)
|
||||
...
|
||||
runner-daemon_1 | time="2023-08-24T10:22:16Z" level=info msg="Starting runner daemon"
|
||||
```
|
||||
|
||||
### Manual testing
|
||||
|
||||
To login the Forgejo instance:
|
||||
|
||||
* URL: http://0.0.0.0:8080
|
||||
* 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 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 workflows:
|
||||
|
||||
#### `.forgejo/workflows/demo.yml`:
|
||||
|
||||
```yaml
|
||||
on: [push]
|
||||
jobs:
|
||||
test:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- 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.
|
||||
|
||||
### Running
|
||||
|
||||
```sh
|
||||
$ docker-compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml up demo-workflow
|
||||
...
|
||||
demo-workflow_1 | To http://forgejo:3000/root/test
|
||||
demo-workflow_1 | + 5ce134e...261cc79 main -> main (forced update)
|
||||
demo-workflow_1 | branch 'main' set up to track 'http://root:admin1234@forgejo:3000/root/test/main'.
|
||||
...
|
||||
demo-workflow_1 | running
|
||||
...
|
||||
```
|
||||
|
|
35
examples/docker-compose/compose-demo-workflow.yml
Normal file
35
examples/docker-compose/compose-demo-workflow.yml
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Copyright 2024 The Forgejo Authors.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
services:
|
||||
|
||||
demo-workflow:
|
||||
image: code.forgejo.org/oci/alpine:3.19
|
||||
links:
|
||||
- forgejo
|
||||
command: >-
|
||||
sh -ec '
|
||||
apk add --quiet git curl jq ;
|
||||
mkdir -p /srv/demo ;
|
||||
cd /srv/demo ;
|
||||
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 ;
|
||||
git commit -m demo ;
|
||||
while : ; do
|
||||
git push --set-upstream --force http://root:{ROOT_PASSWORD}@forgejo:3000/root/test main && break ;
|
||||
sleep 5 ;
|
||||
done ;
|
||||
sha=`git rev-parse HEAD` ;
|
||||
for delay in 1 1 1 1 2 5 5 10 10 10 15 30 30 30 30 30 30 30 ; do
|
||||
curl -sS -f http://forgejo:3000/api/v1/repos/root/test/commits/$$sha/status | jq --raw-output .state | tee status ;
|
||||
if grep success status ; then echo DEMO WORKFLOW SUCCESS && break ; fi ;
|
||||
if grep failure status ; then echo DEMO WORKFLOW FAILURE && break ; fi ;
|
||||
sleep $$delay ;
|
||||
done ;
|
||||
grep success status || echo DEMO WORKFLOW FAILURE
|
||||
'
|
93
examples/docker-compose/compose-forgejo-and-runner.yml
Normal file
93
examples/docker-compose/compose-forgejo-and-runner.yml
Normal file
|
@ -0,0 +1,93 @@
|
|||
# Copyright 2024 The Forgejo Authors.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
#
|
||||
# Create a secret with:
|
||||
#
|
||||
# openssl rand -hex 20
|
||||
#
|
||||
# Replace all occurences of {SHARED_SECRET} below with the output.
|
||||
#
|
||||
# NOTE: a token obtained from the Forgejo web interface cannot be used
|
||||
# as a shared secret.
|
||||
#
|
||||
# Replace {ROOT_PASSWORD} with a secure password
|
||||
#
|
||||
|
||||
volumes:
|
||||
docker_certs:
|
||||
|
||||
services:
|
||||
|
||||
docker-in-docker:
|
||||
image: code.forgejo.org/oci/docker:dind
|
||||
hostname: docker # Must set hostname as TLS certificates are only valid for docker or localhost
|
||||
privileged: true
|
||||
environment:
|
||||
DOCKER_TLS_CERTDIR: /certs
|
||||
DOCKER_HOST: docker-in-docker
|
||||
volumes:
|
||||
- docker_certs:/certs
|
||||
|
||||
forgejo:
|
||||
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}" 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__repository__ENABLE_PUSH_CREATE_USER: "true"
|
||||
FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE: "false"
|
||||
FORGEJO__repository__DEFAULT_REPO_UNITS: "repo.code,repo.actions"
|
||||
volumes:
|
||||
- /srv/forgejo-data:/data
|
||||
ports:
|
||||
- 8080:3000
|
||||
|
||||
runner-register:
|
||||
image: code.forgejo.org/forgejo/runner:3.4.1
|
||||
links:
|
||||
- docker-in-docker
|
||||
- forgejo
|
||||
environment:
|
||||
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 --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|^ 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.4.1
|
||||
links:
|
||||
- docker-in-docker
|
||||
- forgejo
|
||||
environment:
|
||||
DOCKER_HOST: tcp://docker:2376
|
||||
DOCKER_CERT_PATH: /certs/client
|
||||
DOCKER_TLS_VERIFY: "1"
|
||||
volumes:
|
||||
- /srv/runner-data:/data
|
||||
- docker_certs:/certs
|
||||
command: >-
|
||||
bash -c '
|
||||
while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done
|
||||
'
|
|
@ -1,8 +1,12 @@
|
|||
### Run `act_runner` in a Docker Container
|
||||
The following assumes:
|
||||
|
||||
* a docker server runs on the host
|
||||
* the docker group of the host is GID 133
|
||||
* a `.runner` file exists in /tmp/data
|
||||
* a `runner-config.yml` file exists in /tmp/data
|
||||
|
||||
```sh
|
||||
docker run -e GITEA_INSTANCE_URL=http://192.168.8.18:3000 -e GITEA_RUNNER_REGISTRATION_TOKEN=<runner_token> -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/data:/data --name my_runner gitea/act_runner:nightly
|
||||
docker run -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/data:/data --user 1000:133 --rm code.forgejo.org/forgejo/runner:3.0.0 forgejo-runner --config runner-config.yaml daemon
|
||||
```
|
||||
|
||||
The `/data` directory inside the docker container contains the runner API keys after registration.
|
||||
It must be persisted, otherwise the runner would try to register again, using the same, now defunct registration token.
|
||||
The workflows will run using the host docker srever
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
## Kubernetes Docker in Docker Deployment with `act_runner`
|
||||
## Kubernetes Docker in Docker Deployment
|
||||
|
||||
Registers Kubernetes pod runners using [offline registration](https://forgejo.org/docs/v1.21/admin/actions/#offline-registration), allowing the scaling of runners as needed.
|
||||
|
||||
NOTE: Docker in Docker (dind) requires elevated privileges on Kubernetes. The current way to achieve this is to set the pod `SecurityContext` to `privileged`. Keep in mind that this is a potential security issue that has the potential for a malicious application to break out of the container context.
|
||||
|
||||
Files in this directory:
|
||||
|
||||
- [`dind-docker.yaml`](dind-docker.yaml)
|
||||
How to create a Deployment and Secret for Kubernetes to act as a runner. The Docker credentials are re-generated each time the pod connects and does not need to be persisted.
|
||||
|
||||
- [`rootless-docker.yaml`](rootless-docker.yaml)
|
||||
How to create a rootless Deployment and Secret for Kubernetes to act as a runner. The Docker credentials are re-generated each time the pod connects and does not need to be persisted.
|
||||
[`dind-docker.yaml`](dind-docker.yaml) creates a deployment and secret for Kubernetes to act as a runner. The Docker credentials are re-generated each time the pod connects and does not need to be persisted.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Secret data.
|
||||
# You will need to retrive this from the web UI, and your Forgejo instance must be running v1.21+
|
||||
# Alternatively, create this with
|
||||
# kubectl create secret generic runner-secret --from-literal=token=your_offline_token_here
|
||||
apiVersion: v1
|
||||
|
@ -12,20 +13,20 @@ apiVersion: apps/v1
|
|||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: act-runner
|
||||
name: act-runner
|
||||
app: forgejo-runner
|
||||
name: forgejo-runner
|
||||
spec:
|
||||
# Two replicas means that if one is busy, the other can pick up jobs.
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: act-runner
|
||||
app: forgejo-runner
|
||||
strategy: {}
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: act-runner
|
||||
app: forgejo-runner
|
||||
spec:
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
|
@ -36,24 +37,32 @@ spec:
|
|||
# Initialise our configuration file using offline registration
|
||||
# https://forgejo.org/docs/v1.21/admin/actions/#offline-registration
|
||||
initContainers:
|
||||
- name: runner-config-generation
|
||||
image: code.forgejo.org/forgejo/runner:2.4.0
|
||||
command: [ "sh", "-c", "cd /data && forgejo-runner create-runner-file --instance $GITEA_INSTANCE_URL --secret $RUNNER_SECRET --connect" ]
|
||||
env:
|
||||
- name: RUNNER_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: runner-secret
|
||||
key: token
|
||||
- name: GITEA_INSTANCE_URL
|
||||
value: http://gitea-http.gitea.svc.cluster.local:3000
|
||||
volumeMounts:
|
||||
- name: runner-data
|
||||
mountPath: /data
|
||||
- name: runner-register
|
||||
image: code.forgejo.org/forgejo/runner:3.2.0
|
||||
command: ["forgejo-runner", "register", "--no-interactive", "--token", $(RUNNER_SECRET), "--name", $(RUNNER_NAME), "--instance", $(FORGEJO_INSTANCE_URL)]
|
||||
env:
|
||||
- name: RUNNER_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: RUNNER_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: runner-secret
|
||||
key: token
|
||||
- name: FORGEJO_INSTANCE_URL
|
||||
value: http://forgejo-http.forgejo.svc.cluster.local:3000
|
||||
resources:
|
||||
limits:
|
||||
cpu: "0.50"
|
||||
memory: "64Mi"
|
||||
volumeMounts:
|
||||
- name: runner-data
|
||||
mountPath: /data
|
||||
containers:
|
||||
- name: runner
|
||||
image: gitea/act_runner:nightly
|
||||
command: ["sh", "-c", "while ! nc -z localhost 2376 </dev/null; do echo 'waiting for docker daemon...'; sleep 5; done; /sbin/tini -- /opt/act/run.sh"]
|
||||
image: code.forgejo.org/forgejo/runner:3.0.0
|
||||
command: ["sh", "-c", "while ! nc -z localhost 2376 </dev/null; do echo 'waiting for docker daemon...'; sleep 5; done; forgejo-runner daemon"]
|
||||
env:
|
||||
- name: DOCKER_HOST
|
||||
value: tcp://localhost:2376
|
||||
|
@ -61,8 +70,6 @@ spec:
|
|||
value: /certs/client
|
||||
- name: DOCKER_TLS_VERIFY
|
||||
value: "1"
|
||||
- name: GITEA_INSTANCE_URL
|
||||
value: http://gitea-http.gitea.svc.cluster.local:3000
|
||||
volumeMounts:
|
||||
- name: docker-certs
|
||||
mountPath: /certs
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
# Secret data.
|
||||
# Alternatively, create this with
|
||||
# kubectl create secret generic runner-secret --from-literal=token=your_offline_token_here
|
||||
apiVersion: v1
|
||||
stringData:
|
||||
token: your_offline_secret_here
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: runner-secret
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: act-runner
|
||||
name: act-runner
|
||||
spec:
|
||||
# Two replicas means that if one is busy, the other can pick up jobs.
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: act-runner
|
||||
strategy: {}
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: act-runner
|
||||
spec:
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: runner-data
|
||||
emptyDir: {}
|
||||
# Initialise our configuration file using offline registration
|
||||
# https://forgejo.org/docs/v1.21/admin/actions/#offline-registration
|
||||
initContainers:
|
||||
- name: runner-config-generation
|
||||
image: code.forgejo.org/forgejo/runner:2.4.0
|
||||
command: [ "sh", "-c", "cd /data && forgejo-runner create-runner-file --instance $GITEA_INSTANCE_URL --secret $RUNNER_SECRET --connect" ]
|
||||
env:
|
||||
- name: RUNNER_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: runner-secret
|
||||
key: token
|
||||
- name: GITEA_INSTANCE_URL
|
||||
value: http://gitea-http.gitea.svc.cluster.local:3000
|
||||
volumeMounts:
|
||||
- name: runner-data
|
||||
mountPath: /data
|
||||
containers:
|
||||
- name: runner
|
||||
image: gitea/act_runner:nightly-dind-rootless
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: DOCKER_HOST
|
||||
value: tcp://localhost:2376
|
||||
- name: DOCKER_CERT_PATH
|
||||
value: /certs/client
|
||||
- name: DOCKER_TLS_VERIFY
|
||||
value: "1"
|
||||
- name: GITEA_INSTANCE_URL
|
||||
value: http://gitea-http.gitea.svc.cluster.local:3000
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: runner-data
|
||||
mountPath: /data
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
## `act_runner` on Virtual or Physical Servers
|
||||
|
||||
Files in this directory:
|
||||
|
||||
- [`rootless-docker.md`](rootless-docker.md)
|
||||
How to set up a rootless docker implementation of the runner.
|
|
@ -1,87 +0,0 @@
|
|||
## Using Rootless Docker with`act_runner`
|
||||
|
||||
Here is a simple example of how to set up `act_runner` with rootless Docker. It has been created with Debian, but other Linux should work the same way.
|
||||
|
||||
Note: This procedure needs a real login shell -- using `sudo su` or other method of accessing the account will fail some of the steps below.
|
||||
|
||||
As `root`:
|
||||
|
||||
- Create a user to run both `docker` and `act_runner`. In this example, we use a non-privileged account called `rootless`.
|
||||
|
||||
```bash
|
||||
useradd -m rootless
|
||||
passwd rootless
|
||||
```
|
||||
|
||||
- Install [`docker-ce`](https://docs.docker.com/engine/install/)
|
||||
- (Recommended) Disable the system-wide Docker daemon
|
||||
|
||||
``systemctl disable --now docker.service docker.socket``
|
||||
|
||||
As the `rootless` user:
|
||||
|
||||
- Follow the instructions for [enabling rootless mode](https://docs.docker.com/engine/security/rootless/)
|
||||
- Add the following lines to the `/home/rootless/.bashrc`:
|
||||
|
||||
```bash
|
||||
export XDG_RUNTIME_DIR=/home/rootless/.docker/run
|
||||
export PATH=/home/rootless/bin:$PATH
|
||||
export DOCKER_HOST=unix:///run/user/1001/docker.sock
|
||||
```
|
||||
|
||||
- Reboot. Ensure that the Docker process is working.
|
||||
- Create a directory for saving `act_runner` data between restarts
|
||||
|
||||
`mkdir /home/rootless/act_runner`
|
||||
|
||||
- Register the runner from the data directory
|
||||
|
||||
```bash
|
||||
cd /home/rootless/act_runner
|
||||
act_runner register
|
||||
```
|
||||
|
||||
- Generate a `act_runner` configuration file in the data directory. Edit the file to adjust for the system.
|
||||
|
||||
```bash
|
||||
act_runner generate-config >/home/rootless/act_runner/config
|
||||
```
|
||||
|
||||
- Create a new user-level`systemd` unit file as `/home/rootless/.config/systemd/user/act_runner.service` with the following contents:
|
||||
|
||||
```bash
|
||||
Description=Gitea Actions runner
|
||||
Documentation=https://gitea.com/gitea/act_runner
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Environment=PATH=/home/rootless/bin:/sbin:/usr/sbin:/home/rootless/bin:/home/rootless/bin:/home/rootless/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
|
||||
Environment=DOCKER_HOST=unix:///run/user/1001/docker.sock
|
||||
ExecStart=/usr/bin/act_runner daemon -c /home/rootless/act_runner/config
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
WorkingDirectory=/home/rootless/act_runner
|
||||
TimeoutSec=0
|
||||
RestartSec=2
|
||||
Restart=always
|
||||
StartLimitBurst=3
|
||||
StartLimitInterval=60s
|
||||
LimitNOFILE=infinity
|
||||
LimitNPROC=infinity
|
||||
LimitCORE=infinity
|
||||
TasksMax=infinity
|
||||
Delegate=yes
|
||||
Type=notify
|
||||
NotifyAccess=all
|
||||
KillMode=mixed
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
- Reboot
|
||||
|
||||
After the system restarts, check that the`act_runner` is working and that the runner is connected to Gitea.
|
||||
|
||||
````bash
|
||||
systemctl --user status act_runner
|
||||
journalctl --user -xeu act_runner
|
99
go.mod
99
go.mod
|
@ -1,25 +1,27 @@
|
|||
module gitea.com/gitea/act_runner
|
||||
|
||||
go 1.21
|
||||
go 1.21.13
|
||||
|
||||
toolchain go1.23.1
|
||||
|
||||
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.5+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.6+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.11.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.9.0
|
||||
golang.org/x/term v0.24.0
|
||||
golang.org/x/time v0.6.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gotest.tools/v3 v3.5.0
|
||||
gotest.tools/v3 v3.5.1
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -27,26 +29,31 @@ require (
|
|||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
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-20230717121422-5aa5874ade95 // 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/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // 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/docker/cli v24.0.5+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
github.com/distribution/reference v0.5.0 // 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.4.1 // indirect
|
||||
github.com/go-git/go-git/v5 v5.8.1 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.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
|
||||
|
@ -54,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.1 // indirect
|
||||
github.com/moby/patternmatcher v0.5.0 // 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-rc4 // indirect
|
||||
github.com/opencontainers/runc v1.1.8 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // 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.25 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/robfig/cron v1.2.0 // 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.12.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.14.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.11.0 // indirect
|
||||
golang.org/x/tools v0.12.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.25.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.10.0
|
||||
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.21.3
|
||||
|
|
258
go.sum
258
go.sum
|
@ -1,13 +1,15 @@
|
|||
code.forgejo.org/forgejo/act v1.10.0 h1:vvF8V0t8CC95wttzRnCRHFS3tW+HVuzxCJXXolNDdBU=
|
||||
code.forgejo.org/forgejo/act v1.10.0/go.mod h1:tfannUyz3cgmq1P1o69KW1AMB1aSlNOMzlswHkRjzcQ=
|
||||
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.21.3 h1:EeJbrz0aar2QhIcBlOW5gjK1rjrQxcAvQSPpG/R1h5w=
|
||||
code.forgejo.org/forgejo/act v1.21.3/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,76 +17,87 @@ 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/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/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/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/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.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
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=
|
||||
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/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc=
|
||||
github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
|
||||
github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
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 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 v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg=
|
||||
github.com/docker/docker v25.0.6+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-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0=
|
||||
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
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.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
|
||||
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||
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.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A=
|
||||
github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo=
|
||||
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.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=
|
||||
|
@ -101,44 +114,42 @@ 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.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
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.1 h1:vvMG7EZYCiQZpTtXQkvyeyj7HzT1JHhDWj+/aiGIzLM=
|
||||
github.com/moby/buildkit v0.12.1/go.mod h1:adB4y0SxxX8trnrY+oEulb48ODLqPO6pKMF0ppGcCoI=
|
||||
github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo=
|
||||
github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc4/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/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/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=
|
||||
|
@ -147,41 +158,36 @@ 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.25 h1:0Is99a51w1iocdxKUzNYiBNwjoSlO2Klqzll98joVj4=
|
||||
github.com/rhysd/actionlint v1.6.25/go.mod h1:Q+MtZKm1MdmJ9woOSKxLscMW7kU44/PShvjNy5ZKHA8=
|
||||
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/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
||||
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
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=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.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=
|
||||
|
@ -198,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=
|
||||
|
@ -207,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.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
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=
|
||||
|
@ -225,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.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
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=
|
||||
|
@ -252,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.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.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.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
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=
|
||||
|
@ -268,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.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||
golang.org/x/text v0.12.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.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.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=
|
||||
|
@ -279,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.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
|
||||
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||
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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
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=
|
||||
|
@ -300,5 +328,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
|
||||
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
|
|
|
@ -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
|
||||
|
@ -101,14 +103,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 +120,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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ type executeArgs struct {
|
|||
image string
|
||||
cacheHandler *artifactcache.Handler
|
||||
network string
|
||||
enableIPv6 bool
|
||||
githubInstance string
|
||||
}
|
||||
|
||||
|
@ -402,12 +403,13 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command
|
|||
ArtifactServerPort: execArgs.artifactServerPort,
|
||||
ArtifactServerAddr: execArgs.artifactServerAddr,
|
||||
NoSkipCheckout: execArgs.noSkipCheckout,
|
||||
// PresetGitHubContext: preset,
|
||||
// EventJSON: string(eventJSON),
|
||||
ContainerNamePrefix: fmt.Sprintf("FORGEJO-ACTIONS-TASK-%s", eventName),
|
||||
ContainerMaxLifetime: maxLifetime,
|
||||
ContainerNetworkMode: container.NetworkMode(execArgs.network),
|
||||
DefaultActionInstance: execArgs.defaultActionsURL,
|
||||
// PresetGitHubContext: preset,
|
||||
// EventJSON: string(eventJSON),
|
||||
ContainerNamePrefix: fmt.Sprintf("FORGEJO-ACTIONS-TASK-%s", eventName),
|
||||
ContainerMaxLifetime: maxLifetime,
|
||||
ContainerNetworkMode: container.NetworkMode(execArgs.network),
|
||||
ContainerNetworkEnableIPv6: execArgs.enableIPv6,
|
||||
DefaultActionInstance: execArgs.defaultActionsURL,
|
||||
PlatformPicker: func(_ []string) string {
|
||||
return execArgs.image
|
||||
},
|
||||
|
@ -484,8 +486,9 @@ 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.")
|
||||
|
||||
return execCmd
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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 := ""
|
||||
|
@ -169,8 +174,12 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||
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 +191,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>"
|
||||
|
@ -189,28 +205,31 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||
BindWorkdir: false,
|
||||
ActionCacheDir: filepath.FromSlash(r.cfg.Host.WorkdirParent),
|
||||
|
||||
ReuseContainers: false,
|
||||
ForcePull: r.cfg.Container.ForcePull,
|
||||
ForceRebuild: false,
|
||||
LogOutput: true,
|
||||
JSONLogger: false,
|
||||
Env: r.envs,
|
||||
Secrets: task.Secrets,
|
||||
GitHubInstance: strings.TrimSuffix(r.client.Address(), "/"),
|
||||
AutoRemove: true,
|
||||
NoSkipCheckout: true,
|
||||
PresetGitHubContext: preset,
|
||||
EventJSON: string(eventJSON),
|
||||
ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id),
|
||||
ContainerMaxLifetime: maxLifetime,
|
||||
ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network),
|
||||
ContainerOptions: r.cfg.Container.Options,
|
||||
ContainerDaemonSocket: r.cfg.Container.DockerHost,
|
||||
Privileged: r.cfg.Container.Privileged,
|
||||
DefaultActionInstance: taskContext["gitea_default_actions_url"].GetStringValue(),
|
||||
PlatformPicker: r.labels.PickPlatform,
|
||||
Vars: task.Vars,
|
||||
ValidVolumes: r.cfg.Container.ValidVolumes,
|
||||
ReuseContainers: false,
|
||||
ForcePull: r.cfg.Container.ForcePull,
|
||||
ForceRebuild: false,
|
||||
LogOutput: true,
|
||||
JSONLogger: false,
|
||||
Env: r.envs,
|
||||
Secrets: task.Secrets,
|
||||
GitHubInstance: strings.TrimSuffix(r.client.Address(), "/"),
|
||||
AutoRemove: true,
|
||||
NoSkipCheckout: true,
|
||||
PresetGitHubContext: preset,
|
||||
EventJSON: string(eventJSON),
|
||||
ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id),
|
||||
ContainerMaxLifetime: maxLifetime,
|
||||
ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network),
|
||||
ContainerNetworkEnableIPv6: r.cfg.Container.EnableIPv6,
|
||||
ContainerOptions: r.cfg.Container.Options,
|
||||
ContainerDaemonSocket: r.cfg.Container.DockerHost,
|
||||
Privileged: r.cfg.Container.Privileged,
|
||||
DefaultActionInstance: taskContext["gitea_default_actions_url"].GetStringValue(),
|
||||
PlatformPicker: r.labels.PickPlatform,
|
||||
Vars: task.Vars,
|
||||
ValidVolumes: r.cfg.Container.ValidVolumes,
|
||||
InsecureSkipTLS: r.cfg.Runner.Insecure,
|
||||
Inputs: inputs,
|
||||
}
|
||||
|
||||
rr, err := runner.New(runnerConfig)
|
||||
|
@ -235,3 +254,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"
|
||||
|
||||
|
|
|
@ -23,14 +23,22 @@ 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.
|
||||
labels: []
|
||||
|
@ -58,6 +66,9 @@ container:
|
|||
# Could be host, bridge or the name of a custom network.
|
||||
# If it's empty, create a network automatically.
|
||||
network: ""
|
||||
# Whether to create networks with IPv6 enabled. Requires the Docker daemon to be set up accordingly.
|
||||
# Only takes effect if "network" is set to "".
|
||||
enable_ipv6: false
|
||||
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
|
||||
privileged: false
|
||||
# And other options to be used when the container is started (eg, --add-host=my.forgejo.url:host-gateway).
|
||||
|
|
|
@ -21,15 +21,17 @@ type Log struct {
|
|||
|
||||
// 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.
|
||||
|
@ -45,6 +47,7 @@ type Cache struct {
|
|||
type Container struct {
|
||||
Network string `yaml:"network"` // Network specifies the network for the container.
|
||||
NetworkMode string `yaml:"network_mode"` // Deprecated: use Network instead. Could be removed after Gitea 1.20
|
||||
EnableIPv6 bool `yaml:"enable_ipv6"` // EnableIPv6 indicates whether the network is created with IPv6 enabled.
|
||||
Privileged bool `yaml:"privileged"` // Privileged indicates whether the container runs in privileged mode.
|
||||
Options string `yaml:"options"` // Options specifies additional options for the container.
|
||||
WorkdirParent string `yaml:"workdir_parent"` // WorkdirParent specifies the parent directory for the container's working directory.
|
||||
|
@ -67,6 +70,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) {
|
||||
|
@ -88,6 +101,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
|
||||
}
|
||||
|
@ -129,6 +145,9 @@ 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
|
||||
}
|
||||
|
||||
// although `container.network_mode` will be deprecated, but we have to be compatible with it for now.
|
||||
if cfg.Container.NetworkMode != "" && cfg.Container.Network == "" {
|
||||
|
|
37
internal/pkg/config/config_test.go
Normal file
37
internal/pkg/config/config_test.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
// 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)
|
||||
})
|
||||
}
|
|
@ -27,7 +27,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
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
const (
|
||||
SchemeHost = "host"
|
||||
SchemeDocker = "docker"
|
||||
SchemeLXC = "lxc"
|
||||
)
|
||||
|
||||
type Label struct {
|
||||
|
@ -32,7 +33,7 @@ func Parse(str string) (*Label, error) {
|
|||
if len(splits) >= 3 {
|
||||
label.Arg = splits[2]
|
||||
}
|
||||
if label.Schema != SchemeHost && label.Schema != SchemeDocker {
|
||||
if label.Schema != SchemeHost && label.Schema != SchemeDocker && label.Schema != SchemeLXC {
|
||||
return nil, fmt.Errorf("unsupported schema: %s", label.Schema)
|
||||
}
|
||||
return label, nil
|
||||
|
@ -55,10 +56,11 @@ 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"
|
||||
case SchemeLXC:
|
||||
platforms[label.Name] = "lxc:" + strings.TrimPrefix(label.Arg, "//")
|
||||
default:
|
||||
// It should not happen, because Parse has checked it.
|
||||
continue
|
||||
|
@ -80,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(""))
|
||||
}()
|
||||
|
|
11
renovate.json
Normal file
11
renovate.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["local>forgejo/renovate-config"],
|
||||
"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