Document required forge methods (#6049)

This commit is contained in:
6543
2026-02-03 17:04:24 +01:00
committed by GitHub
parent e9cf3a7988
commit 52cb9f6c21
5 changed files with 36 additions and 6 deletions

View File

@@ -144,7 +144,9 @@ func HandleAuth(c *gin.Context) {
Page: page,
PerPage: perPage,
})
if terr != nil {
if errors.Is(terr, forge_types.ErrNotImplemented) {
log.Debug().Msg("Could not fetch membership of user as forge adapter did not implement it")
} else if terr != nil {
log.Error().Err(terr).Msgf("cannot verify team membership for %s", userFromForge.Login)
c.Redirect(http.StatusSeeOther, server.Config.Server.RootPath+"/login?error=internal_error")
return

View File

@@ -396,7 +396,9 @@ func GetRepoBranches(c *gin.Context) {
forge.Refresh(c, _forge, _store, repoUser)
branches, err := _forge.Branches(c, repoUser, repo, session.Pagination(c))
if err != nil {
if errors.Is(err, forge_types.ErrNotImplemented) {
log.Debug().Msg("Could not fetch repo branch list as forge adapter did not implement it")
} else if err != nil {
log.Error().Err(err).Msg("failed to load branches")
c.String(http.StatusInternalServerError, "failed to load branches: %s", err)
return
@@ -435,7 +437,9 @@ func GetRepoPullRequests(c *gin.Context) {
forge.Refresh(c, _forge, _store, repoUser)
prs, err := _forge.PullRequests(c, repoUser, repo, session.Pagination(c))
if err != nil {
if errors.Is(err, forge_types.ErrNotImplemented) {
log.Debug().Msg("Could not fetch repo pull-request list as forge adapter did not implement it")
} else if err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

View File

@@ -16,12 +16,15 @@ package cache
import (
"context"
"errors"
"fmt"
"time"
"github.com/jellydator/ttlcache/v3"
"github.com/rs/zerolog/log"
"go.woodpecker-ci.org/woodpecker/v3/server/forge"
forge_types "go.woodpecker-ci.org/woodpecker/v3/server/forge/types"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/server/store"
)
@@ -56,7 +59,10 @@ func (c *membershipCache) Get(ctx context.Context, _forge forge.Forge, u *model.
}
perm, err := _forge.OrgMembership(ctx, u, org)
if err != nil {
if errors.Is(err, forge_types.ErrNotImplemented) {
log.Debug().Msg("Could not check user org membership as forge adapter did not implement it")
return &model.OrgPerm{}, nil
} else if err != nil {
return nil, err
}
c.cache.Set(key, perm, c.ttl)

View File

@@ -51,6 +51,7 @@ import (
// Error Handling:
// - types.ErrIgnoreEvent: Skippable webhook events
// - types.RecordNotExist: Resource not found
// - types.ErrNotImplemented: Can be used to signal it's not supported
// - nil Repo/Pipeline: "No action needed" (not an error).
type Forge interface {
// Name returns the unique identifier of this forge driver.
@@ -76,9 +77,11 @@ type Forge interface {
Auth(ctx context.Context, token, secret string) (string, error)
// Teams fetches all team/organization memberships for a user.
// May return empty slice if forge doesn't support teams/organizations.
// Used to determine if an user is member of an team/organization.
// Should support pagination via ListOptions.
//
// Errors:
// - Expect types.ErrNotImplemented to be returned if forge doesn't support teams/organizations.
Teams(ctx context.Context, u *model.User, p *model.ListOptions) ([]*model.Team, error)
// Repo fetches a single repository.
@@ -105,6 +108,9 @@ type Forge interface {
// Dir fetches all files in a directory at a specific commit.
// Supports pipeline configurations split across multiple files.
// Should return files only.
//
// Errors:
// - Expect types.ErrNotImplemented to be returned if not supported by the forge
Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Pipeline, dirName string) ([]*types.FileMeta, error)
// Status sends workflow status updates to the forge.
@@ -128,13 +134,20 @@ type Forge interface {
// Branches returns all branch names in the repository.
// Should support pagination via ListOptions.
//
// Errors:
// - Expect types.ErrNotImplemented to be returned if not supported by the forge
Branches(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]string, error)
// BranchHead returns the latest commit SHA for a branch.
// Is essential for cron feature to work.
BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (*model.Commit, error)
// PullRequests returns all open pull requests.
// Should support pagination via ListOptions.
//
// Errors:
// - Expect types.ErrNotImplemented to be returned if not supported by the forge
PullRequests(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]*model.PullRequest, error)
// Hook parses incoming webhook and returns pipeline data.
@@ -157,6 +170,9 @@ type Forge interface {
// OrgMembership checks if user is member of organization and their permission.
// Should return (Member: false, Admin: false) if not a member.
//
// Errors:
// - Expect types.ErrNotImplemented to be returned if not supported by the forge
OrgMembership(ctx context.Context, u *model.User, org string) (*model.OrgPerm, error)
// Org fetches organization details.

View File

@@ -146,7 +146,9 @@ func (f *forgeFetcherContext) getFirstAvailableConfig(c context.Context, configs
files, err := f.forge.Dir(c, f.user, f.repo, f.pipeline, strings.TrimSuffix(fileOrFolder, "/"))
// if folder is not supported we will get a "Not implemented" error and continue
if err != nil {
if !errors.Is(err, types.ErrNotImplemented) && !errors.Is(err, &types.ErrConfigNotFound{}) {
if errors.Is(err, types.ErrNotImplemented) {
log.Debug().Msg("Could not fetch config folder as forge adapter did not implement it")
} else if !errors.Is(err, &types.ErrConfigNotFound{}) {
log.Error().Err(err).Str("repo", f.repo.FullName).Str("user", f.user.Login).Msgf("could not get folder from forge: %s", err)
forgeErr = append(forgeErr, err)
}