2 Commits

Author SHA1 Message Date
Garet Halliday
47c8d37a8a sort imports 2024-09-11 12:24:25 -06:00
Garet Halliday
d1a6a360e4 add once flag to daemon 2024-09-10 12:26:09 -06:00
12 changed files with 70 additions and 43 deletions

View File

@@ -17,9 +17,10 @@ jobs:
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"
- name: goreleaser - name: goreleaser
uses: goreleaser/goreleaser-action@v6 uses: goreleaser/goreleaser-action@v5
with: with:
distribution: goreleaser-pro distribution: goreleaser-pro
version: latest
args: release --nightly args: release --nightly
env: env:
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

View File

@@ -23,9 +23,10 @@ jobs:
passphrase: ${{ secrets.PASSPHRASE }} passphrase: ${{ secrets.PASSPHRASE }}
fingerprint: CC64B1DB67ABBEECAB24B6455FC346329753F4B0 fingerprint: CC64B1DB67ABBEECAB24B6455FC346329753F4B0
- name: goreleaser - name: goreleaser
uses: goreleaser/goreleaser-action@v6 uses: goreleaser/goreleaser-action@v5
with: with:
distribution: goreleaser-pro distribution: goreleaser-pro
version: latest
args: release args: release
env: env:
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

View File

@@ -1,5 +1,3 @@
version: 2
before: before:
hooks: hooks:
- go mod tidy - go mod tidy
@@ -83,7 +81,7 @@ blobs:
provider: s3 provider: s3
bucket: "{{ .Env.S3_BUCKET }}" bucket: "{{ .Env.S3_BUCKET }}"
region: "{{ .Env.S3_REGION }}" region: "{{ .Env.S3_REGION }}"
directory: "act_runner/{{.Version}}" folder: "act_runner/{{.Version}}"
extra_files: extra_files:
- glob: ./**.xz - glob: ./**.xz
- glob: ./**.sha256 - glob: ./**.sha256
@@ -99,10 +97,10 @@ checksum:
- glob: ./**.xz - glob: ./**.xz
snapshot: snapshot:
version_template: "{{ .Branch }}-devel" name_template: "{{ .Branch }}-devel"
nightly: nightly:
version_template: "nightly" name_template: "nightly"
gitea_urls: gitea_urls:
api: https://gitea.com/api/v1 api: https://gitea.com/api/v1

View File

@@ -1,4 +1,4 @@
FROM golang:1.23-alpine AS builder FROM golang:1.21-alpine3.18 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
@@ -7,7 +7,7 @@ WORKDIR /opt/src/act_runner
RUN make clean && make build RUN make clean && make build
FROM alpine FROM alpine:3.18
RUN apk add --no-cache git bash tini RUN apk add --no-cache git bash tini
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

View File

@@ -1,4 +1,4 @@
FROM golang:1.23-alpine AS builder FROM golang:1.21-alpine3.18 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

View File

@@ -5,22 +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
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

View File

@@ -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.

4
go.mod
View File

@@ -1,6 +1,6 @@
module gitea.com/gitea/act_runner module gitea.com/gitea/act_runner
go 1.23 go 1.22
require ( require (
code.gitea.io/actions-proto-go v0.4.0 code.gitea.io/actions-proto-go v0.4.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.3 replace github.com/nektos/act => gitea.com/gitea/act v0.261.1

4
go.sum
View File

@@ -6,8 +6,8 @@ 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.3 h1:BhiYpGJQKGq0XMYYICCYAN4KnsEWHyLbA6dxhZwFcV4= gitea.com/gitea/act v0.261.1 h1:iACWLc/k8wct9fCF2WdYKqn2Hxx6NjW9zbOP79HF4H4=
gitea.com/gitea/act v0.261.3/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok= gitea.com/gitea/act v0.261.1/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=

View File

@@ -42,12 +42,14 @@ func Execute(ctx context.Context) {
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(1), Args: cobra.MaximumNArgs(0),
RunE: runDaemon(ctx, &configFile), RunE: runDaemon(ctx, &daemArgs, &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

View File

@@ -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, configFile *string) func(cmd *cobra.Command, args []string) error { func runDaemon(ctx context.Context, daemArgs *daemonArgs, 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,9 +122,24 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command,
poller := poll.New(cfg, cli, runner) poller := poll.New(cfg, cli, runner)
go poller.Poll() if daemArgs.Once {
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)
@@ -134,10 +149,15 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command,
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) {
isTerm := isatty.IsTerminal(os.Stdout.Fd()) isTerm := isatty.IsTerminal(os.Stdout.Fd())

View File

@@ -70,6 +70,15 @@ 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()
@@ -101,6 +110,19 @@ 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 {
@@ -114,6 +136,7 @@ func (p *Poller) poll(wg *sync.WaitGroup, limiter *rate.Limiter) {
} }
p.runTaskWithRecover(p.jobsCtx, task) p.runTaskWithRecover(p.jobsCtx, task)
return
} }
} }