mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-10-29 11:26:31 +08:00
Add `act/common/logging`: a printf-style `Logger` on a slog-shaped `Handler`, with a logrus-backed handler as the only backend, plus a `logtest` handler for tests. Move the job logger onto it: `common.Logger` returns `*logging.Logger`, the job log formatters and the `Reporter` hook become handlers, and composite step IDs travel in the context. Logging is tightly coupled to logrus types (hooks, formatters, `Entry.Data`). Going through our own interface first lets the remaining call sites move over with unchanged behavior, and lets the backend be swapped for `log/slog` in one place afterwards. The global process logger and its masking formatter stay on logrus for now. Assisted-by: Codet Co-authored-by: bircni <bircni@icloud.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/1295 Reviewed-by: bircni <bircni@icloud.com>
111 lines
4.3 KiB
Go
111 lines
4.3 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
|
|
|
package runner
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.com/gitea/runner/act/common"
|
|
"gitea.com/gitea/runner/act/common/logging/logtest"
|
|
"gitea.com/gitea/runner/act/container"
|
|
|
|
"gitea.dev/actionslib/pkg/model"
|
|
cerrdefs "github.com/containerd/errdefs"
|
|
"github.com/moby/moby/client"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDockerProxyMountedJob(t *testing.T) {
|
|
mode := os.Getenv("ACT_TEST_DOCKER_PROXY")
|
|
if mode == "" {
|
|
t.Skip("set ACT_TEST_DOCKER_PROXY=proxy or direct to verify mounted Docker access")
|
|
}
|
|
require.Contains(t, []string{"proxy", "direct"}, mode)
|
|
ctx, cancel := context.WithTimeout(t.Context(), 2*time.Minute)
|
|
defer cancel()
|
|
dockerClient, err := container.GetDockerClient(ctx)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { assert.NoError(t, dockerClient.Close()) })
|
|
require.True(t, strings.HasPrefix(dockerClient.DaemonHost(), "unix://"), "mounted Docker coverage requires a Unix daemon socket")
|
|
|
|
fixtureDir, err := filepath.Abs("testdata/docker-proxy")
|
|
require.NoError(t, err)
|
|
resourceName := "gitea-proxy-test-" + strings.ToLower(rand.Text())
|
|
runner, err := New(&Config{
|
|
Workdir: fixtureDir,
|
|
ActionCacheDir: t.TempDir(),
|
|
EventName: "push",
|
|
PlatformPicker: mapPlatformPicker(platforms),
|
|
ContainerNamePrefix: resourceName,
|
|
ContainerDaemonSocket: dockerClient.DaemonHost(),
|
|
ContainerMaxLifetime: 2 * time.Minute,
|
|
ContainerOptions: "-v /usr/local/bin/docker:/usr/local/bin/docker:ro -v /usr/local/libexec/docker/cli-plugins:/usr/local/libexec/docker/cli-plugins:ro",
|
|
ValidVolumes: []string{"/usr/local/bin/docker", "/usr/local/libexec/docker/cli-plugins"},
|
|
Env: map[string]string{"PROXY_TEST_RESOURCE": resourceName, "PROXY_TEST_MODE": mode, "PROXY_TEST_IMAGE": baseImage, "COMPOSE_PROJECT_NAME": resourceName},
|
|
})
|
|
require.NoError(t, err)
|
|
planner, err := model.NewWorkflowPlanner(filepath.Join(fixtureDir, "push.yml"), true)
|
|
require.NoError(t, err)
|
|
plan, err := planner.PlanEvent("push")
|
|
if mode == "direct" {
|
|
plan, err = planner.PlanJob("proxy")
|
|
}
|
|
require.NoError(t, err)
|
|
runContext, err := runner.newRunContext(ctx, plan.Stages[0].Runs[0], nil)
|
|
require.NoError(t, err)
|
|
jobName := runContext.jobContainerName()
|
|
jobNetwork, _ := runContext.networkNameForGitea()
|
|
t.Cleanup(func() {
|
|
cleanCtx, cleanCancel := context.WithTimeout(context.WithoutCancel(ctx), 30*time.Second)
|
|
defer cleanCancel()
|
|
if _, err := dockerClient.ContainerRemove(cleanCtx, jobName, client.ContainerRemoveOptions{Force: true, RemoveVolumes: true}); !cerrdefs.IsNotFound(err) {
|
|
assert.NoError(t, err)
|
|
}
|
|
for _, name := range []string{resourceName, jobNetwork} {
|
|
if _, err := dockerClient.NetworkRemove(cleanCtx, name, client.NetworkRemoveOptions{}); !cerrdefs.IsNotFound(err) {
|
|
assert.NoError(t, err)
|
|
}
|
|
}
|
|
for _, name := range []string{resourceName, jobName, jobName + "-env"} {
|
|
if _, err := dockerClient.VolumeRemove(cleanCtx, name, client.VolumeRemoveOptions{}); !cerrdefs.IsNotFound(err) {
|
|
assert.NoError(t, err)
|
|
}
|
|
}
|
|
})
|
|
|
|
hook := logtest.New()
|
|
require.NoError(t, runner.NewPlanExecutor(plan)(common.WithLoggerHandler(ctx, hook)))
|
|
var messages []string
|
|
for _, entry := range hook.AllRecords() {
|
|
messages = append(messages, strings.TrimSpace(entry.Message))
|
|
}
|
|
require.Contains(t, messages, "docker proxy post verified")
|
|
if mode == "proxy" {
|
|
require.Contains(t, messages, "docker binds verified")
|
|
}
|
|
_, err = dockerClient.ContainerInspect(ctx, jobName, client.ContainerInspectOptions{})
|
|
assert.True(t, cerrdefs.IsNotFound(err), "job container survived cleanup: %v", err)
|
|
_, err = dockerClient.NetworkInspect(ctx, resourceName, client.NetworkInspectOptions{})
|
|
if mode == "proxy" {
|
|
assert.True(t, cerrdefs.IsNotFound(err), "labelled network survived cleanup: %v", err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
_, err = dockerClient.VolumeInspect(ctx, resourceName, client.VolumeInspectOptions{})
|
|
if mode == "proxy" {
|
|
assert.True(t, cerrdefs.IsNotFound(err), "labelled volume survived cleanup: %v", err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
}
|