mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-03-20 03:46:09 +08:00
feat: add configurable bind_workdir option with workspace cleanup for DinD setups (#810)
## Summary
Adds a `container.bind_workdir` config option that exposes the nektos/act `BindWorkdir` setting. When enabled, workspaces are bind-mounted from the host filesystem instead of Docker volumes, which is required for DinD setups where jobs use `docker compose` with bind mounts (e.g. `.:/app`).
Each job gets an isolated workspace at `/workspace/<task_id>/<owner>/<repo>` to prevent concurrent jobs from the same repo interfering with each other. The task directory is cleaned up after job execution.
### Configuration
```yaml
container:
bind_workdir: true
```
When using this with DinD, also mount the workspace parent into the runner container and add it to `valid_volumes`:
```yaml
container:
valid_volumes:
- /workspace/**
```
*This PR was authored by Claude (AI assistant)*
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/810
Reviewed-by: ChristopherHX <38043+christopherhx@noreply.gitea.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -196,11 +197,18 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
||||
maxLifetime = time.Until(deadline)
|
||||
}
|
||||
|
||||
workdirParent := strings.TrimLeft(r.cfg.Container.WorkdirParent, "/")
|
||||
if r.cfg.Container.BindWorkdir {
|
||||
// Append the task ID to isolate concurrent jobs from the same repo.
|
||||
workdirParent = fmt.Sprintf("%s/%d", workdirParent, task.Id)
|
||||
}
|
||||
workdir := filepath.FromSlash(fmt.Sprintf("/%s/%s", workdirParent, preset.Repository))
|
||||
|
||||
runnerConfig := &runner.Config{
|
||||
// On Linux, Workdir will be like "/<parent_directory>/<owner>/<repo>"
|
||||
// On Windows, Workdir will be like "\<parent_directory>\<owner>\<repo>"
|
||||
Workdir: filepath.FromSlash(fmt.Sprintf("/%s/%s", strings.TrimLeft(r.cfg.Container.WorkdirParent, "/"), preset.Repository)),
|
||||
BindWorkdir: false,
|
||||
Workdir: workdir,
|
||||
BindWorkdir: r.cfg.Container.BindWorkdir,
|
||||
ActionCacheDir: filepath.FromSlash(r.cfg.Host.WorkdirParent),
|
||||
|
||||
ReuseContainers: false,
|
||||
@@ -245,6 +253,15 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
||||
|
||||
execErr := executor(ctx)
|
||||
reporter.SetOutputs(job.Outputs)
|
||||
|
||||
if r.cfg.Container.BindWorkdir {
|
||||
// Remove the entire task-specific directory (e.g. /workspace/<task_id>).
|
||||
taskDir := filepath.FromSlash("/" + workdirParent)
|
||||
if err := os.RemoveAll(taskDir); err != nil {
|
||||
log.Warnf("failed to clean up workspace %s: %v", taskDir, err)
|
||||
}
|
||||
}
|
||||
|
||||
return execErr
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user