mirror of
https://gitea.com/gitea/runner.git
synced 2026-08-26 05:47:45 +00:00
test: add end-to-end Gitea compatibility suite (#1180)
Adds a real-Gitea compatibility suite against stable and nightly to catch runner and API drift before release. The suite shares one Gitea and regular runner, using repository runners only for cache v1/v2 and ephemeral behavior. It covers registration, payload and log encoding, secrets, variables, services, artifacts, outputs, matrices, cache, dispatch, live logs, cancellation, and ephemeral teardown. CI runs both images in parallel. Warm local timings: | Image | Before | After | | --- | ---: | ---: | | `gitea/gitea:latest` | ~70s | 26.54s | | `gitea/gitea:main-nightly` | ~54s | 22.53s | The former serial matrix took about 2 minutes. Parallel suite execution is now bounded by the slower ~26.5-second variant. Shared Renovate matcher: https://gitea.com/gitea/renovate-config/pulls/552 --------- Co-authored-by: silverwind <me@silverwind.io> Reviewed-on: https://gitea.com/gitea/runner/pulls/1180 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: bircni <bircni@icloud.com>
This commit is contained in:
+11
-57
@@ -8,13 +8,10 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -191,9 +188,6 @@ func TestGraphEvent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// these two build the same action Dockerfiles into one image tag, so they cannot overlap
|
||||
var sharedImageWorkflows = []string{"local-action-dockerfile", "local-action-via-composite-dockerfile"}
|
||||
|
||||
// bounds concurrent plans: each job holds a network, and the daemon's address pool is finite
|
||||
var planSlots = make(chan struct{}, 4)
|
||||
|
||||
@@ -244,11 +238,18 @@ func (j *TestJobFileInfo) runTest(ctx context.Context, t *testing.T, cfg *Config
|
||||
plan, err := planner.PlanEvent(j.eventName)
|
||||
assert.True(t, (err == nil) != (plan == nil), "PlanEvent should return either a plan or an error") //nolint:testifylint // pre-existing issue from nektos/act
|
||||
if err == nil && plan != nil {
|
||||
err = func() error {
|
||||
usesDocker := false
|
||||
for _, platform := range j.platforms {
|
||||
if platform != "-self-hosted" {
|
||||
usesDocker = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if usesDocker && !common.Dryrun(ctx) {
|
||||
planSlots <- struct{}{}
|
||||
defer func() { <-planSlots }()
|
||||
return runner.NewPlanExecutor(plan)(ctx)
|
||||
}()
|
||||
}
|
||||
err = runner.NewPlanExecutor(plan)(ctx)
|
||||
if j.errorMessage == "" {
|
||||
assert.NoError(t, err, fullWorkflowPath) //nolint:testifylint // pre-existing issue from nektos/act
|
||||
} else {
|
||||
@@ -292,7 +293,6 @@ func TestRunEvent(t *testing.T) {
|
||||
|
||||
{workdir, "basic", "push", "", platforms, secrets},
|
||||
{workdir, "fail", "push", "exit with `FAILURE`: 1", platforms, secrets},
|
||||
{workdir, "checkout", "push", "", platforms, secrets},
|
||||
{workdir, "job-container", "push", "", platforms, secrets},
|
||||
{workdir, "job-container-invalid-credentials", "push", "failed to handle credentials: failed to interpolate container.credentials.password", platforms, secrets},
|
||||
{workdir, "container-hostname", "push", "", platforms, secrets},
|
||||
@@ -335,7 +335,6 @@ func TestRunEvent(t *testing.T) {
|
||||
{workdir, "services-empty-image", "push", "", platforms, secrets},
|
||||
}
|
||||
|
||||
var sharedImageMu sync.Mutex
|
||||
for _, table := range tables {
|
||||
t.Run(table.workflowPath, func(t *testing.T) {
|
||||
if table.workflowPath == "container-volumes" {
|
||||
@@ -343,13 +342,10 @@ func TestRunEvent(t *testing.T) {
|
||||
requireLinuxDocker(t)
|
||||
}
|
||||
t.Parallel()
|
||||
if slices.Contains(sharedImageWorkflows, table.workflowPath) {
|
||||
sharedImageMu.Lock()
|
||||
defer sharedImageMu.Unlock()
|
||||
}
|
||||
|
||||
config := &Config{
|
||||
Secrets: table.secrets,
|
||||
Env: map[string]string{"GITHUB_REPOSITORY": t.Name()},
|
||||
}
|
||||
|
||||
eventFile := filepath.Join(workdir, table.workflowPath, "event.json")
|
||||
@@ -401,7 +397,6 @@ func TestRunEventHostEnvironment(t *testing.T) {
|
||||
{workdir, "evalmatrix-merge-map", "push", "", platforms, secrets},
|
||||
{workdir, "evalmatrix-merge-array", "push", "", platforms, secrets},
|
||||
|
||||
{workdir, "checkout", "push", "", platforms, secrets},
|
||||
{workdir, "matrix", "push", "", platforms, secrets},
|
||||
{workdir, "commands", "push", "", platforms, secrets},
|
||||
{workdir, "defaults-run", "push", "", platforms, secrets},
|
||||
@@ -498,47 +493,6 @@ func TestReusableWorkflowCaller(t *testing.T) {
|
||||
table.runTest(context.Background(), t, &Config{Secrets: table.secrets})
|
||||
}
|
||||
|
||||
type maskJobLoggerFactory struct {
|
||||
Output bytes.Buffer
|
||||
}
|
||||
|
||||
func (f *maskJobLoggerFactory) WithJobLogger() *log.Logger {
|
||||
logger := log.New()
|
||||
logger.SetOutput(io.MultiWriter(&f.Output, os.Stdout))
|
||||
logger.SetLevel(log.DebugLevel)
|
||||
return logger
|
||||
}
|
||||
|
||||
func TestMaskValues(t *testing.T) {
|
||||
t.Parallel()
|
||||
assertNoSecret := func(text, secret string) { //nolint:unparam // pre-existing issue from nektos/act
|
||||
found := strings.Contains(text, "composite secret")
|
||||
if found {
|
||||
fmt.Printf("\nFound Secret in the given text:\n%s\n", text) //nolint:forbidigo // pre-existing issue from nektos/act
|
||||
}
|
||||
assert.False(t, strings.Contains(text, "composite secret")) //nolint:testifylint // pre-existing issue from nektos/act
|
||||
}
|
||||
|
||||
requireDocker(t)
|
||||
|
||||
log.SetLevel(log.DebugLevel)
|
||||
|
||||
tjfi := TestJobFileInfo{
|
||||
workdir: workdir,
|
||||
workflowPath: "mask-values",
|
||||
eventName: "push",
|
||||
errorMessage: "",
|
||||
platforms: platforms,
|
||||
}
|
||||
|
||||
logger := &maskJobLoggerFactory{}
|
||||
tjfi.runTest(WithJobLoggerFactory(common.WithLogger(context.Background(), logger.WithJobLogger()), logger), t, &Config{})
|
||||
output := logger.Output.String()
|
||||
|
||||
assertNoSecret(output, "secret value")
|
||||
assertNoSecret(output, "YWJjCg==")
|
||||
}
|
||||
|
||||
func TestRunEventSecrets(t *testing.T) {
|
||||
requireDocker(t)
|
||||
t.Parallel()
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
name: checkout
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
checkout:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -1,12 +0,0 @@
|
||||
name: composite
|
||||
description: composite
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- run: echo "secret value"
|
||||
shell: bash
|
||||
- run: echo "::add-mask::$(echo "abc" | base64)"
|
||||
shell: bash
|
||||
- run: echo "abc" | base64
|
||||
shell: bash
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
name: mask-values
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: echo "::add-mask::secret value"
|
||||
- run: echo "secret value"
|
||||
- uses: ./mask-values/composite
|
||||
- run: echo "YWJjCg=="
|
||||
Reference in New Issue
Block a user