mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-05-07 15:53:24 +02:00
fix: avoid 'filename too long' on matrix jobs by hashing container names (#853)
## Bug fixes
- Fixed "file name too long" errors when running matrix jobs with many or
long-valued matrix parameters. Docker volume and container names are now
bounded to a safe length by hashing the full name with SHA-256, keeping
the result well within the filesystem `NAME_MAX` limit (255 bytes) even
after Docker appends its own suffixes (`-env`, `-network`, etc.).
## Upgrade notes
This change renames the Docker containers, volumes and networks created by
the runner. Resources created by a previous version will **not** be cleaned
up automatically after upgrade and will become orphans.
After upgrading, you can remove the legacy resources with:
```sh
# volumes
docker volume ls -q | grep -E '^GITEA-ACTIONS-TASK-[0-9]+_' | xargs -r docker volume rm
# networks
docker network ls --format '{{.Name}}' | grep -E '^GITEA-ACTIONS-TASK-[0-9]+_.*-network$' | xargs -r docker network rm
```
> **Note:** If multiple act_runner instances share the same Docker daemon,
> make sure no runner using the old version is running before executing the
> cleanup commands above.
Fixes #686
---------
Co-authored-by: Nicolas <bircni@icloud.com>
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/853
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: Morgan Peyre <195218+peyremorgan@noreply.gitea.com>
Co-committed-by: Morgan Peyre <195218+peyremorgan@noreply.gitea.com>
This commit is contained in:
@@ -429,7 +429,7 @@ func newStepContainer(ctx context.Context, step step, image string, cmd, entrypo
|
|||||||
Image: image,
|
Image: image,
|
||||||
Username: rc.Config.Secrets["DOCKER_USERNAME"],
|
Username: rc.Config.Secrets["DOCKER_USERNAME"],
|
||||||
Password: rc.Config.Secrets["DOCKER_PASSWORD"],
|
Password: rc.Config.Secrets["DOCKER_PASSWORD"],
|
||||||
Name: createSimpleContainerName(rc.jobContainerName(), "STEP-"+stepModel.ID),
|
Name: createContainerName(rc.jobContainerName(), "STEP-"+stepModel.ID),
|
||||||
Env: envList,
|
Env: envList,
|
||||||
Mounts: mounts,
|
Mounts: mounts,
|
||||||
NetworkMode: networkMode,
|
NetworkMode: networkMode,
|
||||||
|
|||||||
@@ -101,8 +101,7 @@ func (rc *RunContext) jobContainerName() string {
|
|||||||
if rc.caller != nil {
|
if rc.caller != nil {
|
||||||
nameParts = append(nameParts, "CALLED-BY-"+rc.caller.runContext.JobName)
|
nameParts = append(nameParts, "CALLED-BY-"+rc.caller.runContext.JobName)
|
||||||
}
|
}
|
||||||
// return createSimpleContainerName(rc.Config.ContainerNamePrefix, "WORKFLOW-"+rc.Run.Workflow.Name, "JOB-"+rc.Name)
|
return createContainerName(nameParts...) // For Gitea
|
||||||
return createSimpleContainerName(nameParts...) // For Gitea
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// networkNameForGitea return the name of the network
|
// networkNameForGitea return the name of the network
|
||||||
@@ -769,7 +768,6 @@ func mergeMaps(maps ...map[string]string) map[string]string {
|
|||||||
return rtnMap
|
return rtnMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: use createSimpleContainerName
|
|
||||||
func createContainerName(parts ...string) string {
|
func createContainerName(parts ...string) string {
|
||||||
name := strings.Join(parts, "-")
|
name := strings.Join(parts, "-")
|
||||||
pattern := regexp.MustCompile("[^a-zA-Z0-9]")
|
pattern := regexp.MustCompile("[^a-zA-Z0-9]")
|
||||||
@@ -783,22 +781,6 @@ func createContainerName(parts ...string) string {
|
|||||||
return fmt.Sprintf("%s-%x", trimmedName, hash)
|
return fmt.Sprintf("%s-%x", trimmedName, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSimpleContainerName(parts ...string) string {
|
|
||||||
pattern := regexp.MustCompile("[^a-zA-Z0-9-]")
|
|
||||||
name := make([]string, 0, len(parts))
|
|
||||||
for _, v := range parts {
|
|
||||||
v = pattern.ReplaceAllString(v, "-")
|
|
||||||
v = strings.Trim(v, "-")
|
|
||||||
for strings.Contains(v, "--") {
|
|
||||||
v = strings.ReplaceAll(v, "--", "-")
|
|
||||||
}
|
|
||||||
if v != "" {
|
|
||||||
name = append(name, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(name, "_")
|
|
||||||
}
|
|
||||||
|
|
||||||
func trimToLen(s string, l int) string {
|
func trimToLen(s string, l int) string {
|
||||||
if l < 0 {
|
if l < 0 {
|
||||||
l = 0
|
l = 0
|
||||||
|
|||||||
@@ -622,23 +622,16 @@ func TestRunContextGetEnv(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_createSimpleContainerName(t *testing.T) {
|
func TestCreateContainerNameBoundedForLongMatrixInput(t *testing.T) {
|
||||||
tests := []struct {
|
longMatrixValue := strings.Repeat("os=ubuntu-latest-go=1.24-node=22-", 20)
|
||||||
parts []string
|
name := createContainerName(
|
||||||
want string
|
"gitea",
|
||||||
}{
|
"WORKFLOW-super-long-workflow-name",
|
||||||
{
|
"JOB-build-matrix-"+longMatrixValue,
|
||||||
parts: []string{"a--a", "BB正", "c-C"},
|
)
|
||||||
want: "a-a_BB_c-C",
|
|
||||||
},
|
assert.LessOrEqual(t, len(name), 128)
|
||||||
{
|
assert.LessOrEqual(t, len(name+"-env"), 255)
|
||||||
parts: []string{"a-a", "", "-"},
|
assert.LessOrEqual(t, len(name+"-network"), 255)
|
||||||
want: "a-a",
|
assert.LessOrEqual(t, len(name+"-job1234567890"), 255)
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(strings.Join(tt.parts, " "), func(t *testing.T) {
|
|
||||||
assert.Equalf(t, tt.want, createSimpleContainerName(tt.parts...), "createSimpleContainerName(%v)", tt.parts)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ func (sd *stepDocker) newStepContainer(ctx context.Context, image string, cmd, e
|
|||||||
Image: image,
|
Image: image,
|
||||||
Username: rc.Config.Secrets["DOCKER_USERNAME"],
|
Username: rc.Config.Secrets["DOCKER_USERNAME"],
|
||||||
Password: rc.Config.Secrets["DOCKER_PASSWORD"],
|
Password: rc.Config.Secrets["DOCKER_PASSWORD"],
|
||||||
Name: createSimpleContainerName(rc.jobContainerName(), "STEP-"+step.ID),
|
Name: createContainerName(rc.jobContainerName(), "STEP-"+step.ID),
|
||||||
Env: envList,
|
Env: envList,
|
||||||
Mounts: mounts,
|
Mounts: mounts,
|
||||||
NetworkMode: networkMode,
|
NetworkMode: networkMode,
|
||||||
|
|||||||
Reference in New Issue
Block a user