test: add e2e tests with local Forgejo instance (#201)

* feat(forge): add new forge for forgejo

We only support repositories hosted on Forgejo instances, but not
Forgejo Actions or Woodpecker as CI solutions for now.

* test(e2e): introduce e2e test framework with local forgejo
This commit is contained in:
Julian Tölle 2025-09-13 12:00:54 +02:00 committed by GitHub
parent afef176e37
commit fcf7906149
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 936 additions and 1 deletions

23
test/e2e/forgejo/app.ini Normal file
View file

@ -0,0 +1,23 @@
WORK_PATH = /data/gitea
[database]
DB_TYPE = sqlite3
PATH = /data/gitea/forgejo.db
[security]
INSTALL_LOCK = true
SECRET_KEY = releaser-pleaser
INTERNAL_TOKEN = releaser-pleaser
[service]
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
DISABLE_REGISTRATION = true
[server]
DOMAIN = localhost
HTTP_PORT = 3000
ROOT_URL = http://localhost:3000/
[oauth2]
JWT_SECRET = rTD-FL2n_aBB6v4AOcr5lBvwgZ6PSr3HGZAuNH6nMu8

View file

@ -0,0 +1,16 @@
services:
forgejo:
image: codeberg.org/forgejo/forgejo:11
ports:
- '3000:3000'
- '222:22'
volumes:
- data:/data/gitea
- ./app.ini:/data/gitea/conf/app.ini:ro
healthcheck:
test: ["CMD", "curl", "localhost:3000/api/healthz"]
volumes:
data:

113
test/e2e/forgejo/forge.go Normal file
View file

@ -0,0 +1,113 @@
package forgejo
import (
"context"
"fmt"
"log/slog"
"os/exec"
"strings"
"testing"
"codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2"
"github.com/apricote/releaser-pleaser/test/e2e"
)
const (
TestAPIURL = "http://localhost:3000"
TestUserNameTemplate = "rp-%s"
TestUserPassword = "releaser-pleaser"
TestUserEmailTemplate = "releaser-pleaser-%s@example.com"
TestTokenName = "rp"
TestTokenScopes = "write:user,write:issue,write:repository"
)
type TestForge struct {
username string
token string
client *forgejo.Client
}
func (f *TestForge) Init(ctx context.Context, runID string) error {
if err := f.initUser(ctx, runID); err != nil {
return err
}
if err := f.initClient(ctx); err != nil {
return err
}
return nil
}
func (f *TestForge) initUser(ctx context.Context, runID string) error {
f.username = fmt.Sprintf(TestUserNameTemplate, runID)
//gosec:disable G204
if output, err := exec.CommandContext(ctx,
"docker", "compose", "exec", "--user=1000", "forgejo",
"forgejo", "admin", "user", "create",
"--username", f.username,
"--password", TestUserPassword,
"--email", fmt.Sprintf(TestUserEmailTemplate, runID),
"--must-change-password=false",
).CombinedOutput(); err != nil {
slog.Debug("create forgejo user output", "output", output)
return fmt.Errorf("failed to create forgejo user: %w", err)
}
//gosec:disable G204
token, err := exec.CommandContext(ctx,
"docker", "compose", "exec", "--user=1000", "forgejo",
"forgejo", "admin", "user", "generate-access-token",
"--username", f.username,
"--token-name", TestTokenName,
"--scopes", TestTokenScopes,
"--raw",
).Output()
if err != nil {
return fmt.Errorf("failed to create forgejo token: %w", err)
}
f.token = strings.TrimSpace(string(token))
return nil
}
func (f *TestForge) initClient(ctx context.Context) (err error) {
f.client, err = forgejo.NewClient(TestAPIURL,
forgejo.SetToken(f.token),
forgejo.SetUserAgent("releaser-pleaser-e2e-tests"),
forgejo.SetContext(ctx),
// forgejo.SetDebugMode(),
)
return err
}
func (f *TestForge) CreateRepo(t *testing.T, opts e2e.CreateRepoOpts) (*e2e.Repository, error) {
t.Helper()
repo, _, err := f.client.CreateRepo(forgejo.CreateRepoOption{
Name: opts.Name,
Description: opts.Description,
DefaultBranch: opts.DefaultBranch,
Readme: "Default",
AutoInit: true,
})
if err != nil {
return nil, err
}
return &e2e.Repository{
Name: repo.Name,
}, nil
}
func (f *TestForge) RunArguments() []string {
return []string{"--forge=forgejo",
fmt.Sprintf("--owner=%s", f.username),
fmt.Sprintf("--api-url=%s", TestAPIURL),
fmt.Sprintf("--api-token=%s", f.token),
fmt.Sprintf("--username=%s", f.username),
}
}

View file

@ -0,0 +1,39 @@
//go:build e2e_forgejo
package forgejo
import (
"context"
"log/slog"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/apricote/releaser-pleaser/test/e2e"
)
var (
f *e2e.Framework
)
func TestMain(m *testing.M) {
ctx := context.Background()
var err error
f, err = e2e.NewFramework(ctx, &TestForge{})
if err != nil {
slog.Error("failed to set up test framework", "err", err)
}
os.Exit(m.Run())
}
func TestCreateRepository(t *testing.T) {
_ = f.NewRepository(t, t.Name())
}
func TestRun(t *testing.T) {
repo := f.NewRepository(t, t.Name())
require.NoError(t, f.Run(t, repo, []string{}))
}