mirror of
https://github.com/apricote/releaser-pleaser.git
synced 2026-02-08 10:47:02 +00:00
Compare commits
3 commits
17ea9b6cf5
...
af70a267f5
| Author | SHA1 | Date | |
|---|---|---|---|
| af70a267f5 | |||
| 6ed133946e | |||
| f3269de8fe |
14 changed files with 218 additions and 348 deletions
29
.github/workflows/ci.yaml
vendored
29
.github/workflows/ci.yaml
vendored
|
|
@ -41,35 +41,6 @@ jobs:
|
|||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: unit
|
||||
|
||||
test-e2e-forgejo:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
# We can not use "jobs.<job>.services".
|
||||
# We want to mount the config file, which is only available after "Checkout".
|
||||
- name: Start Forgejo
|
||||
working-directory: test/e2e/forgejo
|
||||
run: docker compose up --wait
|
||||
|
||||
- name: Run tests
|
||||
run: go test -tags e2e_forgejo -v -race -coverpkg=./... -coverprofile=coverage.txt ./test/e2e/forgejo
|
||||
|
||||
|
||||
- name: Upload results to Codecov
|
||||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: e2e
|
||||
|
||||
go-mod-tidy:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
|
|
@ -5,15 +5,14 @@ import (
|
|||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/apricote/releaser-pleaser/internal/forge/forgejo"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
rp "github.com/apricote/releaser-pleaser"
|
||||
"github.com/apricote/releaser-pleaser/internal/commitparser/conventionalcommits"
|
||||
"github.com/apricote/releaser-pleaser/internal/forge"
|
||||
"github.com/apricote/releaser-pleaser/internal/forge/forgejo"
|
||||
"github.com/apricote/releaser-pleaser/internal/forge/github"
|
||||
"github.com/apricote/releaser-pleaser/internal/forge/gitlab"
|
||||
"github.com/apricote/releaser-pleaser/internal/log"
|
||||
"github.com/apricote/releaser-pleaser/internal/updater"
|
||||
"github.com/apricote/releaser-pleaser/internal/versioning"
|
||||
)
|
||||
|
|
@ -35,11 +34,10 @@ func newRunCommand() *cobra.Command {
|
|||
Use: "run",
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
ctx := cmd.Context()
|
||||
logger := log.GetLogger(cmd.ErrOrStderr())
|
||||
|
||||
var err error
|
||||
|
||||
logger.DebugContext(ctx, "run called",
|
||||
slog.DebugContext(ctx, "run called",
|
||||
"forge", flagForge,
|
||||
"branch", flagBranch,
|
||||
"owner", flagOwner,
|
||||
|
|
@ -55,8 +53,8 @@ func newRunCommand() *cobra.Command {
|
|||
|
||||
switch flagForge {
|
||||
case "gitlab":
|
||||
logger.DebugContext(ctx, "using forge GitLab")
|
||||
f, err = gitlab.New(logger, &gitlab.Options{
|
||||
slog.DebugContext(ctx, "using forge GitLab")
|
||||
f, err = gitlab.New(slog.Default(), &gitlab.Options{
|
||||
Options: forgeOptions,
|
||||
Path: fmt.Sprintf("%s/%s", flagOwner, flagRepo),
|
||||
})
|
||||
|
|
@ -65,15 +63,15 @@ func newRunCommand() *cobra.Command {
|
|||
return fmt.Errorf("failed to create gitlab client: %w", err)
|
||||
}
|
||||
case "github":
|
||||
logger.DebugContext(ctx, "using forge GitHub")
|
||||
f = github.New(logger, &github.Options{
|
||||
slog.DebugContext(ctx, "using forge GitHub")
|
||||
f = github.New(slog.Default(), &github.Options{
|
||||
Options: forgeOptions,
|
||||
Owner: flagOwner,
|
||||
Repo: flagRepo,
|
||||
})
|
||||
case "forgejo":
|
||||
logger.DebugContext(ctx, "using forge Forgejo")
|
||||
f, err = forgejo.New(logger, &forgejo.Options{
|
||||
slog.DebugContext(ctx, "using forge Forgejo")
|
||||
f, err = forgejo.New(slog.Default(), &forgejo.Options{
|
||||
Options: forgeOptions,
|
||||
Owner: flagOwner,
|
||||
Repo: flagRepo,
|
||||
|
|
@ -83,7 +81,7 @@ func newRunCommand() *cobra.Command {
|
|||
Username: flagUsername,
|
||||
})
|
||||
if err != nil {
|
||||
logger.ErrorContext(ctx, "failed to create client", "err", err)
|
||||
slog.ErrorContext(ctx, "failed to create client", "err", err)
|
||||
return fmt.Errorf("failed to create forgejo client: %w", err)
|
||||
}
|
||||
default:
|
||||
|
|
@ -94,9 +92,9 @@ func newRunCommand() *cobra.Command {
|
|||
|
||||
releaserPleaser := rp.New(
|
||||
f,
|
||||
logger,
|
||||
slog.Default(),
|
||||
flagBranch,
|
||||
conventionalcommits.NewParser(logger),
|
||||
conventionalcommits.NewParser(slog.Default()),
|
||||
versioning.SemVer,
|
||||
extraFiles,
|
||||
[]updater.NewUpdater{updater.Generic},
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
ignore:
|
||||
- "test"
|
||||
4
go.mod
4
go.mod
|
|
@ -1,6 +1,6 @@
|
|||
module github.com/apricote/releaser-pleaser
|
||||
|
||||
go 1.24
|
||||
go 1.23.2
|
||||
|
||||
toolchain go1.24.4
|
||||
|
||||
|
|
@ -55,4 +55,4 @@ require (
|
|||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 => codeberg.org/apricote/forgejo-sdk/forgejo/v2 v2.1.2-0.20250615152743-47d3f0434561
|
||||
replace codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 => ../../../codeberg.org/mvdkleijn/forgejo-sdk/forgejo
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -1,5 +1,5 @@
|
|||
codeberg.org/apricote/forgejo-sdk/forgejo/v2 v2.1.2-0.20250615152743-47d3f0434561 h1:ZFGmrGQ7cd2mbSLrfjrj3COwPKFfKM6sDO/IsrGDW7w=
|
||||
codeberg.org/apricote/forgejo-sdk/forgejo/v2 v2.1.2-0.20250615152743-47d3f0434561/go.mod h1:2i9GsyawlJtVMO5pTS/Om5uo2O3JN/eCjGWy5v15NGg=
|
||||
codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.1.0 h1:BsxZzd3nPPMyv8r6W964OL7XgTpsXvxO8f0vBTWpPok=
|
||||
codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.1.0/go.mod h1:2i9GsyawlJtVMO5pTS/Om5uo2O3JN/eCjGWy5v15NGg=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs=
|
||||
|
|
|
|||
|
|
@ -8,14 +8,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2"
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
|
||||
"github.com/apricote/releaser-pleaser/internal/forge"
|
||||
"github.com/apricote/releaser-pleaser/internal/git"
|
||||
"github.com/apricote/releaser-pleaser/internal/pointer"
|
||||
"github.com/apricote/releaser-pleaser/internal/releasepr"
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
)
|
||||
|
||||
const ()
|
||||
|
|
@ -147,7 +146,7 @@ func (f *Forgejo) CommitsSince(ctx context.Context, tag *git.Tag) ([]git.Commit,
|
|||
return commits, nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) commitsSinceTag(_ context.Context, tag *git.Tag) ([]*forgejo.Commit, error) {
|
||||
func (f *Forgejo) commitsSinceTag(ctx context.Context, tag *git.Tag) ([]*forgejo.Commit, error) {
|
||||
head := f.options.BaseBranch
|
||||
log := f.log.With("base", tag.Hash, "head", head)
|
||||
log.Debug("comparing commits")
|
||||
|
|
@ -162,7 +161,7 @@ func (f *Forgejo) commitsSinceTag(_ context.Context, tag *git.Tag) ([]*forgejo.C
|
|||
return compare.Commits, nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) commitsSinceInit(_ context.Context) ([]*forgejo.Commit, error) {
|
||||
func (f *Forgejo) commitsSinceInit(ctx context.Context) ([]*forgejo.Commit, error) {
|
||||
head := f.options.BaseBranch
|
||||
log := f.log.With("head", head)
|
||||
log.Debug("listing all commits")
|
||||
|
|
@ -183,7 +182,7 @@ func (f *Forgejo) commitsSinceInit(_ context.Context) ([]*forgejo.Commit, error)
|
|||
return repositoryCommits, nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) prForCommit(_ context.Context, commit git.Commit) (*git.PullRequest, error) {
|
||||
func (f *Forgejo) prForCommit(ctx context.Context, commit git.Commit) (*git.PullRequest, error) {
|
||||
// We naively look up the associated PR for each commit through the "List pull requests associated with a commit"
|
||||
// endpoint. This requires len(commits) requests.
|
||||
// Using the "List pull requests" endpoint might be faster, as it allows us to fetch 100 arbitrary PRs per request,
|
||||
|
|
@ -196,17 +195,13 @@ func (f *Forgejo) prForCommit(_ context.Context, commit git.Commit) (*git.PullRe
|
|||
commit.Hash,
|
||||
)
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "pull request does not exist") {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return forgejoPRToPullRequest(pullRequest), nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) EnsureLabelsExist(_ context.Context, labels []releasepr.Label) error {
|
||||
func (f *Forgejo) EnsureLabelsExist(ctx context.Context, labels []releasepr.Label) error {
|
||||
f.log.Debug("fetching labels on repo")
|
||||
fLabels, err := all(func(listOptions forgejo.ListOptions) ([]*forgejo.Label, *forgejo.Response, error) {
|
||||
return f.client.ListRepoLabels(
|
||||
|
|
@ -239,7 +234,7 @@ func (f *Forgejo) EnsureLabelsExist(_ context.Context, labels []releasepr.Label)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) PullRequestForBranch(_ context.Context, branch string) (*releasepr.ReleasePullRequest, error) {
|
||||
func (f *Forgejo) PullRequestForBranch(ctx context.Context, branch string) (*releasepr.ReleasePullRequest, error) {
|
||||
prs, err := all(
|
||||
func(listOptions forgejo.ListOptions) ([]*forgejo.PullRequest, *forgejo.Response, error) {
|
||||
return f.client.ListRepoPullRequests(
|
||||
|
|
@ -289,7 +284,7 @@ func (f *Forgejo) CreatePullRequest(ctx context.Context, pr *releasepr.ReleasePu
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) UpdatePullRequest(_ context.Context, pr *releasepr.ReleasePullRequest) error {
|
||||
func (f *Forgejo) UpdatePullRequest(ctx context.Context, pr *releasepr.ReleasePullRequest) error {
|
||||
_, _, err := f.client.EditPullRequest(
|
||||
f.options.Owner, f.options.Repo,
|
||||
int64(pr.ID), forgejo.EditPullRequestOption{
|
||||
|
|
@ -304,15 +299,12 @@ func (f *Forgejo) UpdatePullRequest(_ context.Context, pr *releasepr.ReleasePull
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) SetPullRequestLabels(_ context.Context, pr *releasepr.ReleasePullRequest, remove, add []releasepr.Label) error {
|
||||
func (f *Forgejo) SetPullRequestLabels(ctx context.Context, pr *releasepr.ReleasePullRequest, remove, add []releasepr.Label) error {
|
||||
allLabels, err := all(
|
||||
func(listOptions forgejo.ListOptions) ([]*forgejo.Label, *forgejo.Response, error) {
|
||||
return f.client.ListRepoLabels(f.options.Owner, f.options.Repo, forgejo.ListLabelsOptions{ListOptions: listOptions})
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
findLabel := func(labelName string) *forgejo.Label {
|
||||
for _, fLabel := range allLabels {
|
||||
|
|
@ -360,7 +352,7 @@ func (f *Forgejo) SetPullRequestLabels(_ context.Context, pr *releasepr.ReleaseP
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) ClosePullRequest(_ context.Context, pr *releasepr.ReleasePullRequest) error {
|
||||
func (f *Forgejo) ClosePullRequest(ctx context.Context, pr *releasepr.ReleasePullRequest) error {
|
||||
_, _, err := f.client.EditPullRequest(
|
||||
f.options.Owner, f.options.Repo,
|
||||
int64(pr.ID), forgejo.EditPullRequestOption{
|
||||
|
|
@ -374,7 +366,7 @@ func (f *Forgejo) ClosePullRequest(_ context.Context, pr *releasepr.ReleasePullR
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) PendingReleases(_ context.Context, pendingLabel releasepr.Label) ([]*releasepr.ReleasePullRequest, error) {
|
||||
func (f *Forgejo) PendingReleases(ctx context.Context, pendingLabel releasepr.Label) ([]*releasepr.ReleasePullRequest, error) {
|
||||
fPRs, err := all(func(listOptions forgejo.ListOptions) ([]*forgejo.PullRequest, *forgejo.Response, error) {
|
||||
return f.client.ListRepoPullRequests(
|
||||
f.options.Owner, f.options.Repo,
|
||||
|
|
@ -385,7 +377,6 @@ func (f *Forgejo) PendingReleases(_ context.Context, pendingLabel releasepr.Labe
|
|||
})
|
||||
})
|
||||
if err != nil {
|
||||
// "The target couldn't be found." means that the repo does not have pull requests activated.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -411,7 +402,7 @@ func (f *Forgejo) PendingReleases(_ context.Context, pendingLabel releasepr.Labe
|
|||
return prs, nil
|
||||
}
|
||||
|
||||
func (f *Forgejo) CreateRelease(_ context.Context, commit git.Commit, title, changelog string, preRelease, latest bool) error {
|
||||
func (f *Forgejo) CreateRelease(ctx context.Context, commit git.Commit, title, changelog string, preRelease, latest bool) error {
|
||||
// latest can not be set through the API
|
||||
|
||||
_, _, err := f.client.CreateRelease(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"time"
|
||||
|
|
@ -9,15 +8,11 @@ import (
|
|||
"github.com/lmittmann/tint"
|
||||
)
|
||||
|
||||
func GetLogger(w io.Writer) *slog.Logger {
|
||||
return slog.New(
|
||||
tint.NewHandler(w, &tint.Options{
|
||||
func init() {
|
||||
slog.SetDefault(slog.New(
|
||||
tint.NewHandler(os.Stderr, &tint.Options{
|
||||
Level: slog.LevelDebug,
|
||||
TimeFormat: time.RFC3339,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
slog.SetDefault(GetLogger(os.Stderr))
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TestForge interface {
|
||||
Init(ctx context.Context, runID string) error
|
||||
CreateRepo(t *testing.T, opts CreateRepoOpts) (*Repository, error)
|
||||
|
||||
RunArguments() []string
|
||||
}
|
||||
|
||||
type CreateRepoOpts struct {
|
||||
Name string
|
||||
Description string
|
||||
DefaultBranch string
|
||||
}
|
||||
|
|
@ -8,9 +8,5 @@ services:
|
|||
- data:/data/gitea
|
||||
- ./app.ini:/data/gitea/conf/app.ini:ro
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "localhost:3000/api/healthz"]
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
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)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
//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{}))
|
||||
}
|
||||
147
test/e2e/forgejo/framework.go
Normal file
147
test/e2e/forgejo/framework.go
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
//go:build e2e_forgejo
|
||||
|
||||
package forgejo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2"
|
||||
"github.com/apricote/releaser-pleaser/cmd/rp/cmd"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
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"
|
||||
|
||||
TestDefaultBranch = "main"
|
||||
)
|
||||
|
||||
var (
|
||||
TestToken string
|
||||
TestUserName string
|
||||
TestClient *forgejo.Client
|
||||
)
|
||||
|
||||
func randomSuffix() string {
|
||||
bytes := make([]byte, 4)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hex.EncodeToString(bytes)
|
||||
}
|
||||
|
||||
func setupTestUser(ctx context.Context, suffix string) string {
|
||||
TestUserName = fmt.Sprintf(TestUserNameTemplate, suffix)
|
||||
|
||||
if output, err := exec.CommandContext(ctx,
|
||||
"docker", "compose", "exec", "--user=1000", "forgejo",
|
||||
"forgejo", "admin", "user", "create",
|
||||
"--username", TestUserName,
|
||||
"--password", TestUserPassword,
|
||||
"--email", fmt.Sprintf(TestUserEmailTemplate, suffix),
|
||||
"--must-change-password=false",
|
||||
).CombinedOutput(); err != nil {
|
||||
slog.ErrorContext(ctx, "failed to create forgejo user", "err", err, "output", output)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
token, err := exec.CommandContext(ctx,
|
||||
"docker", "compose", "exec", "--user=1000", "forgejo",
|
||||
"forgejo", "admin", "user", "generate-access-token",
|
||||
"--username", TestUserName,
|
||||
"--token-name", TestTokenName,
|
||||
"--scopes", TestTokenScopes,
|
||||
"--raw",
|
||||
).Output()
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "failed to create forgejo token", "err", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(token))
|
||||
}
|
||||
|
||||
func setupTestClient(ctx context.Context, token string) *forgejo.Client {
|
||||
client, err := forgejo.NewClient(TestAPIURL,
|
||||
forgejo.SetToken(token),
|
||||
forgejo.SetUserAgent("releaser-pleaser-e2e-tests"),
|
||||
forgejo.SetContext(ctx),
|
||||
// forgejo.SetDebugMode(),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func NewRepository(t *testing.T, name string) *Repository {
|
||||
t.Helper()
|
||||
|
||||
r := &Repository{
|
||||
Name: fmt.Sprintf("%s-%s", name, randomSuffix())}
|
||||
|
||||
repo, _, err := TestClient.CreateRepo(forgejo.CreateRepoOption{
|
||||
Name: r.Name,
|
||||
Description: name,
|
||||
DefaultBranch: TestDefaultBranch,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, repo)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func Run(t *testing.T, r *Repository, extraFiles []string) (stdout bytes.Buffer, stderr bytes.Buffer, err error) {
|
||||
t.Helper()
|
||||
|
||||
ctx := t.Context()
|
||||
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
rootCmd.SetArgs([]string{
|
||||
"run", "--forge=forgejo",
|
||||
fmt.Sprintf("--branch=%s", TestDefaultBranch),
|
||||
fmt.Sprintf("--owner=%s", TestUserName),
|
||||
fmt.Sprintf("--repo=%s", r.Name),
|
||||
fmt.Sprintf("--extra-files=%q", strings.Join(extraFiles, "\n")),
|
||||
fmt.Sprintf("--api-url=%s", TestAPIURL),
|
||||
fmt.Sprintf("--api-token=%s", TestToken),
|
||||
fmt.Sprintf("--username=%s", TestUserName),
|
||||
})
|
||||
|
||||
rootCmd.SetOut(&stdout)
|
||||
rootCmd.SetErr(&stderr)
|
||||
|
||||
err = rootCmd.ExecuteContext(ctx)
|
||||
|
||||
return stdout, stderr, err
|
||||
}
|
||||
|
||||
func MustRun(t *testing.T, r *Repository, extraFiles []string) {
|
||||
t.Helper()
|
||||
|
||||
stdout, stderr, err := Run(t, r, extraFiles)
|
||||
if !assert.NoError(t, err) {
|
||||
t.Log(stdout)
|
||||
t.Log(stderr)
|
||||
}
|
||||
}
|
||||
39
test/e2e/forgejo/framework_test.go
Normal file
39
test/e2e/forgejo/framework_test.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//go:build e2e_forgejo
|
||||
|
||||
package forgejo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
ctx := context.Background()
|
||||
|
||||
suffix := randomSuffix()
|
||||
|
||||
TestToken = setupTestUser(ctx, suffix)
|
||||
|
||||
TestClient = setupTestClient(ctx, TestToken)
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestAPIAccess(t *testing.T) {
|
||||
user, _, err := TestClient.GetMyUserInfo()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, user)
|
||||
}
|
||||
|
||||
func TestCreateRepository(t *testing.T) {
|
||||
_ = NewRepository(t, t.Name())
|
||||
}
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
repo := NewRepository(t, t.Name())
|
||||
MustRun(t, repo, []string{})
|
||||
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
package e2e
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/apricote/releaser-pleaser/cmd/rp/cmd"
|
||||
)
|
||||
|
||||
const (
|
||||
TestDefaultBranch = "main"
|
||||
)
|
||||
|
||||
func randomString() string {
|
||||
randomBytes := make([]byte, 4)
|
||||
if _, err := rand.Read(randomBytes); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hex.EncodeToString(randomBytes)
|
||||
}
|
||||
|
||||
type Framework struct {
|
||||
runID string
|
||||
forge TestForge
|
||||
}
|
||||
|
||||
func NewFramework(ctx context.Context, forge TestForge) (*Framework, error) {
|
||||
f := &Framework{
|
||||
runID: randomString(),
|
||||
forge: forge,
|
||||
}
|
||||
|
||||
err := forge.Init(ctx, f.runID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (f *Framework) NewRepository(t *testing.T, name string) *Repository {
|
||||
t.Helper()
|
||||
|
||||
r := &Repository{
|
||||
Name: fmt.Sprintf("%s-%s-%s", name, f.runID, randomString()),
|
||||
}
|
||||
|
||||
repo, err := f.forge.CreateRepo(t, CreateRepoOpts{
|
||||
Name: r.Name,
|
||||
Description: name,
|
||||
DefaultBranch: TestDefaultBranch,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, repo)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (f *Framework) Run(t *testing.T, r *Repository, extraFiles []string) error {
|
||||
t.Helper()
|
||||
|
||||
ctx := t.Context()
|
||||
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
rootCmd.SetArgs(append([]string{
|
||||
"run",
|
||||
fmt.Sprintf("--repo=%s", r.Name),
|
||||
fmt.Sprintf("--extra-files=%q", strings.Join(extraFiles, "\n")),
|
||||
}, f.forge.RunArguments()...))
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
rootCmd.SetOut(&stdout)
|
||||
rootCmd.SetErr(&stderr)
|
||||
|
||||
err := rootCmd.ExecuteContext(ctx)
|
||||
|
||||
stdoutString := stdout.String()
|
||||
stderrString := stderr.String()
|
||||
|
||||
t.Log(stdoutString)
|
||||
t.Log(stderrString)
|
||||
|
||||
return err
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue