mirror of
https://gitea.com/gitea/act_runner.git
synced 2025-06-08 15:50:41 +02:00
Compare commits
No commits in common. "main" and "v0.2.11" have entirely different histories.
@ -66,7 +66,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
target: basic
|
|
||||||
platforms: |
|
platforms: |
|
||||||
linux/amd64
|
linux/amd64
|
||||||
linux/arm64
|
linux/arm64
|
||||||
@ -74,25 +73,13 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}
|
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}
|
||||||
|
|
||||||
- name: Build and push dind
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
target: dind
|
|
||||||
platforms: |
|
|
||||||
linux/amd64
|
|
||||||
linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}-dind
|
|
||||||
|
|
||||||
- name: Build and push dind-rootless
|
- name: Build and push dind-rootless
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
|
env:
|
||||||
|
ACTIONS_RUNTIME_TOKEN: "" # See https://gitea.com/gitea/act_runner/issues/119
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile.rootless
|
||||||
target: dind-rootless
|
|
||||||
platforms: |
|
platforms: |
|
||||||
linux/amd64
|
linux/amd64
|
||||||
linux/arm64
|
linux/arm64
|
||||||
|
@ -73,7 +73,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
target: basic
|
|
||||||
platforms: |
|
platforms: |
|
||||||
linux/amd64
|
linux/amd64
|
||||||
linux/arm64
|
linux/arm64
|
||||||
@ -82,26 +81,13 @@ jobs:
|
|||||||
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}
|
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}
|
||||||
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}
|
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}
|
||||||
|
|
||||||
- name: Build and push dind
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
target: dind
|
|
||||||
platforms: |
|
|
||||||
linux/amd64
|
|
||||||
linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}-dind
|
|
||||||
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}-dind
|
|
||||||
|
|
||||||
- name: Build and push dind-rootless
|
- name: Build and push dind-rootless
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
|
env:
|
||||||
|
ACTIONS_RUNTIME_TOKEN: "" # See https://gitea.com/gitea/act_runner/issues/119
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile.rootless
|
||||||
target: dind-rootless
|
|
||||||
platforms: |
|
platforms: |
|
||||||
linux/amd64
|
linux/amd64
|
||||||
linux/arm64
|
linux/arm64
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
/act_runner
|
act_runner
|
||||||
.env
|
.env
|
||||||
.runner
|
.runner
|
||||||
coverage.txt
|
coverage.txt
|
||||||
|
@ -16,8 +16,6 @@ builds:
|
|||||||
- amd64
|
- amd64
|
||||||
- arm
|
- arm
|
||||||
- arm64
|
- arm64
|
||||||
- s390x
|
|
||||||
- riscv64
|
|
||||||
goarm:
|
goarm:
|
||||||
- "5"
|
- "5"
|
||||||
- "6"
|
- "6"
|
||||||
|
48
Dockerfile
48
Dockerfile
@ -1,54 +1,16 @@
|
|||||||
FROM golang:1.24-alpine AS builder
|
FROM golang:1.23-alpine AS builder
|
||||||
|
|
||||||
# Do not remove `git` here, it is required for getting runner version when executing `make build`
|
# 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 make git
|
||||||
|
|
||||||
ARG GOPROXY
|
|
||||||
ENV GOPROXY=${GOPROXY:-}
|
|
||||||
|
|
||||||
COPY . /opt/src/act_runner
|
COPY . /opt/src/act_runner
|
||||||
WORKDIR /opt/src/act_runner
|
WORKDIR /opt/src/act_runner
|
||||||
|
|
||||||
RUN make clean && make build
|
RUN make clean && make build
|
||||||
|
|
||||||
FROM docker:dind AS dind
|
FROM alpine
|
||||||
|
RUN apk add --no-cache git bash tini
|
||||||
RUN apk add --no-cache s6 bash git
|
|
||||||
|
|
||||||
COPY --from=builder /opt/src/act_runner/act_runner /usr/local/bin/act_runner
|
COPY --from=builder /opt/src/act_runner/act_runner /usr/local/bin/act_runner
|
||||||
COPY scripts/run.sh /usr/local/bin/run.sh
|
COPY scripts/run.sh /opt/act/run.sh
|
||||||
COPY scripts/s6 /etc/s6
|
|
||||||
|
|
||||||
VOLUME /data
|
ENTRYPOINT ["/sbin/tini","--","/opt/act/run.sh"]
|
||||||
|
|
||||||
ENTRYPOINT ["s6-svscan","/etc/s6"]
|
|
||||||
|
|
||||||
FROM docker:dind-rootless AS dind-rootless
|
|
||||||
|
|
||||||
USER root
|
|
||||||
RUN apk add --no-cache s6 bash git
|
|
||||||
|
|
||||||
COPY --from=builder /opt/src/act_runner/act_runner /usr/local/bin/act_runner
|
|
||||||
COPY scripts/run.sh /usr/local/bin/run.sh
|
|
||||||
COPY scripts/s6 /etc/s6
|
|
||||||
|
|
||||||
VOLUME /data
|
|
||||||
|
|
||||||
RUN mkdir -p /data && chown -R rootless:rootless /etc/s6 /data
|
|
||||||
|
|
||||||
ENV DOCKER_HOST=unix:///run/user/1000/docker.sock
|
|
||||||
|
|
||||||
USER rootless
|
|
||||||
ENTRYPOINT ["s6-svscan","/etc/s6"]
|
|
||||||
|
|
||||||
FROM alpine AS basic
|
|
||||||
RUN apk add --no-cache tini bash git
|
|
||||||
|
|
||||||
COPY --from=builder /opt/src/act_runner/act_runner /usr/local/bin/act_runner
|
|
||||||
COPY scripts/run.sh /usr/local/bin/run.sh
|
|
||||||
|
|
||||||
VOLUME /var/run/docker.sock
|
|
||||||
|
|
||||||
VOLUME /data
|
|
||||||
|
|
||||||
ENTRYPOINT ["/sbin/tini","--","run.sh"]
|
|
||||||
|
24
Dockerfile.rootless
Normal file
24
Dockerfile.rootless
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
FROM golang:1.23-alpine AS builder
|
||||||
|
# Do not remove `git` here, it is required for getting runner version when executing `make build`
|
||||||
|
RUN apk add --no-cache make git
|
||||||
|
|
||||||
|
COPY . /opt/src/act_runner
|
||||||
|
WORKDIR /opt/src/act_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/act_runner/act_runner /usr/local/bin/act_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"]
|
3
Makefile
3
Makefile
@ -7,7 +7,7 @@ GO ?= go
|
|||||||
SHASUM ?= shasum -a 256
|
SHASUM ?= shasum -a 256
|
||||||
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
XGO_VERSION := go-1.24.x
|
XGO_VERSION := go-1.18.x
|
||||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
|
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
|
||||||
|
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/arm64
|
LINUX_ARCHS ?= linux/amd64,linux/arm64
|
||||||
@ -170,6 +170,7 @@ docker:
|
|||||||
ARG_DISABLE_CONTENT_TRUST=--disable-content-trust=false; \
|
ARG_DISABLE_CONTENT_TRUST=--disable-content-trust=false; \
|
||||||
fi; \
|
fi; \
|
||||||
docker build $${ARG_DISABLE_CONTENT_TRUST} -t $(DOCKER_REF) .
|
docker build $${ARG_DISABLE_CONTENT_TRUST} -t $(DOCKER_REF) .
|
||||||
|
docker build $${ARG_DISABLE_CONTENT_TRUST} -t $(DOCKER_ROOTLESS_REF) -f Dockerfile.rootless .
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(GO) clean -x -i ./...
|
$(GO) clean -x -i ./...
|
||||||
|
@ -58,9 +58,9 @@ INFO Enter the runner token:
|
|||||||
fe884e8027dc292970d4e0303fe82b14xxxxxxxx
|
fe884e8027dc292970d4e0303fe82b14xxxxxxxx
|
||||||
INFO Enter the runner name (if set empty, use hostname: Test.local):
|
INFO Enter the runner name (if set empty, use hostname: Test.local):
|
||||||
|
|
||||||
INFO Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest):
|
INFO Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-latest:docker://gitea/runner-images:ubuntu-latest):
|
||||||
|
|
||||||
INFO Registering runner, name=Test.local, instance=http://192.168.8.8:3000/, labels=[ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04 ubuntu-20.04:docker://docker.gitea.com/runner-images:ubuntu-20.04].
|
INFO Registering runner, name=Test.local, instance=http://192.168.8.8:3000/, labels=[ubuntu-latest:docker://gitea/runner-images:ubuntu-latest ubuntu-22.04:docker://gitea/runner-images:ubuntu-22.04 ubuntu-20.04:docker://gitea/runner-images:ubuntu-20.04].
|
||||||
DEBU Successfully pinged the Gitea instance server
|
DEBU Successfully pinged the Gitea instance server
|
||||||
INFO Runner registered successfully.
|
INFO Runner registered successfully.
|
||||||
```
|
```
|
||||||
|
@ -5,27 +5,12 @@
|
|||||||
gitea:
|
gitea:
|
||||||
image: gitea/gitea
|
image: gitea/gitea
|
||||||
...
|
...
|
||||||
healthcheck:
|
|
||||||
# checks availability of Gitea's front-end with curl
|
|
||||||
test: ["CMD", "curl", "-f", "<instance_url>"]
|
|
||||||
interval: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 30s
|
|
||||||
timeout: 10s
|
|
||||||
environment:
|
|
||||||
# GITEA_RUNNER_REGISTRATION_TOKEN can be used to set a global runner registration token.
|
|
||||||
# The Gitea version must be v1.23 or higher.
|
|
||||||
# It's also possible to use GITEA_RUNNER_REGISTRATION_TOKEN_FILE to pass the location.
|
|
||||||
# - GITEA_RUNNER_REGISTRATION_TOKEN=<user-defined registration token>
|
|
||||||
|
|
||||||
runner:
|
runner:
|
||||||
image: gitea/act_runner
|
image: gitea/act_runner
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
gitea:
|
- gitea
|
||||||
# required so runner can attach to gitea, see "healthcheck"
|
|
||||||
condition: service_healthy
|
|
||||||
restart: true
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/act_runner:/data
|
- ./data/act_runner:/data
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
@ -12,9 +12,6 @@ spec:
|
|||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
# The registration token can be obtained from the web UI, API or command-line.
|
|
||||||
# You can also set a pre-defined global runner registration token for the Gitea instance via
|
|
||||||
# `GITEA_RUNNER_REGISTRATION_TOKEN`/`GITEA_RUNNER_REGISTRATION_TOKEN_FILE` environment variable.
|
|
||||||
token: << base64 encoded registration token >>
|
token: << base64 encoded registration token >>
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
@ -49,7 +46,7 @@ spec:
|
|||||||
containers:
|
containers:
|
||||||
- name: runner
|
- name: runner
|
||||||
image: gitea/act_runner:nightly
|
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 -- run.sh"]
|
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"]
|
||||||
env:
|
env:
|
||||||
- name: DOCKER_HOST
|
- name: DOCKER_HOST
|
||||||
value: tcp://localhost:2376
|
value: tcp://localhost:2376
|
||||||
|
@ -12,10 +12,7 @@ spec:
|
|||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
# The registration token can be obtained from the web UI, API or command-line.
|
token: << runner registration token goes here >>
|
||||||
# You can also set a pre-defined global runner registration token for the Gitea instance via
|
|
||||||
# `GITEA_RUNNER_REGISTRATION_TOKEN`/`GITEA_RUNNER_REGISTRATION_TOKEN_FILE` environment variable.
|
|
||||||
token: << base64 encoded registration token >>
|
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
name: runner-secret
|
name: runner-secret
|
||||||
|
@ -11,8 +11,7 @@ As `root`:
|
|||||||
```bash
|
```bash
|
||||||
useradd -m rootless
|
useradd -m rootless
|
||||||
passwd rootless
|
passwd rootless
|
||||||
apt-get install -y uidmap # Not mentioned but needed for docker rootless.
|
```
|
||||||
```
|
|
||||||
|
|
||||||
- Install [`docker-ce`](https://docs.docker.com/engine/install/)
|
- Install [`docker-ce`](https://docs.docker.com/engine/install/)
|
||||||
- (Recommended) Disable the system-wide Docker daemon
|
- (Recommended) Disable the system-wide Docker daemon
|
||||||
@ -22,19 +21,12 @@ As `root`:
|
|||||||
As the `rootless` user:
|
As the `rootless` user:
|
||||||
|
|
||||||
- Follow the instructions for [enabling rootless mode](https://docs.docker.com/engine/security/rootless/)
|
- Follow the instructions for [enabling rootless mode](https://docs.docker.com/engine/security/rootless/)
|
||||||
- Add the following line to the `/home/rootless/.bashrc`:
|
- Add the following lines to the `/home/rootless/.bashrc`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
for f in ./.bashrc.d/*.bash; do echo "Processing $f file..."; . "$f"; done
|
export XDG_RUNTIME_DIR=/home/rootless/.docker/run
|
||||||
```
|
export PATH=/home/rootless/bin:$PATH
|
||||||
|
export DOCKER_HOST=unix:///run/user/1001/docker.sock
|
||||||
- Create the .bashrc.d directory `mkdir ~/.bashrc.d`
|
|
||||||
- Add the following lines to the `/home/rootless/.bashrc.d/rootless-docker.bash`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export XDG_RUNTIME_DIR=/home/rootless/.docker/run
|
|
||||||
export PATH=/home/rootless/bin:$PATH
|
|
||||||
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- Reboot. Ensure that the Docker process is working.
|
- Reboot. Ensure that the Docker process is working.
|
||||||
|
6
go.mod
6
go.mod
@ -1,9 +1,9 @@
|
|||||||
module gitea.com/gitea/act_runner
|
module gitea.com/gitea/act_runner
|
||||||
|
|
||||||
go 1.24
|
go 1.23
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/actions-proto-go v0.4.1
|
code.gitea.io/actions-proto-go v0.4.0
|
||||||
code.gitea.io/gitea-vet v0.2.3
|
code.gitea.io/gitea-vet v0.2.3
|
||||||
connectrpc.com/connect v1.16.2
|
connectrpc.com/connect v1.16.2
|
||||||
github.com/avast/retry-go/v4 v4.6.0
|
github.com/avast/retry-go/v4 v4.6.0
|
||||||
@ -98,4 +98,4 @@ require (
|
|||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/nektos/act => gitea.com/gitea/act v0.261.4
|
replace github.com/nektos/act => gitea.com/gitea/act v0.261.2
|
||||||
|
8
go.sum
8
go.sum
@ -1,13 +1,13 @@
|
|||||||
code.gitea.io/actions-proto-go v0.4.1 h1:l0EYhjsgpUe/1VABo2eK7zcoNX2W44WOnb0MSLrKfls=
|
code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
|
||||||
code.gitea.io/actions-proto-go v0.4.1/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
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 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
|
||||||
code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
||||||
connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE=
|
connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE=
|
||||||
connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc=
|
connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc=
|
||||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
gitea.com/gitea/act v0.261.4 h1:Tf9eLlvsYFtKcpuxlMvf9yT3g4Hshb2Beqw6C1STuH8=
|
gitea.com/gitea/act v0.261.2 h1:yAhxlt11gpRmF7CeVsVjgLg1Ph0xxroJ/l2fWaYyl84=
|
||||||
gitea.com/gitea/act v0.261.4/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
|
gitea.com/gitea/act v0.261.2/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
|
||||||
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 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
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 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||||
|
@ -39,18 +39,15 @@ func Execute(ctx context.Context) {
|
|||||||
registerCmd.Flags().StringVar(®Args.Token, "token", "", "Runner token")
|
registerCmd.Flags().StringVar(®Args.Token, "token", "", "Runner token")
|
||||||
registerCmd.Flags().StringVar(®Args.RunnerName, "name", "", "Runner name")
|
registerCmd.Flags().StringVar(®Args.RunnerName, "name", "", "Runner name")
|
||||||
registerCmd.Flags().StringVar(®Args.Labels, "labels", "", "Runner tags, comma separated")
|
registerCmd.Flags().StringVar(®Args.Labels, "labels", "", "Runner tags, comma separated")
|
||||||
registerCmd.Flags().BoolVar(®Args.Ephemeral, "ephemeral", false, "Configure the runner to be ephemeral and only ever be able to pick a single job (stricter than --once)")
|
|
||||||
rootCmd.AddCommand(registerCmd)
|
rootCmd.AddCommand(registerCmd)
|
||||||
|
|
||||||
// ./act_runner daemon
|
// ./act_runner daemon
|
||||||
var daemArgs daemonArgs
|
|
||||||
daemonCmd := &cobra.Command{
|
daemonCmd := &cobra.Command{
|
||||||
Use: "daemon",
|
Use: "daemon",
|
||||||
Short: "Run as a runner daemon",
|
Short: "Run as a runner daemon",
|
||||||
Args: cobra.MaximumNArgs(0),
|
Args: cobra.MaximumNArgs(1),
|
||||||
RunE: runDaemon(ctx, &daemArgs, &configFile),
|
RunE: runDaemon(ctx, &configFile),
|
||||||
}
|
}
|
||||||
daemonCmd.Flags().BoolVar(&daemArgs.Once, "once", false, "Run one job then exit")
|
|
||||||
rootCmd.AddCommand(daemonCmd)
|
rootCmd.AddCommand(daemonCmd)
|
||||||
|
|
||||||
// ./act_runner exec
|
// ./act_runner exec
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
"gitea.com/gitea/act_runner/internal/pkg/ver"
|
"gitea.com/gitea/act_runner/internal/pkg/ver"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) func(cmd *cobra.Command, args []string) error {
|
func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, args []string) error {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
cfg, err := config.LoadDefault(*configFile)
|
cfg, err := config.LoadDefault(*configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -122,24 +122,9 @@ func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) fu
|
|||||||
|
|
||||||
poller := poll.New(cfg, cli, runner)
|
poller := poll.New(cfg, cli, runner)
|
||||||
|
|
||||||
if daemArgs.Once || reg.Ephemeral {
|
go poller.Poll()
|
||||||
done := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
defer close(done)
|
|
||||||
poller.PollOnce()
|
|
||||||
}()
|
|
||||||
|
|
||||||
// shutdown when we complete a job or cancel is requested
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
case <-done:
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
go poller.Poll()
|
|
||||||
|
|
||||||
<-ctx.Done()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
<-ctx.Done()
|
||||||
log.Infof("runner: %s shutdown initiated, waiting %s for running jobs to complete before shutting down", resp.Msg.Runner.Name, cfg.Runner.ShutdownTimeout)
|
log.Infof("runner: %s shutdown initiated, waiting %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)
|
ctx, cancel := context.WithTimeout(context.Background(), cfg.Runner.ShutdownTimeout)
|
||||||
@ -149,57 +134,45 @@ func runDaemon(ctx context.Context, daemArgs *daemonArgs, configFile *string) fu
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("runner: %s cancelled in progress jobs during shutdown", resp.Msg.Runner.Name)
|
log.Warnf("runner: %s cancelled in progress jobs during shutdown", resp.Msg.Runner.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type daemonArgs struct {
|
|
||||||
Once bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// initLogging setup the global logrus logger.
|
// initLogging setup the global logrus logger.
|
||||||
func initLogging(cfg *config.Config) {
|
func initLogging(cfg *config.Config) {
|
||||||
callPrettyfier := func(f *runtime.Frame) (string, string) {
|
|
||||||
// get function name
|
|
||||||
s := strings.Split(f.Function, ".")
|
|
||||||
funcname := "[" + s[len(s)-1] + "]"
|
|
||||||
// get file name and line number
|
|
||||||
_, filename := path.Split(f.File)
|
|
||||||
filename = "[" + filename + ":" + strconv.Itoa(f.Line) + "]"
|
|
||||||
return funcname, filename
|
|
||||||
}
|
|
||||||
|
|
||||||
isTerm := isatty.IsTerminal(os.Stdout.Fd())
|
isTerm := isatty.IsTerminal(os.Stdout.Fd())
|
||||||
format := &log.TextFormatter{
|
format := &log.TextFormatter{
|
||||||
DisableColors: !isTerm,
|
DisableColors: !isTerm,
|
||||||
FullTimestamp: true,
|
FullTimestamp: true,
|
||||||
CallerPrettyfier: callPrettyfier,
|
|
||||||
}
|
}
|
||||||
log.SetFormatter(format)
|
log.SetFormatter(format)
|
||||||
|
|
||||||
l := cfg.Log.Level
|
if l := cfg.Log.Level; l != "" {
|
||||||
if l == "" {
|
level, err := log.ParseLevel(l)
|
||||||
log.Infof("Log level not set, sticking to info")
|
if err != nil {
|
||||||
return
|
log.WithError(err).
|
||||||
}
|
Errorf("invalid log level: %q", l)
|
||||||
|
}
|
||||||
|
|
||||||
level, err := log.ParseLevel(l)
|
// debug level
|
||||||
if err != nil {
|
if level == log.DebugLevel {
|
||||||
log.WithError(err).
|
log.SetReportCaller(true)
|
||||||
Errorf("invalid log level: %q", l)
|
format.CallerPrettyfier = func(f *runtime.Frame) (string, string) {
|
||||||
}
|
// get function name
|
||||||
|
s := strings.Split(f.Function, ".")
|
||||||
|
funcname := "[" + s[len(s)-1] + "]"
|
||||||
|
// get file name and line number
|
||||||
|
_, filename := path.Split(f.File)
|
||||||
|
filename = "[" + filename + ":" + strconv.Itoa(f.Line) + "]"
|
||||||
|
return funcname, filename
|
||||||
|
}
|
||||||
|
log.SetFormatter(format)
|
||||||
|
}
|
||||||
|
|
||||||
// debug level
|
if log.GetLevel() != level {
|
||||||
switch level {
|
log.Infof("log level changed to %v", level)
|
||||||
case log.DebugLevel, log.TraceLevel:
|
log.SetLevel(level)
|
||||||
log.SetReportCaller(true) // Only in debug or trace because it takes a performance toll
|
}
|
||||||
log.Infof("Log level %s requested, setting up report caller for further debugging", level)
|
|
||||||
}
|
|
||||||
|
|
||||||
if log.GetLevel() != level {
|
|
||||||
log.Infof("log level set to %v", level)
|
|
||||||
log.SetLevel(level)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,7 +484,7 @@ func loadExecCmd(ctx context.Context) *cobra.Command {
|
|||||||
execCmd.PersistentFlags().BoolVarP(&execArg.noSkipCheckout, "no-skip-checkout", "", false, "Do not skip actions/checkout")
|
execCmd.PersistentFlags().BoolVarP(&execArg.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.debug, "debug", "d", false, "enable debug log")
|
||||||
execCmd.PersistentFlags().BoolVarP(&execArg.dryrun, "dryrun", "n", false, "dryrun mode")
|
execCmd.PersistentFlags().BoolVarP(&execArg.dryrun, "dryrun", "n", false, "dryrun mode")
|
||||||
execCmd.PersistentFlags().StringVarP(&execArg.image, "image", "i", "docker.gitea.com/runner-images:ubuntu-latest", "Docker image to use. Use \"-self-hosted\" to run directly on the host.")
|
execCmd.PersistentFlags().StringVarP(&execArg.image, "image", "i", "gitea/runner-images:ubuntu-latest", "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().StringVarP(&execArg.network, "network", "", "", "Specify the network to which the container will connect")
|
||||||
execCmd.PersistentFlags().StringVarP(&execArg.githubInstance, "gitea-instance", "", "", "Gitea instance to use.")
|
execCmd.PersistentFlags().StringVarP(&execArg.githubInstance, "gitea-instance", "", "", "Gitea instance to use.")
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ func runRegister(ctx context.Context, regArgs *registerArgs, configFile *string)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
go func() {
|
go func() {
|
||||||
if err := registerInteractive(ctx, *configFile, regArgs); err != nil {
|
if err := registerInteractive(ctx, *configFile); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -75,7 +75,6 @@ type registerArgs struct {
|
|||||||
Token string
|
Token string
|
||||||
RunnerName string
|
RunnerName string
|
||||||
Labels string
|
Labels string
|
||||||
Ephemeral bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type registerStage int8
|
type registerStage int8
|
||||||
@ -92,9 +91,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var defaultLabels = []string{
|
var defaultLabels = []string{
|
||||||
"ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest",
|
"ubuntu-latest:docker://gitea/runner-images:ubuntu-latest",
|
||||||
"ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04",
|
"ubuntu-22.04:docker://gitea/runner-images:ubuntu-22.04",
|
||||||
"ubuntu-20.04:docker://docker.gitea.com/runner-images:ubuntu-20.04",
|
"ubuntu-20.04:docker://gitea/runner-images:ubuntu-20.04",
|
||||||
}
|
}
|
||||||
|
|
||||||
type registerInputs struct {
|
type registerInputs struct {
|
||||||
@ -102,7 +101,6 @@ type registerInputs struct {
|
|||||||
Token string
|
Token string
|
||||||
RunnerName string
|
RunnerName string
|
||||||
Labels []string
|
Labels []string
|
||||||
Ephemeral bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *registerInputs) validate() error {
|
func (r *registerInputs) validate() error {
|
||||||
@ -127,22 +125,6 @@ func validateLabels(ls []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *registerInputs) stageValue(stage registerStage) string {
|
|
||||||
switch stage {
|
|
||||||
case StageInputInstance:
|
|
||||||
return r.InstanceAddr
|
|
||||||
case StageInputToken:
|
|
||||||
return r.Token
|
|
||||||
case StageInputRunnerName:
|
|
||||||
return r.RunnerName
|
|
||||||
case StageInputLabels:
|
|
||||||
if len(r.Labels) > 0 {
|
|
||||||
return strings.Join(r.Labels, ",")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *config.Config) registerStage {
|
func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *config.Config) registerStage {
|
||||||
// must set instance address and token.
|
// must set instance address and token.
|
||||||
// if empty, keep current stage.
|
// if empty, keep current stage.
|
||||||
@ -196,8 +178,7 @@ func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *co
|
|||||||
}
|
}
|
||||||
|
|
||||||
if validateLabels(r.Labels) != nil {
|
if validateLabels(r.Labels) != nil {
|
||||||
log.Infoln("Invalid labels, please input again, leave blank to use the default labels (for example, ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest)")
|
log.Infoln("Invalid labels, please input again, leave blank to use the default labels (for example, ubuntu-latest:docker://gitea/runner-images:ubuntu-latest)")
|
||||||
r.Labels = nil
|
|
||||||
return StageInputLabels
|
return StageInputLabels
|
||||||
}
|
}
|
||||||
return StageWaitingForRegistration
|
return StageWaitingForRegistration
|
||||||
@ -205,25 +186,11 @@ func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *co
|
|||||||
return StageUnknown
|
return StageUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
func initInputs(regArgs *registerArgs) *registerInputs {
|
func registerInteractive(ctx context.Context, configFile string) error {
|
||||||
inputs := ®isterInputs{
|
|
||||||
InstanceAddr: regArgs.InstanceAddr,
|
|
||||||
Token: regArgs.Token,
|
|
||||||
RunnerName: regArgs.RunnerName,
|
|
||||||
Ephemeral: regArgs.Ephemeral,
|
|
||||||
}
|
|
||||||
regArgs.Labels = strings.TrimSpace(regArgs.Labels)
|
|
||||||
// command line flag.
|
|
||||||
if regArgs.Labels != "" {
|
|
||||||
inputs.Labels = strings.Split(regArgs.Labels, ",")
|
|
||||||
}
|
|
||||||
return inputs
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerInteractive(ctx context.Context, configFile string, regArgs *registerArgs) error {
|
|
||||||
var (
|
var (
|
||||||
reader = bufio.NewReader(os.Stdin)
|
reader = bufio.NewReader(os.Stdin)
|
||||||
stage = StageInputInstance
|
stage = StageInputInstance
|
||||||
|
inputs = new(registerInputs)
|
||||||
)
|
)
|
||||||
|
|
||||||
cfg, err := config.LoadDefault(configFile)
|
cfg, err := config.LoadDefault(configFile)
|
||||||
@ -233,17 +200,13 @@ func registerInteractive(ctx context.Context, configFile string, regArgs *regist
|
|||||||
if f, err := os.Stat(cfg.Runner.File); err == nil && !f.IsDir() {
|
if f, err := os.Stat(cfg.Runner.File); err == nil && !f.IsDir() {
|
||||||
stage = StageOverwriteLocalConfig
|
stage = StageOverwriteLocalConfig
|
||||||
}
|
}
|
||||||
inputs := initInputs(regArgs)
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
cmdString := inputs.stageValue(stage)
|
printStageHelp(stage)
|
||||||
if cmdString == "" {
|
|
||||||
printStageHelp(stage)
|
cmdString, err := reader.ReadString('\n')
|
||||||
var err error
|
if err != nil {
|
||||||
cmdString, err = reader.ReadString('\n')
|
return err
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
stage = inputs.assignToNext(stage, strings.TrimSpace(cmdString), cfg)
|
stage = inputs.assignToNext(stage, strings.TrimSpace(cmdString), cfg)
|
||||||
|
|
||||||
@ -279,7 +242,7 @@ func printStageHelp(stage registerStage) {
|
|||||||
hostname, _ := os.Hostname()
|
hostname, _ := os.Hostname()
|
||||||
log.Infof("Enter the runner name (if set empty, use hostname: %s):\n", hostname)
|
log.Infof("Enter the runner name (if set empty, use hostname: %s):\n", hostname)
|
||||||
case StageInputLabels:
|
case StageInputLabels:
|
||||||
log.Infoln("Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest):")
|
log.Infoln("Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-latest:docker://gitea/runner-images:ubuntu-latest):")
|
||||||
case StageWaitingForRegistration:
|
case StageWaitingForRegistration:
|
||||||
log.Infoln("Waiting for registration...")
|
log.Infoln("Waiting for registration...")
|
||||||
}
|
}
|
||||||
@ -290,7 +253,17 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
inputs := initInputs(regArgs)
|
inputs := ®isterInputs{
|
||||||
|
InstanceAddr: regArgs.InstanceAddr,
|
||||||
|
Token: regArgs.Token,
|
||||||
|
RunnerName: regArgs.RunnerName,
|
||||||
|
Labels: defaultLabels,
|
||||||
|
}
|
||||||
|
regArgs.Labels = strings.TrimSpace(regArgs.Labels)
|
||||||
|
// command line flag.
|
||||||
|
if regArgs.Labels != "" {
|
||||||
|
inputs.Labels = strings.Split(regArgs.Labels, ",")
|
||||||
|
}
|
||||||
// specify labels in config file.
|
// specify labels in config file.
|
||||||
if len(cfg.Runner.Labels) > 0 {
|
if len(cfg.Runner.Labels) > 0 {
|
||||||
if regArgs.Labels != "" {
|
if regArgs.Labels != "" {
|
||||||
@ -298,9 +271,6 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi
|
|||||||
}
|
}
|
||||||
inputs.Labels = cfg.Runner.Labels
|
inputs.Labels = cfg.Runner.Labels
|
||||||
}
|
}
|
||||||
if len(inputs.Labels) == 0 {
|
|
||||||
inputs.Labels = defaultLabels
|
|
||||||
}
|
|
||||||
|
|
||||||
if inputs.RunnerName == "" {
|
if inputs.RunnerName == "" {
|
||||||
inputs.RunnerName, _ = os.Hostname()
|
inputs.RunnerName, _ = os.Hostname()
|
||||||
@ -308,7 +278,7 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi
|
|||||||
}
|
}
|
||||||
if err := inputs.validate(); err != nil {
|
if err := inputs.validate(); err != nil {
|
||||||
log.WithError(err).Errorf("Invalid input, please re-run act command.")
|
log.WithError(err).Errorf("Invalid input, please re-run act command.")
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
if err := doRegister(ctx, cfg, inputs); err != nil {
|
if err := doRegister(ctx, cfg, inputs); err != nil {
|
||||||
return fmt.Errorf("Failed to register runner: %w", err)
|
return fmt.Errorf("Failed to register runner: %w", err)
|
||||||
@ -351,11 +321,10 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reg := &config.Registration{
|
reg := &config.Registration{
|
||||||
Name: inputs.RunnerName,
|
Name: inputs.RunnerName,
|
||||||
Token: inputs.Token,
|
Token: inputs.Token,
|
||||||
Address: inputs.InstanceAddr,
|
Address: inputs.InstanceAddr,
|
||||||
Labels: inputs.Labels,
|
Labels: inputs.Labels,
|
||||||
Ephemeral: inputs.Ephemeral,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ls := make([]string, len(reg.Labels))
|
ls := make([]string, len(reg.Labels))
|
||||||
@ -370,7 +339,6 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs)
|
|||||||
Version: ver.Version(),
|
Version: ver.Version(),
|
||||||
AgentLabels: ls, // Could be removed after Gitea 1.20
|
AgentLabels: ls, // Could be removed after Gitea 1.20
|
||||||
Labels: ls,
|
Labels: ls,
|
||||||
Ephemeral: reg.Ephemeral,
|
|
||||||
}))
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("poller: cannot register new runner")
|
log.WithError(err).Error("poller: cannot register new runner")
|
||||||
@ -382,11 +350,6 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs)
|
|||||||
reg.Name = resp.Msg.Runner.Name
|
reg.Name = resp.Msg.Runner.Name
|
||||||
reg.Token = resp.Msg.Runner.Token
|
reg.Token = resp.Msg.Runner.Token
|
||||||
|
|
||||||
if inputs.Ephemeral != resp.Msg.Runner.Ephemeral {
|
|
||||||
// TODO we cannot remove the configuration via runner api, if we return an error here we just fill the database
|
|
||||||
log.Error("poller: cannot register new runner as ephemeral upgrade Gitea to gain security, run-once will be used automatically")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := config.SaveRegistration(cfg.Runner.File, reg); err != nil {
|
if err := config.SaveRegistration(cfg.Runner.File, reg); err != nil {
|
||||||
return fmt.Errorf("failed to save runner config: %w", err)
|
return fmt.Errorf("failed to save runner config: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"gotest.tools/v3/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRegisterNonInteractiveReturnsLabelValidationError(t *testing.T) {
|
|
||||||
err := registerNoInteractive(t.Context(), "", ®isterArgs{
|
|
||||||
Labels: "label:invalid",
|
|
||||||
Token: "token",
|
|
||||||
InstanceAddr: "http://localhost:3000",
|
|
||||||
})
|
|
||||||
assert.Error(t, err, "unsupported schema: invalid")
|
|
||||||
}
|
|
@ -70,15 +70,6 @@ func (p *Poller) Poll() {
|
|||||||
close(p.done)
|
close(p.done)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Poller) PollOnce() {
|
|
||||||
limiter := rate.NewLimiter(rate.Every(p.cfg.Runner.FetchInterval), 1)
|
|
||||||
|
|
||||||
p.pollOnce(limiter)
|
|
||||||
|
|
||||||
// signal that we're done
|
|
||||||
close(p.done)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Poller) Shutdown(ctx context.Context) error {
|
func (p *Poller) Shutdown(ctx context.Context) error {
|
||||||
p.shutdownPolling()
|
p.shutdownPolling()
|
||||||
|
|
||||||
@ -110,19 +101,6 @@ func (p *Poller) Shutdown(ctx context.Context) error {
|
|||||||
|
|
||||||
func (p *Poller) poll(wg *sync.WaitGroup, limiter *rate.Limiter) {
|
func (p *Poller) poll(wg *sync.WaitGroup, limiter *rate.Limiter) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for {
|
|
||||||
p.pollOnce(limiter)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-p.pollingCtx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Poller) pollOnce(limiter *rate.Limiter) {
|
|
||||||
for {
|
for {
|
||||||
if err := limiter.Wait(p.pollingCtx); err != nil {
|
if err := limiter.Wait(p.pollingCtx); err != nil {
|
||||||
if p.pollingCtx.Err() != nil {
|
if p.pollingCtx.Err() != nil {
|
||||||
@ -136,7 +114,6 @@ func (p *Poller) pollOnce(limiter *rate.Limiter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.runTaskWithRecover(p.jobsCtx, task)
|
p.runTaskWithRecover(p.jobsCtx, task)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,12 +163,6 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||||||
preset.Token = t
|
preset.Token = t
|
||||||
}
|
}
|
||||||
|
|
||||||
if actionsIdTokenRequestUrl := taskContext["actions_id_token_request_url"].GetStringValue(); actionsIdTokenRequestUrl != "" {
|
|
||||||
r.envs["ACTIONS_ID_TOKEN_REQUEST_URL"] = actionsIdTokenRequestUrl
|
|
||||||
r.envs["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = taskContext["actions_id_token_request_token"].GetStringValue()
|
|
||||||
task.Secrets["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = r.envs["ACTIONS_ID_TOKEN_REQUEST_TOKEN"]
|
|
||||||
}
|
|
||||||
|
|
||||||
giteaRuntimeToken := taskContext["gitea_runtime_token"].GetStringValue()
|
giteaRuntimeToken := taskContext["gitea_runtime_token"].GetStringValue()
|
||||||
if giteaRuntimeToken == "" {
|
if giteaRuntimeToken == "" {
|
||||||
// use task token to action api token for previous Gitea Server Versions
|
// use task token to action api token for previous Gitea Server Versions
|
||||||
|
@ -33,14 +33,14 @@ runner:
|
|||||||
# The interval for fetching the job from the Gitea instance.
|
# The interval for fetching the job from the Gitea instance.
|
||||||
fetch_interval: 2s
|
fetch_interval: 2s
|
||||||
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
|
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
|
||||||
# Like: "macos-arm64:host" or "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
|
# Like: "macos-arm64:host" or "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"
|
||||||
# Find more images provided by Gitea at https://gitea.com/docker.gitea.com/runner-images .
|
# Find more images provided by Gitea at https://gitea.com/gitea/runner-images .
|
||||||
# If it's empty when registering, it will ask for inputting labels.
|
# If it's empty when registering, it will ask for inputting labels.
|
||||||
# If it's empty when execute `daemon`, will use labels in `.runner` file.
|
# If it's empty when execute `daemon`, will use labels in `.runner` file.
|
||||||
labels:
|
labels:
|
||||||
- "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
|
- "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"
|
||||||
- "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
|
- "ubuntu-22.04:docker://gitea/runner-images:ubuntu-22.04"
|
||||||
- "ubuntu-20.04:docker://docker.gitea.com/runner-images:ubuntu-20.04"
|
- "ubuntu-20.04:docker://gitea/runner-images:ubuntu-20.04"
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
# Enable cache server to use actions/cache.
|
# Enable cache server to use actions/cache.
|
||||||
|
@ -14,13 +14,12 @@ const registrationWarning = "This file is automatically generated by act-runner.
|
|||||||
type Registration struct {
|
type Registration struct {
|
||||||
Warning string `json:"WARNING"` // Warning message to display, it's always the registrationWarning constant
|
Warning string `json:"WARNING"` // Warning message to display, it's always the registrationWarning constant
|
||||||
|
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
UUID string `json:"uuid"`
|
UUID string `json:"uuid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Labels []string `json:"labels"`
|
Labels []string `json:"labels"`
|
||||||
Ephemeral bool `json:"ephemeral"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadRegistration(file string) (*Registration, error) {
|
func LoadRegistration(file string) (*Registration, error) {
|
||||||
|
@ -79,7 +79,7 @@ func (l Labels) PickPlatform(runsOn []string) string {
|
|||||||
// So the runner receives a task with a label that the runner doesn't have,
|
// 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.
|
// 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?
|
// TODO: it may be not correct, what if the runner is used as host mode only?
|
||||||
return "docker.gitea.com/runner-images:ubuntu-latest"
|
return "gitea/runner-images:ubuntu-latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Labels) Names() []string {
|
func (l Labels) Names() []string {
|
||||||
|
@ -143,12 +143,6 @@ func (r *Reporter) Fire(entry *log.Entry) error {
|
|||||||
if step.StartedAt == nil {
|
if step.StartedAt == nil {
|
||||||
step.StartedAt = timestamppb.New(timestamp)
|
step.StartedAt = timestamppb.New(timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force reporting log errors as raw output to prevent silent failures
|
|
||||||
if entry.Level == log.ErrorLevel {
|
|
||||||
entry.Data["raw_output"] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, ok := entry.Data["raw_output"]; ok {
|
if v, ok := entry.Data["raw_output"]; ok {
|
||||||
if rawOutput, ok := v.(bool); ok && rawOutput {
|
if rawOutput, ok := v.(bool); ok && rawOutput {
|
||||||
if row := r.parseLogRow(entry); row != nil {
|
if row := r.parseLogRow(entry); row != nil {
|
||||||
|
9
scripts/rootless.sh
Executable file
9
scripts/rootless.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# wait for docker daemon
|
||||||
|
while ! nc -z localhost 2376 </dev/null; do
|
||||||
|
echo 'waiting for docker daemon...'
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
. /opt/act/run.sh
|
@ -16,13 +16,6 @@ EXTRA_ARGS=""
|
|||||||
if [[ ! -z "${GITEA_RUNNER_LABELS}" ]]; then
|
if [[ ! -z "${GITEA_RUNNER_LABELS}" ]]; then
|
||||||
EXTRA_ARGS="${EXTRA_ARGS} --labels ${GITEA_RUNNER_LABELS}"
|
EXTRA_ARGS="${EXTRA_ARGS} --labels ${GITEA_RUNNER_LABELS}"
|
||||||
fi
|
fi
|
||||||
if [[ ! -z "${GITEA_RUNNER_EPHEMERAL}" ]]; then
|
|
||||||
EXTRA_ARGS="${EXTRA_ARGS} --ephemeral"
|
|
||||||
fi
|
|
||||||
RUN_ARGS=""
|
|
||||||
if [[ ! -z "${GITEA_RUNNER_ONCE}" ]]; then
|
|
||||||
RUN_ARGS="${RUN_ARGS} --once"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# In case no token is set, it's possible to read the token from a file, i.e. a Docker Secret
|
# In case no token is set, it's possible to read the token from a file, i.e. a Docker Secret
|
||||||
if [[ -z "${GITEA_RUNNER_REGISTRATION_TOKEN}" ]] && [[ -f "${GITEA_RUNNER_REGISTRATION_TOKEN_FILE}" ]]; then
|
if [[ -z "${GITEA_RUNNER_REGISTRATION_TOKEN}" ]] && [[ -f "${GITEA_RUNNER_REGISTRATION_TOKEN_FILE}" ]]; then
|
||||||
@ -61,4 +54,4 @@ fi
|
|||||||
unset GITEA_RUNNER_REGISTRATION_TOKEN
|
unset GITEA_RUNNER_REGISTRATION_TOKEN
|
||||||
unset GITEA_RUNNER_REGISTRATION_TOKEN_FILE
|
unset GITEA_RUNNER_REGISTRATION_TOKEN_FILE
|
||||||
|
|
||||||
exec act_runner daemon ${CONFIG_ARG} ${RUN_ARGS}
|
exec act_runner daemon ${CONFIG_ARG}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
exec s6-svscanctl -t /etc/s6
|
|
@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
s6-svwait -U /etc/s6/docker
|
|
||||||
|
|
||||||
exec run.sh
|
|
@ -1,6 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
if ! docker info &> /dev/null; then
|
|
||||||
echo "Waiting for Docker daemon to start..."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
exec s6-svscanctl -t /etc/s6
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
3
|
|
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
exec s6-notifyoncheck dockerd-entrypoint.sh
|
|
17
scripts/supervisord.conf
Normal file
17
scripts/supervisord.conf
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[supervisord]
|
||||||
|
nodaemon=true
|
||||||
|
logfile=/dev/null
|
||||||
|
logfile_maxbytes=0
|
||||||
|
|
||||||
|
[program:dockerd]
|
||||||
|
command=/usr/local/bin/dockerd-entrypoint.sh
|
||||||
|
|
||||||
|
[program:act_runner]
|
||||||
|
stdout_logfile=/dev/fd/1
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
redirect_stderr=true
|
||||||
|
command=/opt/act/rootless.sh
|
||||||
|
|
||||||
|
[eventlistener:processes]
|
||||||
|
command=bash -c "echo READY && read line && kill -SIGQUIT $PPID"
|
||||||
|
events=PROCESS_STATE_STOPPED,PROCESS_STATE_EXITED,PROCESS_STATE_FATAL
|
Loading…
x
Reference in New Issue
Block a user