Help us shape the future of Go! Take the 2026 Go Developer Survey

gitoperationslib

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: GPL-3.0 Imports: 8 Imported by: 0

README

gitoperationslib banner

___

gitoperationslib

Go Reference

A Go library for managing git forges through one set of interfaces. Write your code once against gitoperationslib.Client and run it against Forgejo (the primary backend), GitHub or Bitbucket Cloud. Anything a forge cannot do is reported with a typed error. The library never skips part of a request without saying so.

Covered: repositories, branches and tags, branch and tag protection, releases and assets, pull requests and reviews, issues (with labels, milestones and comments), webhooks (managing them, and receiving and verifying deliveries), reading users, organisations and teams with any token (Forgejo and GitHub), and Forgejo administration (managing users, organisations, teams).

Documentation

Document Contents
docs/USAGE.md The full guide: every package, interface, type and option, with examples and per-backend notes
docs/support_grid.md Support level of every feature, per backend
docs/CHANGELOG.md Release history
docs/TODO.md Open items, planned work, and the reasons behind each limitation
pkg.go.dev API reference generated from the source

Installation

go get github.com/jeanfrancoisgratton/gitoperationslib

Requirements:

  • Go 1.27.2 or later.
  • Forgejo 11.0.10 or later. forgejo.New checks the server version and refuses older servers.
  • GitHub: github.com, or GitHub Enterprise Server.
  • Bitbucket: Bitbucket Cloud only. Data Center has a different API.

The module has a single third-party dependency: google/go-github (v93), and only the GitHub backend uses it.

Quick start

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	gol "github.com/jeanfrancoisgratton/gitoperationslib"
	"github.com/jeanfrancoisgratton/gitoperationslib/forgejo"
)

func main() {
	ctx := context.Background()

	client, err := forgejo.New(ctx, "https://git.example.com", forgejo.Token(os.Getenv("FORGEJO_TOKEN")))
	if err != nil {
		log.Fatal(err)
	}

	repo, err := client.Repos().Create(ctx, gol.CreateRepoOptions{
		Owner:      "acme",
		Name:       "widget",
		Visibility: gol.VisibilityPrivate,
		AutoInit:   true,
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("created", repo.FullName, repo.CloneURL)

	// Every page of a list, as a Go iterator.
	for r, err := range gol.All(ctx, gol.ListOptions{PerPage: 50},
		func(ctx context.Context, o gol.ListOptions) (gol.Page[gol.Repo], error) {
			return client.Repos().List(ctx, "acme", o)
		}) {
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(r.FullName)
	}
}

To use another forge, change only the constructor:

client, err := github.New(os.Getenv("GITHUB_TOKEN"))
client, err := bitbucket.New(bitbucket.APIToken(os.Getenv("BITBUCKET_EMAIL"), os.Getenv("BITBUCKET_TOKEN")))

docs/USAGE.md covers every area in detail.

Architecture

gitoperationslib/             interfaces, domain types, errors, pagination  (no backend code)
├── forgejo/                  Forgejo backend      → internal/forgejoapi    (net/http)
├── github/                   GitHub backend       → google/go-github v93 + a small GraphQL client
├── bitbucket/                Bitbucket backend    → internal/bitbucketapi  (net/http)
├── webhook/                  receiving deliveries (depends on the root package only)
└── internal/
    ├── forgejoapi/           Forgejo transport: base URL, auth, pagination, errors, uploads
    ├── bitbucketapi/         Bitbucket transport: REST 2.0, pagination, errors
    ├── partial/              helpers for the Directory info calls (paging, tolerated refusals)
    └── contracttest/         one integration suite every backend must pass
Package Import path Role
root github.com/jeanfrancoisgratton/gitoperationslib Client and the area interfaces, domain types, errors, Page/All, Ptr
forgejo …/gitoperationslib/forgejo Forgejo backend; implements Client, Admin and ExternalAssets
github …/gitoperationslib/github GitHub backend; implements Client
bitbucket …/gitoperationslib/bitbucket Bitbucket Cloud backend; implements Client
webhook …/gitoperationslib/webhook Verifies, identifies and decodes webhook deliveries from all three forges

How a call flows:

  1. A constructor (forgejo.New, github.New, bitbucket.New) returns a concrete *Client that satisfies gitoperationslib.Client.
  2. Client hands out one interface per area: Repos(), Branches(), Tags(), BranchProtections(), TagProtections(), Releases(), PullRequests(), Issues(), Labels(), Milestones(), Webhooks() and Directory() (users, organisations, teams).
  3. The backend converts the library's option structs into the forge's request and calls its API. It then converts the response back into the library's types, so no forge-specific type crosses the boundary.
  4. Error responses become a *gitoperationslib.APIError. Requests the forge cannot honour fail with an error matching gitoperationslib.ErrNotSupported.

The webhook package depends only on the root package, so a service that only receives deliveries does not pull in any backend.

Design choices

  • One interface, several forges. The domain types model what the forges share. Features only some forges have are separate, optional interfaces (Admin, ExternalAssets), so the shared model is not bent around one vendor. Check for them with Capabilities() or a type assertion.
  • Explicit refusals. When a forge cannot do something (a merge method, an option, a whole area), the call returns ErrNotSupported with a *NotSupportedError naming the backend, the operation and the reason. A few calls also return the result along with that error: this happens when the server applied the request but silently ignored part of it, so you can see what actually happened.
  • No third-party types in the public API. Every exported type belongs to this library, and conversion happens inside each backend. A go-github major version bump therefore never breaks callers.
  • Few dependencies. The Forgejo and Bitbucket backends are small hand-written HTTP clients on net/http, not SDKs. The Forgejo SDK was rejected because of its churn, and because its minimum Go version would have become ours (see DESIGN-NOTES.md). Only GitHub uses an SDK (go-github, pinned), plus a minimal GraphQL client for what REST cannot do: draft toggling, auto-merge and issue deletion.
  • Consistent conventions:
    • Every call takes a context.Context.
    • Lists are paginated the same way everywhere (ListOptions, Page[T], All).
    • In Edit…Options, nil means "leave unchanged".
    • Enums are typed (Visibility, MergeMethod, PRState, …), never bare strings or booleans.
    • Webhook event names follow GitHub's and are translated for the other forges.
    • Every public struct has camelCase JSON tags. Fields only some forges report, and zero times, are omitted, and secrets are never serialised. See USAGE §3.7.
  • Safe defaults. A zero-value BranchProtection blocks deletion and force pushes. Deleting, renaming or changing the permissions of an organisation's owner team is refused (ErrOwnerTeam), because Forgejo would otherwise let an organisation lose all its owners. Webhook signatures are compared in constant time.
  • Forgejo first. Forgejo is the reference backend, and its full feature set is exposed, including features GitHub lacks: extra merge methods, file-pattern protection, external release assets, and user, organisation and team administration. The minimum supported version is checked when connecting.
  • Verified against real servers. One contract suite (internal/contracttest) runs against every backend, and it also checks that each backend fails the way its documentation says it should.

Backend differences

The library adapts where it can, and returns ErrNotSupported where it cannot. In summary:

Area Forgejo GitHub Bitbucket Cloud
Repositories ✅ ✅ ✅ owner = workspace
Branches and tags ✅ ✅ ✅ no branch rename
Branch protection ✅ protection rules ✅ rulesets (free plans: public repositories) ✅ branch restrictions
Tag protection ✅ ✅ rulesets ❌
Releases and assets ✅ plus external assets ✅ ❌
Pull requests and reviews ✅ ✅ drafts and auto-merge via GraphQL ✅ no reopening, no auto-merge
Issues, labels, milestones, comments ✅ ✅ ❌ issue tracker retired
Webhooks (repository, organisation/workspace) ✅ ✅ ✅
Receiving deliveries (webhook) ✅ ✅ ⚠️ not yet checked against live deliveries
Reading users, organisations, teams (Directory) ✅ ✅ ⚠️ the authenticated user (Me) only
Managing users, organisations, teams (Admin) ✅ — —

Differences worth knowing before you start:

  • Drafts on Forgejo are pull requests whose title starts with WIP: or [WIP]. Draft: true adds the prefix, and Title comes back with it.
  • GitHub rulesets stand in for both branch and tag protection. On free plans they only work on public repositories, and only teams (not individual users) can be exempted.
  • Bitbucket has no public login names. User fields hold the account's nickname, and inputs accept a nickname, an account ID or a {UUID}.
  • Merge methods: Forgejo has six, GitHub three (merge, squash, rebase) and Bitbucket five.
  • Webhooks: Forgejo silently drops event names it does not know, and the library reports them as an error. Only Forgejo has branch filters and authorization headers.

The full feature-by-feature comparison is in docs/support_grid.md. Per-call notes are in docs/USAGE.md.

Testing

go test -race ./...                    # unit tests: no network, no credentials
go test -tags integration ./...        # contract checks against real forges (see below)

Integration tests skip themselves unless their environment variables are set. They only create and delete resources named gitopslib-it-….

Suite Environment
Forgejo GITOPSLIB_FORGEJO_URL, GITOPSLIB_FORGEJO_TOKEN (scopes: repository, organization, user, issue — read and write), GITOPSLIB_FORGEJO_ORG (a throwaway organisation the token's user owns)
GitHub GITOPSLIB_GITHUB_TOKEN, GITOPSLIB_GITHUB_ORG (an organisation, or the account's own login)
Bitbucket GITOPSLIB_BITBUCKET_TOKEN (Atlassian API token or access token), GITOPSLIB_BITBUCKET_EMAIL (required with an API token), GITOPSLIB_BITBUCKET_WORKSPACE (optional when the token sees a single workspace)
Forgejo admin a disposable local instance (below); non-loopback URLs are refused
scripts/forgejo-testenv.sh start   # Forgejo 15 in Docker on 127.0.0.1:3999, writes .env.testenv
set -a; source .env; source .env.testenv; set +a
go test -tags integration ./...
scripts/forgejo-testenv.sh stop    # removes the container and .env.testenv

The GitHub protection checks briefly create a public repository, because free plans only allow rulesets on public repositories. Running the GitHub suites many times in a row can trigger GitHub's secondary rate limit on repository creation, which blocks new repositories for up to an hour.

License

Copyright (C) 2026 Jean-François Gratton

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file for details.

SPDX-License-Identifier: GPL-3.0-or-later

Documentation

Overview

Package gitoperationslib wraps git forge operations behind a common set of interfaces. Forgejo is the primary backend; GitHub and Bitbucket Cloud are supported where their APIs overlap. Operations a backend cannot perform return an error matching ErrNotSupported.

Create a client with forgejo.New, github.New or bitbucket.New; the webhook sub-package receives and verifies deliveries. See docs/USAGE.md in the repository for the full guide.

Index

Constants

This section is empty.

Variables

AllTeamUnits lists every TeamUnit.

View Source
var ErrNotSupported = errors.New("operation not supported")

ErrNotSupported is matched (via errors.Is) by every error returned when a backend cannot perform an operation, instead of silently degrading.

View Source
var ErrOwnerTeam = errors.New("refusing to delete, rename or change the permissions of an owner team")

ErrOwnerTeam is returned when an operation would delete an organisation's owner team, rename it, or change its permissions. Forgejo allows deleting it, which leaves the organisation without owners.

Functions

func All

func All[T any](ctx context.Context, opts ListOptions, fetch func(context.Context, ListOptions) (Page[T], error)) iter.Seq2[T, error]

All iterates over every item of a paginated list, starting at opts.Page. Iteration stops at the first error, which is yielded with a zero item.

for repo, err := range gitoperationslib.All(ctx, opts, func(ctx context.Context, o gitoperationslib.ListOptions) (gitoperationslib.Page[gitoperationslib.Repo], error) {
	return client.Repos().List(ctx, "owner", o)
}) { ... }

func IsForbidden

func IsForbidden(err error) bool

func IsNotFound

func IsNotFound(err error) bool

func IsUnauthorized

func IsUnauthorized(err error) bool

func NotSupported

func NotSupported(backend Backend, operation, reason string) error

NotSupported returns a *NotSupportedError.

func Ptr

func Ptr[T any](v T) *T

Ptr returns a pointer to v, for filling optional fields.

func StatusCode

func StatusCode(err error) int

StatusCode returns the HTTP status of the first *APIError in err's chain, or 0 if there is none.

Types

type APIError

type APIError struct {
	Backend    Backend `json:"backend"`
	StatusCode int     `json:"statusCode"`
	Message    string  `json:"message"`
	// DocumentationURL is GitHub's documentation_url or Forgejo's url field.
	DocumentationURL string `json:"documentationUrl,omitzero"`
	// Details holds GitHub's errors[] entries, flattened to strings.
	Details []string `json:"details,omitzero"`
}

APIError is the normalised form of an error response from either backend.

func (*APIError) Error

func (e *APIError) Error() string

type Admin

type Admin interface {
	Users() Users
	Orgs() Orgs
	Teams() Teams
}

Admin manages accounts. Only the Forgejo backend implements it; detect it with a type assertion (client.(gitoperationslib.Admin)) or CapAdmin.

type Allowlist

type Allowlist struct {
	Users []string `json:"users"` // logins
	Teams []string `json:"teams"` // team names (GitHub: team slugs; organisations only)
}

Allowlist names users and teams exempt from a restriction. On GitHub, rules are rulesets whose exemptions ("bypass actors") can be teams but not individual users, so Users returns ErrNotSupported there.

type Asset

type Asset struct {
	ID            int64  `json:"id"`
	Name          string `json:"name"`
	Size          int64  `json:"size"`
	ContentType   string `json:"contentType,omitzero"` // reported by GitHub only
	DownloadCount int64  `json:"downloadCount"`
	DownloadURL   string `json:"downloadUrl"` // browser download URL
	// External marks a Forgejo asset that links to a file hosted elsewhere
	// (DownloadURL) instead of an uploaded file.
	External  bool      `json:"external,omitzero"`
	CreatedAt time.Time `json:"createdAt,omitzero"`
}

Asset is a file attached to a release.

type Backend

type Backend string

Backend identifies which forge implementation a Client talks to.

const (
	BackendForgejo Backend = "forgejo"
	BackendGitHub  Backend = "github"
	// BackendBitbucket is Bitbucket Cloud (REST API 2.0).
	BackendBitbucket Backend = "bitbucket"
)

type Branch

type Branch struct {
	Name      string `json:"name"`
	SHA       string `json:"sha"` // head commit
	Protected bool   `json:"protected"`
	IsDefault bool   `json:"isDefault"`
}

Branch is a repository branch.

type BranchProtection

type BranchProtection struct {
	ID int64 `json:"id,omitzero"` // GitHub ruleset ID; 0 on Forgejo
	// Pattern is a branch name or glob ("main", "release/*"). Rules are
	// addressed by it.
	Pattern string `json:"pattern"`

	RequiredApprovals     int  `json:"requiredApprovals"`
	DismissStaleApprovals bool `json:"dismissStaleApprovals"` // a new push dismisses earlier approvals
	// RequiredStatusChecks lists the status check contexts that must pass.
	RequiredStatusChecks []string `json:"requiredStatusChecks"`
	// RequireUpToDate requires the branch to be up to date with the base
	// before merging (GitHub strict checks; Forgejo blocks outdated
	// branches).
	RequireUpToDate      bool `json:"requireUpToDate"`
	RequireSignedCommits bool `json:"requireSignedCommits"`
	// ApplyToAdmins enforces the rule for repository administrators too.
	ApplyToAdmins bool `json:"applyToAdmins"`
	// PushAllowlist restricts direct pushes to the listed users and teams;
	// nil lets anyone with write access push. An empty Allowlist blocks
	// direct pushes entirely (changes then go through pull requests).
	PushAllowlist *Allowlist `json:"pushAllowlist,omitzero"`

	AllowDeletion  bool `json:"allowDeletion"`  // Forgejo: not supported (protected branches cannot be deleted)
	AllowForcePush bool `json:"allowForcePush"` // Forgejo: not supported

	// GitHub only.
	RequireLinearHistory          bool `json:"requireLinearHistory,omitzero"`
	RequireConversationResolution bool `json:"requireConversationResolution,omitzero"`

	// Forgejo only.
	MergeAllowlist                *Allowlist `json:"mergeAllowlist,omitzero"`     // who may merge pull requests; nil: anyone with write access
	ApprovalsAllowlist            *Allowlist `json:"approvalsAllowlist,omitzero"` // whose approvals count; nil: anyone with write access
	BlockOnRejectedReviews        bool       `json:"blockOnRejectedReviews,omitzero"`
	BlockOnOfficialReviewRequests bool       `json:"blockOnOfficialReviewRequests,omitzero"`
	ProtectedFilePatterns         string     `json:"protectedFilePatterns,omitzero"` // semicolon-separated globs
	UnprotectedFilePatterns       string     `json:"unprotectedFilePatterns,omitzero"`
}

BranchProtection is a protection rule for the branches matching Pattern. On GitHub it is a branch ruleset; on Forgejo a branch protection rule.

Zero values are the protected choice: deletion and force pushes are blocked unless explicitly allowed.

type BranchProtections

type BranchProtections interface {
	List(ctx context.Context, owner, repo string) ([]BranchProtection, error)
	Get(ctx context.Context, owner, repo, pattern string) (*BranchProtection, error)
	Create(ctx context.Context, owner, repo string, rule BranchProtection) (*BranchProtection, error)
	Update(ctx context.Context, owner, repo, pattern string, rule BranchProtection) (*BranchProtection, error)
	Delete(ctx context.Context, owner, repo, pattern string) error
}

BranchProtections manages branch protection rules, addressed by pattern. Update replaces a rule entirely: Get it, change it, then Update.

type Branches

type Branches interface {
	// List returns the branches; IsDefault marks the default one.
	List(ctx context.Context, owner, repo string, opts ListOptions) (Page[Branch], error)
	Get(ctx context.Context, owner, repo, name string) (*Branch, error)
	Create(ctx context.Context, owner, repo string, opts CreateBranchOptions) (*Branch, error)
	// Rename renames a branch. Open pull requests and protection rules
	// follow it.
	Rename(ctx context.Context, owner, repo, name, newName string) (*Branch, error)
	Delete(ctx context.Context, owner, repo, name string) error
}

Branches manages repository branches. The default branch is changed with Repos().Edit.

type Capability

type Capability uint64

Capability is a bit set of features a Client supports.

const (
	CapRepos Capability = 1 << iota
	CapMirrors
	CapMigrate
	CapAdmin
	CapWebhooks
	CapSystemWebhooks
	CapReleases
	CapPullRequests
	CapExternalAssets
	CapBranches
	CapTags
	CapBranchProtection
	CapTagProtection
	CapIssues
	CapDirectory
)

func (Capability) Has

func (c Capability) Has(want Capability) bool

Has reports whether c includes every capability in want.

func (Capability) String

func (c Capability) String() string

String lists the named capabilities in c, separated by "|".

type Client

type Client interface {
	Backend() Backend
	Capabilities() Capability
	Repos() Repos
	Releases() Releases
	PullRequests() PullRequests
	Webhooks() Webhooks
	Branches() Branches
	Tags() Tags
	BranchProtections() BranchProtections
	TagProtections() TagProtections
	Issues() Issues
	Labels() Labels
	Milestones() Milestones
	// Directory reads users, organisations and teams (CapDirectory).
	Directory() Directory
}

Client is the entry point to a forge backend.

Areas a backend may not support are exposed through optional interfaces; check Capabilities, or use a type assertion, before relying on them.

type Comment

type Comment struct {
	ID        int64     `json:"id"`
	Author    string    `json:"author"`
	Body      string    `json:"body"`
	HTMLURL   string    `json:"htmlUrl"`
	CreatedAt time.Time `json:"createdAt,omitzero"`
	UpdatedAt time.Time `json:"updatedAt,omitzero"`
}

Comment is a comment on an issue or pull request.

type CreateBranchOptions

type CreateBranchOptions struct {
	Name string `json:"name"` // required
	// From is the branch, tag or commit SHA to start from; empty means the
	// default branch.
	From string `json:"from,omitzero"`
}

CreateBranchOptions describes a branch to create.

type CreateIssueOptions

type CreateIssueOptions struct {
	Title     string   `json:"title"` // required
	Body      string   `json:"body,omitzero"`
	Labels    []string `json:"labels,omitzero"` // names; they must exist
	Assignees []string `json:"assignees,omitzero"`
	Milestone int64    `json:"milestone,omitzero"` // Milestone.ID; 0 for none
}

CreateIssueOptions describes an issue to open.

type CreateMilestoneOptions

type CreateMilestoneOptions struct {
	Title       string    `json:"title"` // required
	Description string    `json:"description,omitzero"`
	DueOn       time.Time `json:"dueOn,omitzero"` // zero: none
}

CreateMilestoneOptions describes a milestone to create.

type CreateOrgOptions

type CreateOrgOptions struct {
	// Owner is the user who will own the organisation. Empty means the
	// authenticated user; another user requires a site-admin token.
	Owner                     string          `json:"owner,omitzero"`
	Name                      string          `json:"name"` // required
	FullName                  string          `json:"fullName,omitzero"`
	Description               string          `json:"description,omitzero"`
	Website                   string          `json:"website,omitzero"`
	Location                  string          `json:"location,omitzero"`
	Email                     string          `json:"email,omitzero"`
	Visibility                OwnerVisibility `json:"visibility,omitzero"` // zero value: backend default
	RepoAdminChangeTeamAccess bool            `json:"repoAdminChangeTeamAccess,omitzero"`
}

CreateOrgOptions describes an organisation to create.

type CreatePROptions

type CreatePROptions struct {
	Title string `json:"title"` // required
	Body  string `json:"body,omitzero"`
	Head  string `json:"head"` // branch with the changes; "user:branch" for a fork
	Base  string `json:"base"` // branch to merge into
	// Draft opens the pull request as a draft. On Forgejo this adds the
	// "WIP: " prefix to Title unless it already has a draft prefix.
	Draft               bool  `json:"draft,omitzero"`
	AllowMaintainerEdit *bool `json:"allowMaintainerEdit,omitzero"` // let base maintainers push to the head branch
}

CreatePROptions describes a pull request to open.

type CreateReleaseOptions

type CreateReleaseOptions struct {
	TagName         string `json:"tagName"` // required
	TargetCommitish string `json:"targetCommitish,omitzero"`
	Name            string `json:"name,omitzero"`
	Body            string `json:"body,omitzero"`
	Draft           bool   `json:"draft,omitzero"`
	Prerelease      bool   `json:"prerelease,omitzero"`

	// GenerateReleaseNotes asks the server to write the notes from merged
	// pull requests (GitHub only).
	GenerateReleaseNotes bool `json:"generateReleaseNotes,omitzero"`
	// MakeLatest controls whether the release becomes the "latest" one;
	// nil means the server decides (GitHub only).
	MakeLatest *bool `json:"makeLatest,omitzero"`
	// HideArchiveLinks hides the generated source archives (Forgejo only).
	HideArchiveLinks *bool `json:"hideArchiveLinks,omitzero"`
}

CreateReleaseOptions describes a release to create.

If TagName does not exist yet, it is created from TargetCommitish (the default branch when empty). For a draft, both backends create the tag only when the draft is published.

type CreateRepoOptions

type CreateRepoOptions struct {
	// Owner is the user or organisation that will own the repository; the
	// backend determines which. Empty means the authenticated user. Naming a
	// user other than the authenticated one requires an admin token (Forgejo)
	// and is not supported on GitHub.
	Owner         string     `json:"owner,omitzero"`
	Name          string     `json:"name"`
	Description   string     `json:"description,omitzero"`
	Visibility    Visibility `json:"visibility,omitzero"` // zero value: backend default
	DefaultBranch string     `json:"defaultBranch,omitzero"`
	Template      bool       `json:"template,omitzero"`
	// AutoInit creates an initial commit, using Gitignores and License if set.
	AutoInit bool `json:"autoInit,omitzero"`
	// Gitignores lists gitignore template names. GitHub accepts at most one
	// and returns ErrNotSupported otherwise.
	Gitignores []string `json:"gitignores,omitzero"`
	License    string   `json:"license,omitzero"` // license template name
}

CreateRepoOptions describes a repository to create.

type CreateReviewOptions

type CreateReviewOptions struct {
	Event    ReviewEvent `json:"event"`             // required
	Body     string      `json:"body,omitzero"`     // required for request_changes and comment
	CommitID string      `json:"commitId,omitzero"` // empty: the current head
}

CreateReviewOptions submits a review. Authors cannot approve or request changes on their own pull requests.

type CreateTagOptions

type CreateTagOptions struct {
	Name string `json:"name"` // required
	// Target is the branch, tag or commit SHA to tag; empty means the
	// default branch.
	Target string `json:"target,omitzero"`
	// Message makes an annotated tag; empty makes a lightweight tag.
	Message string `json:"message,omitzero"`
}

CreateTagOptions describes a tag to create. To publish a release for a tag, use Releases().Create, which also creates the tag when needed.

type CreateTeamOptions

type CreateTeamOptions struct {
	Name             string     `json:"name"` // required
	Description      string     `json:"description,omitzero"`
	Access           TeamAccess `json:"access"` // required
	IncludesAllRepos bool       `json:"includesAllRepos,omitzero"`
	CanCreateOrgRepo bool       `json:"canCreateOrgRepo,omitzero"`
}

CreateTeamOptions describes a team to create.

type CreateUserOptions

type CreateUserOptions struct {
	Login    string `json:"login"` // required
	Email    string `json:"email"` // required
	Password string `json:"-"`
	FullName string `json:"fullName,omitzero"`
	// MustChangePassword forces a password change at first sign-in.
	// Nil means the Forgejo default, which is true.
	MustChangePassword *bool           `json:"mustChangePassword,omitzero"`
	Visibility         OwnerVisibility `json:"visibility,omitzero"` // zero value: backend default
	Restricted         bool            `json:"restricted,omitzero"`
	// SendNotify emails the user about the new account.
	SendNotify bool `json:"sendNotify,omitzero"`
}

CreateUserOptions describes a user account to create.

type CreateWebhookOptions

type CreateWebhookOptions struct {
	URL         string          `json:"url"`                  // required
	ContentType HookContentType `json:"contentType,omitzero"` // zero value: json
	// Secret signs deliveries (see the webhook package). Strongly
	// recommended.
	Secret string      `json:"-"`
	Events []HookEvent `json:"events"`          // required
	Active *bool       `json:"active,omitzero"` // nil: active
	// BranchFilter limits push and branch events to matching branches, as a
	// glob such as "{main,release/*}" (Forgejo only).
	BranchFilter string `json:"branchFilter,omitzero"`
	// AuthorizationHeader is sent with every delivery (Forgejo only).
	AuthorizationHeader string `json:"-"`
}

CreateWebhookOptions describes a webhook to create.

type CurrentUser added in v0.2.1

type CurrentUser struct {
	User
	// LoginName is the name used to sign in on an external authentication
	// source (LDAP, OAuth…), and AuthSourceID that source; 0 for a local
	// account. Forgejo only.
	LoginName    string `json:"loginName,omitzero"`
	AuthSourceID int64  `json:"authSourceId,omitzero"`
	UUID         string `json:"uuid,omitzero"`      // Bitbucket only
	AccountID    string `json:"accountId,omitzero"` // Atlassian account ID; Bitbucket only
	// TwoFactorAuth reports whether two-factor authentication is enabled;
	// nil when the backend does not tell. GitHub and Bitbucket only.
	TwoFactorAuth *bool `json:"twoFactorAuth,omitzero"`
	// Type is the account type ("User", "Bot"…); GitHub only.
	Type              string    `json:"type,omitzero"`
	Plan              string    `json:"plan,omitzero"`              // GitHub only
	Hireable          bool      `json:"hireable,omitzero"`          // GitHub only
	TwitterUsername   string    `json:"twitterUsername,omitzero"`   // GitHub only
	PublicRepos       int       `json:"publicRepos,omitzero"`       // GitHub only
	TotalPrivateRepos int64     `json:"totalPrivateRepos,omitzero"` // GitHub only
	OwnedPrivateRepos int64     `json:"ownedPrivateRepos,omitzero"` // GitHub only
	PublicGists       int       `json:"publicGists,omitzero"`       // GitHub only
	PrivateGists      int       `json:"privateGists,omitzero"`      // GitHub only
	DiskUsage         int       `json:"diskUsage,omitzero"`         // in KiB; GitHub only
	Collaborators     int       `json:"collaborators,omitzero"`     // GitHub only
	UpdatedAt         time.Time `json:"updatedAt,omitzero"`         // GitHub only
	// Settings are the account preferences; Forgejo only.
	Settings *UserSettings `json:"settings,omitzero"`

	Emails []Email `json:"emails"`
	Orgs   []Org   `json:"orgs"` // organisations the user belongs to, private memberships included
	Teams  []Team  `json:"teams"`
	// Repos are the repositories the user owns or reaches as a collaborator
	// or organisation member, private ones included.
	Repos   []Repo   `json:"repos"`
	SSHKeys []SSHKey `json:"sshKeys"`
	GPGKeys []GPGKey `json:"gpgKeys"`
	// Incomplete is nil when every part was read; see UserInfo.Incomplete.
	// A token lacking a scope (GitHub's user:email, read:public_key…)
	// leaves the matching part empty and recorded here.
	Incomplete error       `json:"-"`
	Missing    []PartError `json:"missing,omitzero"` // see UserInfo.Missing
}

CurrentUser is the authenticated user, as returned by Directory.Me. Fields a backend does not report are left empty.

type DeleteUserOptions

type DeleteUserOptions struct {
	// Purge also deletes the user's repositories, organisation memberships
	// and other content. Without it, deleting a user who still owns
	// repositories fails.
	Purge bool `json:"purge,omitzero"`
}

DeleteUserOptions controls user deletion.

type Directory added in v0.2.0

type Directory interface {
	// Me returns the authenticated user as the credentials identify it, with
	// everything the token may read about the account: private profile
	// fields, e-mail addresses, memberships, repositories and keys. It is
	// the only Directory method Bitbucket implements.
	Me(ctx context.Context) (*CurrentUser, error)
	// User returns a user account. Fields the server hides from the caller
	// (e-mail, admin flags, last login…) are left empty.
	User(ctx context.Context, login string) (*User, error)
	// UserInfo returns a user with the organisations they belong to and the
	// repositories they own, as far as the caller can see them.
	UserInfo(ctx context.Context, login string) (*UserInfo, error)

	Org(ctx context.Context, name string) (*Org, error)
	// ListOrgs returns the organisations user belongs to; empty user means
	// the authenticated user (whose private memberships are included).
	ListOrgs(ctx context.Context, user string, opts ListOptions) (Page[Org], error)
	// ListAllOrgs returns every organisation visible to the caller. On
	// GitHub, NextPage is an opaque cursor rather than a page number: pass it
	// back unchanged (All does).
	ListAllOrgs(ctx context.Context, opts ListOptions) (Page[Org], error)
	// OrgInfo returns an organisation with its teams, members and
	// repositories, as far as the caller can see them.
	OrgInfo(ctx context.Context, name string) (*OrgInfo, error)
	// OrgMembers lists an organisation's members. Callers outside the
	// organisation see its public members only.
	OrgMembers(ctx context.Context, org string, opts ListOptions) (Page[User], error)

	// ListTeams lists an organisation's teams. Forgejo shows them to
	// organisation members only; GitHub hides secret teams from non-members.
	ListTeams(ctx context.Context, org string, opts ListOptions) (Page[Team], error)
	// Team returns the team of org called name (case-insensitive on
	// Forgejo; the slug on GitHub).
	Team(ctx context.Context, org, name string) (*Team, error)
	// TeamInfo returns a team with its members and repositories.
	TeamInfo(ctx context.Context, org, name string) (*TeamInfo, error)
	TeamMembers(ctx context.Context, org, name string, opts ListOptions) (Page[User], error)
	TeamRepos(ctx context.Context, org, name string, opts ListOptions) (Page[Repo], error)
}

Directory reads users, organisations and teams, with whatever rights the token has: a site admin sees everything, other users see what they could see in the web interface. Forgejo and GitHub implement it (CapDirectory); Bitbucket implements Me only and returns ErrNotSupported elsewhere.

Teams are addressed by organisation and name (GitHub: the team slug), the only addressing both forges share. Account management (creating, editing, deleting) is in Admin.

type EditAssetOptions

type EditAssetOptions struct {
	Name *string `json:"name,omitzero"`
}

EditAssetOptions changes an asset. Nil fields are left unchanged.

type EditIssueOptions

type EditIssueOptions struct {
	Title     *string     `json:"title,omitzero"`
	Body      *string     `json:"body,omitzero"`
	State     *IssueState `json:"state,omitzero"` // close or reopen
	Labels    *[]string   `json:"labels,omitzero"`
	Assignees *[]string   `json:"assignees,omitzero"`
	Milestone *int64      `json:"milestone,omitzero"` // 0 removes the milestone
}

EditIssueOptions changes an issue. Nil fields are left unchanged; non-nil slices replace the current values (an empty slice clears them).

type EditLabelOptions

type EditLabelOptions struct {
	Name        *string `json:"name,omitzero"` // renames the label
	Color       *string `json:"color,omitzero"`
	Description *string `json:"description,omitzero"`
}

EditLabelOptions changes a label. Nil fields are left unchanged.

type EditMilestoneOptions

type EditMilestoneOptions struct {
	Title       *string         `json:"title,omitzero"`
	Description *string         `json:"description,omitzero"`
	State       *MilestoneState `json:"state,omitzero"` // close or reopen
	DueOn       *time.Time      `json:"dueOn,omitzero"`
}

EditMilestoneOptions changes a milestone. Nil fields are left unchanged.

type EditOrgOptions

type EditOrgOptions struct {
	FullName                  *string          `json:"fullName,omitzero"`
	Description               *string          `json:"description,omitzero"`
	Website                   *string          `json:"website,omitzero"`
	Location                  *string          `json:"location,omitzero"`
	Email                     *string          `json:"email,omitzero"`
	Visibility                *OwnerVisibility `json:"visibility,omitzero"`
	RepoAdminChangeTeamAccess *bool            `json:"repoAdminChangeTeamAccess,omitzero"`
}

EditOrgOptions changes an organisation. Nil fields are left unchanged.

type EditPROptions

type EditPROptions struct {
	Title *string `json:"title,omitzero"`
	Body  *string `json:"body,omitzero"`
	Base  *string `json:"base,omitzero"`
	// State closes (PRStateClosed) or reopens (PRStateOpen) the pull request.
	State *PRState `json:"state,omitzero"`
	// Draft converts to or from a draft. Forgejo adds or removes the title
	// prefix; GitHub uses its GraphQL API.
	Draft               *bool `json:"draft,omitzero"`
	AllowMaintainerEdit *bool `json:"allowMaintainerEdit,omitzero"`
}

EditPROptions changes a pull request. Nil fields are left unchanged.

type EditReleaseOptions

type EditReleaseOptions struct {
	TagName         *string `json:"tagName,omitzero"`
	TargetCommitish *string `json:"targetCommitish,omitzero"`
	Name            *string `json:"name,omitzero"`
	Body            *string `json:"body,omitzero"`
	Draft           *bool   `json:"draft,omitzero"`
	Prerelease      *bool   `json:"prerelease,omitzero"`

	MakeLatest       *bool `json:"makeLatest,omitzero"`       // GitHub only
	HideArchiveLinks *bool `json:"hideArchiveLinks,omitzero"` // Forgejo only
}

EditReleaseOptions changes a release. Nil fields are left unchanged. Setting Draft to false publishes a draft.

type EditRepoOptions

type EditRepoOptions struct {
	Name          *string     `json:"name,omitzero"`
	Description   *string     `json:"description,omitzero"`
	Website       *string     `json:"website,omitzero"`
	Visibility    *Visibility `json:"visibility,omitzero"`
	DefaultBranch *string     `json:"defaultBranch,omitzero"`
	Archived      *bool       `json:"archived,omitzero"`
	Template      *bool       `json:"template,omitzero"`
}

EditRepoOptions changes repository settings. Nil fields are left unchanged; use Ptr to set a value.

type EditTeamOptions

type EditTeamOptions struct {
	Name             *string     `json:"name,omitzero"`
	Description      *string     `json:"description,omitzero"`
	Access           *TeamAccess `json:"access,omitzero"`
	IncludesAllRepos *bool       `json:"includesAllRepos,omitzero"`
	CanCreateOrgRepo *bool       `json:"canCreateOrgRepo,omitzero"`
}

EditTeamOptions changes a team. Nil fields are left unchanged.

type EditUserOptions

type EditUserOptions struct {
	Email                   *string          `json:"email,omitzero"`
	FullName                *string          `json:"fullName,omitzero"`
	Description             *string          `json:"description,omitzero"`
	Website                 *string          `json:"website,omitzero"`
	Location                *string          `json:"location,omitzero"`
	Password                *string          `json:"-"`
	MustChangePassword      *bool            `json:"mustChangePassword,omitzero"`
	Visibility              *OwnerVisibility `json:"visibility,omitzero"`
	Admin                   *bool            `json:"admin,omitzero"`
	Active                  *bool            `json:"active,omitzero"`
	ProhibitLogin           *bool            `json:"prohibitLogin,omitzero"`
	Restricted              *bool            `json:"restricted,omitzero"`
	AllowCreateOrganization *bool            `json:"allowCreateOrganization,omitzero"`
	MaxRepoCreation         *int             `json:"maxRepoCreation,omitzero"` // -1 means the instance default
}

EditUserOptions changes a user account. Nil fields are left unchanged.

type EditWebhookOptions

type EditWebhookOptions struct {
	URL                 *string          `json:"url,omitzero"`
	ContentType         *HookContentType `json:"contentType,omitzero"`
	Secret              *string          `json:"-"`
	Events              []HookEvent      `json:"events,omitzero"`
	Active              *bool            `json:"active,omitzero"`
	BranchFilter        *string          `json:"branchFilter,omitzero"` // Forgejo only
	AuthorizationHeader *string          `json:"-"`                     // Forgejo only
}

EditWebhookOptions changes a webhook. Nil fields are left unchanged; a non-nil Events replaces the subscription list.

type Email added in v0.2.1

type Email struct {
	Address  string `json:"address"`
	Primary  bool   `json:"primary"`
	Verified bool   `json:"verified"`
	// Visibility is "public" or "private"; GitHub only, and only for the
	// primary address.
	Visibility string `json:"visibility,omitzero"`
}

Email is one of the authenticated user's e-mail addresses.

type ExternalAssets

type ExternalAssets interface {
	AddExternalAsset(ctx context.Context, owner, repo string, releaseID int64, name, url string) (*Asset, error)
}

ExternalAssets adds release assets that link to files hosted elsewhere. Only the Forgejo backend implements it (CapExternalAssets), on the value returned by Releases():

ext, ok := client.Releases().(gitoperationslib.ExternalAssets)

type GPGKey added in v0.2.1

type GPGKey struct {
	ID                int64         `json:"id"`
	KeyID             string        `json:"keyId"`
	PublicKey         string        `json:"publicKey"`
	Emails            []GPGKeyEmail `json:"emails"`
	Subkeys           []GPGKey      `json:"subkeys,omitzero"`
	CanSign           bool          `json:"canSign"`
	CanEncryptComms   bool          `json:"canEncryptComms"`
	CanEncryptStorage bool          `json:"canEncryptStorage"`
	CanCertify        bool          `json:"canCertify"`
	Verified          bool          `json:"verified,omitzero"` // Forgejo only
	CreatedAt         time.Time     `json:"createdAt,omitzero"`
	ExpiresAt         time.Time     `json:"expiresAt,omitzero"` // zero if the key does not expire
}

GPGKey is a GPG key of the authenticated user.

type GPGKeyEmail added in v0.2.1

type GPGKeyEmail struct {
	Address  string `json:"address"`
	Verified bool   `json:"verified"`
}

GPGKeyEmail is an e-mail address bound to a GPG key.

type HookContentType

type HookContentType string

HookContentType is the encoding of webhook payloads.

const (
	HookContentJSON HookContentType = "json"
	HookContentForm HookContentType = "form" // payload=<json>, URL-encoded
)

type HookEvent

type HookEvent string

HookEvent is an event a webhook subscribes to. The constants use GitHub's names and are translated for Forgejo; other values are passed to the server unchanged, for backend-specific events.

const (
	HookEventPush              HookEvent = "push"
	HookEventCreate            HookEvent = "create" // branch or tag created
	HookEventDelete            HookEvent = "delete" // branch or tag deleted
	HookEventFork              HookEvent = "fork"
	HookEventRelease           HookEvent = "release"
	HookEventIssues            HookEvent = "issues"
	HookEventIssueComment      HookEvent = "issue_comment"
	HookEventPullRequest       HookEvent = "pull_request"
	HookEventPullRequestReview HookEvent = "pull_request_review"
	HookEventRepository        HookEvent = "repository"
	HookEventWiki              HookEvent = "wiki" // GitHub: gollum
)

type HookScope

type HookScope struct {
	Owner string `json:"owner"`
	Repo  string `json:"repo,omitzero"`
}

HookScope selects where webhooks live: a repository, or an organisation when Repo is empty.

func OrgHooks

func OrgHooks(org string) HookScope

OrgHooks is the scope of an organisation's webhooks.

func RepoHooks

func RepoHooks(owner, repo string) HookScope

RepoHooks is the scope of a repository's webhooks.

type Issue

type Issue struct {
	Number    int        `json:"number"`
	Title     string     `json:"title"`
	Body      string     `json:"body"`
	State     IssueState `json:"state"`
	Author    string     `json:"author"`
	Labels    []string   `json:"labels"`    // names
	Assignees []string   `json:"assignees"` // logins
	Milestone *Milestone `json:"milestone,omitzero"`
	Comments  int        `json:"comments"`
	Locked    bool       `json:"locked"`
	HTMLURL   string     `json:"htmlUrl"`
	CreatedAt time.Time  `json:"createdAt,omitzero"`
	UpdatedAt time.Time  `json:"updatedAt,omitzero"`
	ClosedAt  time.Time  `json:"closedAt,omitzero"`
}

Issue is an issue. Issues and pull requests share one number sequence; label, assignee and milestone methods also work on pull requests.

type IssueState

type IssueState string

IssueState is the state of an issue. IssueStateAll is only meaningful as a List filter.

const (
	IssueStateOpen   IssueState = "open"
	IssueStateClosed IssueState = "closed"
	IssueStateAll    IssueState = "all"
)

type Issues

type Issues interface {
	List(ctx context.Context, owner, repo string, opts ListIssuesOptions) (Page[Issue], error)
	Get(ctx context.Context, owner, repo string, number int) (*Issue, error)
	Create(ctx context.Context, owner, repo string, opts CreateIssueOptions) (*Issue, error)
	Edit(ctx context.Context, owner, repo string, number int, opts EditIssueOptions) (*Issue, error)
	// Delete removes an issue permanently (repository admins only; GitHub
	// through GraphQL).
	Delete(ctx context.Context, owner, repo string, number int) error

	AddLabels(ctx context.Context, owner, repo string, number int, labels []string) error
	RemoveLabel(ctx context.Context, owner, repo string, number int, label string) error

	ListComments(ctx context.Context, owner, repo string, number int, opts ListOptions) (Page[Comment], error)
	CreateComment(ctx context.Context, owner, repo string, number int, body string) (*Comment, error)
	EditComment(ctx context.Context, owner, repo string, id int64, body string) (*Comment, error)
	DeleteComment(ctx context.Context, owner, repo string, id int64) error
}

Issues manages issues and their comments. Label and comment methods also accept pull request numbers.

type Label

type Label struct {
	ID          int64  `json:"id"`
	Name        string `json:"name"`
	Color       string `json:"color"` // six hex digits, lower case, without "#"
	Description string `json:"description"`
}

Label is a repository label.

type Labels

type Labels interface {
	List(ctx context.Context, owner, repo string, opts ListOptions) (Page[Label], error)
	Get(ctx context.Context, owner, repo, name string) (*Label, error)
	Create(ctx context.Context, owner, repo string, label Label) (*Label, error)
	Edit(ctx context.Context, owner, repo, name string, opts EditLabelOptions) (*Label, error)
	Delete(ctx context.Context, owner, repo, name string) error
}

Labels manages repository labels, addressed by name.

type ListIssuesOptions

type ListIssuesOptions struct {
	ListOptions
	State  IssueState `json:"state,omitzero"`  // zero value: open
	Labels []string   `json:"labels,omitzero"` // issues carrying all these labels
}

ListIssuesOptions selects issues to list. Pull requests are never included.

type ListOptions

type ListOptions struct {
	Page    int `json:"page,omitzero"` // 1-based
	PerPage int `json:"perPage,omitzero"`
}

ListOptions selects one page of a list call. Zero values mean "first page" and "backend default page size".

type ListPROptions

type ListPROptions struct {
	ListOptions
	State PRState `json:"state,omitzero"` // zero value: open
}

ListPROptions selects pull requests to list.

type MergeMethod

type MergeMethod string

MergeMethod is the strategy used to merge a pull request. Values match Forgejo's "Do" field; the GitHub backend supports only MergeMethodMerge, MergeMethodSquash and MergeMethodRebase.

MergeMethodRebase replays the commits without a merge commit; MergeMethodRebaseMerge rebases and then adds a merge commit; MergeMethodManuallyMerged only marks a pull request whose commits are already in the base branch as merged.

const (
	MergeMethodMerge           MergeMethod = "merge"
	MergeMethodRebase          MergeMethod = "rebase"
	MergeMethodRebaseMerge     MergeMethod = "rebase-merge"
	MergeMethodSquash          MergeMethod = "squash"
	MergeMethodFastForwardOnly MergeMethod = "fast-forward-only"
	MergeMethodManuallyMerged  MergeMethod = "manually-merged"
)

func (MergeMethod) Valid

func (m MergeMethod) Valid() bool

Valid reports whether m is one of the named merge methods.

type MergeOptions

type MergeOptions struct {
	// Method defaults to MergeMethodMerge. GitHub supports only merge,
	// squash and rebase.
	Method  MergeMethod `json:"method,omitzero"`
	Title   string      `json:"title,omitzero"`   // merge or squash commit title; empty: server default
	Message string      `json:"message,omitzero"` // commit message body; empty: server default
	// HeadSHA makes the merge fail unless the head branch is still at this
	// commit.
	HeadSHA string `json:"headSha,omitzero"`
	// DeleteBranch deletes the head branch after a successful merge.
	DeleteBranch bool `json:"deleteBranch,omitzero"`
	// WhenChecksSucceed schedules the merge for when status checks pass;
	// cancel it with CancelAutoMerge. GitHub (through GraphQL) accepts it
	// only in repositories that allow auto-merge, while the pull request
	// still waits for a required check, and not together with DeleteBranch.
	WhenChecksSucceed bool `json:"whenChecksSucceed,omitzero"`
}

MergeOptions controls a merge.

type Milestone

type Milestone struct {
	// ID addresses the milestone: Forgejo's ID, GitHub's milestone number.
	ID           int64          `json:"id"`
	Title        string         `json:"title"`
	Description  string         `json:"description"`
	State        MilestoneState `json:"state"`
	DueOn        time.Time      `json:"dueOn,omitzero"` // zero if none
	OpenIssues   int            `json:"openIssues"`
	ClosedIssues int            `json:"closedIssues"`
	ClosedAt     time.Time      `json:"closedAt,omitzero"`
}

Milestone is a repository milestone.

type MilestoneState

type MilestoneState string

MilestoneState is the state of a milestone; MilestoneStateAll is only meaningful as a List filter.

const (
	MilestoneStateOpen   MilestoneState = "open"
	MilestoneStateClosed MilestoneState = "closed"
	MilestoneStateAll    MilestoneState = "all"
)

type Milestones

type Milestones interface {
	List(ctx context.Context, owner, repo string, state MilestoneState, opts ListOptions) (Page[Milestone], error)
	Get(ctx context.Context, owner, repo string, id int64) (*Milestone, error)
	Create(ctx context.Context, owner, repo string, opts CreateMilestoneOptions) (*Milestone, error)
	Edit(ctx context.Context, owner, repo string, id int64, opts EditMilestoneOptions) (*Milestone, error)
	Delete(ctx context.Context, owner, repo string, id int64) error
}

Milestones manages repository milestones, addressed by Milestone.ID.

type NotSupportedError

type NotSupportedError struct {
	Backend   Backend `json:"backend"`
	Operation string  `json:"operation"`
	Reason    string  `json:"reason,omitzero"` // optional
}

NotSupportedError describes which operation a backend refused.

func (*NotSupportedError) Error

func (e *NotSupportedError) Error() string

func (*NotSupportedError) Is

func (e *NotSupportedError) Is(target error) bool

type Org

type Org struct {
	ID          int64           `json:"id"`
	Name        string          `json:"name"`
	FullName    string          `json:"fullName"`
	Description string          `json:"description"`
	Website     string          `json:"website"`
	Location    string          `json:"location"`
	Email       string          `json:"email"`
	Visibility  OwnerVisibility `json:"visibility"`
	AvatarURL   string          `json:"avatarUrl"`
	HTMLURL     string          `json:"htmlUrl,omitzero"` // GitHub only
	// RepoAdminChangeTeamAccess lets repository admins change team access.
	RepoAdminChangeTeamAccess bool `json:"repoAdminChangeTeamAccess,omitzero"`
}

Org is an organisation.

type OrgInfo added in v0.2.0

type OrgInfo struct {
	Org
	Teams   []Team `json:"teams"`
	Members []User `json:"members"` // non-members only see public members
	Repos   []Repo `json:"repos"`
	// Incomplete is nil when every part was read; see UserInfo.Incomplete.
	Incomplete error       `json:"-"`
	Missing    []PartError `json:"missing,omitzero"` // see UserInfo.Missing
}

OrgInfo is an organisation with the teams, members and repositories the caller can see.

type Orgs

type Orgs interface {
	Get(ctx context.Context, name string) (*Org, error)
	// List returns the organisations user belongs to. Empty user means the
	// authenticated user.
	List(ctx context.Context, user string, opts ListOptions) (Page[Org], error)
	// ListAll returns every organisation visible to the authenticated user
	// (all of them for a site admin).
	ListAll(ctx context.Context, opts ListOptions) (Page[Org], error)
	Create(ctx context.Context, opts CreateOrgOptions) (*Org, error)
	Edit(ctx context.Context, name string, opts EditOrgOptions) (*Org, error)
	// Rename changes an organisation's name. The old name keeps redirecting
	// to the new one.
	Rename(ctx context.Context, name, newName string) error
	// Delete removes an organisation. It fails while the organisation still
	// owns repositories.
	Delete(ctx context.Context, name string) error

	Members(ctx context.Context, org string, opts ListOptions) (Page[User], error)
	// IsMember reports whether user belongs to org. A user that does not
	// exist is reported as not a member.
	IsMember(ctx context.Context, org, user string) (bool, error)
	// RemoveMember removes user from org and all its teams. Removing the last
	// owner fails.
	RemoveMember(ctx context.Context, org, user string) error
}

Orgs manages organisations and their membership. Members join an organisation through its teams; there is no direct "add member".

type OwnerVisibility

type OwnerVisibility string

OwnerVisibility is the visibility of a user or organisation profile. The zero value means "use the backend default" in option structs.

const (
	OwnerVisibilityPublic OwnerVisibility = "public"
	// OwnerVisibilityLimited is visible to signed-in users only.
	OwnerVisibilityLimited OwnerVisibility = "limited"
	OwnerVisibilityPrivate OwnerVisibility = "private"
)

func (OwnerVisibility) Valid

func (v OwnerVisibility) Valid() bool

Valid reports whether v is one of the named owner visibilities.

type PRBranch

type PRBranch struct {
	Ref  string `json:"ref"` // branch name
	SHA  string `json:"sha"`
	Repo string `json:"repo"` // "owner/name"; differs from the base repository for forks
}

PRBranch is one side of a pull request.

type PRState

type PRState string

PRState is the state of a pull request. PRStateAll is only meaningful as a List filter.

const (
	PRStateOpen   PRState = "open"
	PRStateClosed PRState = "closed" // includes merged pull requests
	PRStateAll    PRState = "all"
)

type Page

type Page[T any] struct {
	Items []T `json:"items"`
	// NextPage is the page number to request next, or 0 if this is the last page.
	NextPage int `json:"nextPage"`
}

Page is one page of results.

type PartError added in v0.3.0

type PartError struct {
	Part    string `json:"part"`            // "organisations", "teams", "e-mail addresses"…
	Status  int    `json:"status,omitzero"` // HTTP status of the refusal; 0 when the backend cannot read the part
	Message string `json:"message"`
}

PartError is a part of an info call that could not be read.

type PullRequest

type PullRequest struct {
	Number int `json:"number"`
	// Title is returned as the server stores it. On Forgejo a draft is a
	// title starting with a work-in-progress prefix ("WIP:" or "[WIP]" by
	// default), which therefore appears in Title.
	Title  string   `json:"title"`
	Body   string   `json:"body"`
	State  PRState  `json:"state"`
	Draft  bool     `json:"draft"`
	Author string   `json:"author"`
	Head   PRBranch `json:"head"`
	Base   PRBranch `json:"base"`
	// Mergeable is nil while the server has not computed it yet (GitHub
	// computes it in the background).
	Mergeable      *bool     `json:"mergeable,omitzero"`
	Merged         bool      `json:"merged"`
	MergedBy       string    `json:"mergedBy,omitzero"`
	MergedAt       time.Time `json:"mergedAt,omitzero"`
	MergeCommitSHA string    `json:"mergeCommitSha,omitzero"`
	HTMLURL        string    `json:"htmlUrl"`
	CreatedAt      time.Time `json:"createdAt,omitzero"`
	UpdatedAt      time.Time `json:"updatedAt,omitzero"`
	ClosedAt       time.Time `json:"closedAt,omitzero"`
}

PullRequest is a pull request.

type PullRequests

type PullRequests interface {
	List(ctx context.Context, owner, repo string, opts ListPROptions) (Page[PullRequest], error)
	Get(ctx context.Context, owner, repo string, number int) (*PullRequest, error)
	// Create opens a pull request. If the server does not honour Draft
	// (Forgejo with custom work-in-progress prefixes), the pull request is
	// returned together with an error matching ErrNotSupported.
	Create(ctx context.Context, owner, repo string, opts CreatePROptions) (*PullRequest, error)
	// Edit changes a pull request; see EditPROptions. A Draft change the
	// server does not honour is reported as in Create.
	Edit(ctx context.Context, owner, repo string, number int, opts EditPROptions) (*PullRequest, error)
	// Merge merges a pull request. Drafts cannot be merged. With
	// MergeOptions.WhenChecksSucceed the merge is scheduled instead.
	Merge(ctx context.Context, owner, repo string, number int, opts MergeOptions) error
	// CancelAutoMerge cancels a merge scheduled with WhenChecksSucceed.
	CancelAutoMerge(ctx context.Context, owner, repo string, number int) error
	IsMerged(ctx context.Context, owner, repo string, number int) (bool, error)

	RequestReviewers(ctx context.Context, owner, repo string, number int, users, teams []string) error
	RemoveReviewers(ctx context.Context, owner, repo string, number int, users, teams []string) error
	ListReviews(ctx context.Context, owner, repo string, number int, opts ListOptions) (Page[Review], error)
	CreateReview(ctx context.Context, owner, repo string, number int, opts CreateReviewOptions) (*Review, error)
}

PullRequests manages pull requests and their reviews.

type Release

type Release struct {
	ID              int64     `json:"id"`
	TagName         string    `json:"tagName"`
	TargetCommitish string    `json:"targetCommitish"` // branch or commit the tag is created from
	Name            string    `json:"name"`            // title
	Body            string    `json:"body"`            // notes, Markdown
	Draft           bool      `json:"draft"`
	Prerelease      bool      `json:"prerelease"`
	Author          string    `json:"author"` // login
	HTMLURL         string    `json:"htmlUrl"`
	TarballURL      string    `json:"tarballUrl"` // source archives generated by the forge
	ZipballURL      string    `json:"zipballUrl"`
	CreatedAt       time.Time `json:"createdAt,omitzero"`
	PublishedAt     time.Time `json:"publishedAt,omitzero"` // zero for drafts
	Assets          []Asset   `json:"assets"`
}

Release is a named, tagged point in a repository's history, with notes and attached files (assets).

type Releases

type Releases interface {
	List(ctx context.Context, owner, repo string, opts ListOptions) (Page[Release], error)
	Get(ctx context.Context, owner, repo string, id int64) (*Release, error)
	GetByTag(ctx context.Context, owner, repo, tag string) (*Release, error)
	// Latest returns the most recent published release that is not a
	// prerelease.
	Latest(ctx context.Context, owner, repo string) (*Release, error)
	Create(ctx context.Context, owner, repo string, opts CreateReleaseOptions) (*Release, error)
	Edit(ctx context.Context, owner, repo string, id int64, opts EditReleaseOptions) (*Release, error)
	// Delete removes a release. Its tag is kept.
	Delete(ctx context.Context, owner, repo string, id int64) error

	ListAssets(ctx context.Context, owner, repo string, releaseID int64, opts ListOptions) (Page[Asset], error)
	GetAsset(ctx context.Context, owner, repo string, releaseID, assetID int64) (*Asset, error)
	// UploadAsset streams size bytes from r as a new asset called name.
	// size must be exact. An empty contentType is guessed from the name's
	// extension, falling back to application/octet-stream.
	UploadAsset(ctx context.Context, owner, repo string, releaseID int64, name string, r io.Reader, size int64, contentType string) (*Asset, error)
	EditAsset(ctx context.Context, owner, repo string, releaseID, assetID int64, opts EditAssetOptions) (*Asset, error)
	DeleteAsset(ctx context.Context, owner, repo string, releaseID, assetID int64) error
	// DownloadAsset streams an uploaded asset's content; the caller must
	// close it. External assets are not downloaded: fetch their DownloadURL.
	DownloadAsset(ctx context.Context, owner, repo string, releaseID, assetID int64) (io.ReadCloser, error)
}

Releases manages releases and their assets.

Asset methods take the release ID as well as the asset ID: Forgejo needs both, GitHub ignores the release ID.

type Repo

type Repo struct {
	ID            int64      `json:"id"`
	Owner         string     `json:"owner"`
	Name          string     `json:"name"`
	FullName      string     `json:"fullName"` // "owner/name"
	Description   string     `json:"description"`
	Website       string     `json:"website"` // Forgejo "website", GitHub "homepage"
	Visibility    Visibility `json:"visibility"`
	DefaultBranch string     `json:"defaultBranch"`
	Fork          bool       `json:"fork"`
	Mirror        bool       `json:"mirror"`
	Archived      bool       `json:"archived"`
	Template      bool       `json:"template"`
	Empty         bool       `json:"empty,omitzero"` // not reported by GitHub (always false there)
	HTMLURL       string     `json:"htmlUrl"`
	CloneURL      string     `json:"cloneUrl"`
	SSHURL        string     `json:"sshUrl"`
	CreatedAt     time.Time  `json:"createdAt,omitzero"`
	UpdatedAt     time.Time  `json:"updatedAt,omitzero"`
}

Repo is a repository, modelled on the fields the forges share.

type Repos

type Repos interface {
	Get(ctx context.Context, owner, name string) (*Repo, error)
	// List returns repositories owned by owner (a user or organisation).
	// Empty owner lists every repository the authenticated user can access,
	// including those of organisations they belong to.
	List(ctx context.Context, owner string, opts ListOptions) (Page[Repo], error)
	Create(ctx context.Context, opts CreateRepoOptions) (*Repo, error)
	Edit(ctx context.Context, owner, name string, opts EditRepoOptions) (*Repo, error)
	Delete(ctx context.Context, owner, name string) error
}

Repos manages repositories.

type Review

type Review struct {
	ID          int64       `json:"id"`
	Reviewer    string      `json:"reviewer"`
	State       ReviewState `json:"state"`
	Body        string      `json:"body"`
	CommitID    string      `json:"commitId"`
	HTMLURL     string      `json:"htmlUrl"`
	SubmittedAt time.Time   `json:"submittedAt,omitzero"`
}

Review is a pull request review.

type ReviewEvent

type ReviewEvent string

ReviewEvent is the verdict submitted with a review.

const (
	ReviewEventApprove        ReviewEvent = "approve"
	ReviewEventRequestChanges ReviewEvent = "request_changes"
	ReviewEventComment        ReviewEvent = "comment"
)

type ReviewState

type ReviewState string

ReviewState is the outcome of a review.

const (
	ReviewApproved         ReviewState = "approved"
	ReviewChangesRequested ReviewState = "changes_requested"
	ReviewCommented        ReviewState = "commented"
	ReviewPending          ReviewState = "pending"   // started, not submitted
	ReviewDismissed        ReviewState = "dismissed" // GitHub
	ReviewRequested        ReviewState = "requested" // Forgejo: review requested, not given
)

type SSHKey added in v0.2.1

type SSHKey struct {
	ID          int64     `json:"id,omitzero"` // 0 on Bitbucket
	Title       string    `json:"title"`
	Key         string    `json:"key"`
	Fingerprint string    `json:"fingerprint,omitzero"` // not reported by GitHub
	ReadOnly    bool      `json:"readOnly,omitzero"`    // Forgejo and GitHub only
	CreatedAt   time.Time `json:"createdAt,omitzero"`
	LastUsed    time.Time `json:"lastUsed,omitzero"` // GitHub and Bitbucket only; zero if never used
}

SSHKey is a public SSH key of the authenticated user.

type Tag

type Tag struct {
	Name string `json:"name"`
	SHA  string `json:"sha"` // commit the tag points to (annotated tags are peeled)
	// Message is the annotation of an annotated tag; empty for lightweight
	// tags. GitHub reports it from Get only, not from List.
	Message    string `json:"message,omitzero"`
	TarballURL string `json:"tarballUrl"`
	ZipballURL string `json:"zipballUrl"`
}

Tag is a repository tag.

type TagProtection

type TagProtection struct {
	ID        int64     `json:"id"`
	Pattern   string    `json:"pattern"`
	Allowlist Allowlist `json:"allowlist"`
}

TagProtection restricts creating, updating and deleting the tags matching Pattern ("v*") to the users and teams in Allowlist. On GitHub it is a tag ruleset, and an empty Allowlist blocks everyone, administrators included. Forgejo requires at least one allowed user or team.

type TagProtections

type TagProtections interface {
	List(ctx context.Context, owner, repo string) ([]TagProtection, error)
	Get(ctx context.Context, owner, repo, pattern string) (*TagProtection, error)
	Create(ctx context.Context, owner, repo string, rule TagProtection) (*TagProtection, error)
	Update(ctx context.Context, owner, repo, pattern string, rule TagProtection) (*TagProtection, error)
	Delete(ctx context.Context, owner, repo, pattern string) error
}

TagProtections manages tag protection rules, addressed by pattern.

type Tags

type Tags interface {
	List(ctx context.Context, owner, repo string, opts ListOptions) (Page[Tag], error)
	Get(ctx context.Context, owner, repo, name string) (*Tag, error)
	Create(ctx context.Context, owner, repo string, opts CreateTagOptions) (*Tag, error)
	Delete(ctx context.Context, owner, repo, name string) error
}

Tags manages repository tags. Releases are managed with Releases().

type Team

type Team struct {
	ID   int64  `json:"id"`
	Org  string `json:"org"`
	Name string `json:"name"`
	// Slug is the URL-safe name GitHub addresses teams by; on Forgejo it is
	// the name.
	Slug        string `json:"slug"`
	Description string `json:"description"`
	// Permission is the overall level: admin or owner when the team has
	// that level on every unit, otherwise derived by the server from Units.
	Permission TeamPermission              `json:"permission"`
	Units      map[TeamUnit]TeamPermission `json:"units,omitzero"`
	// IncludesAllRepos gives the team access to every repository of the
	// organisation, current and future.
	IncludesAllRepos bool `json:"includesAllRepos,omitzero"`
	CanCreateOrgRepo bool `json:"canCreateOrgRepo,omitzero"`
}

Team is a team within an organisation.

type TeamAccess

type TeamAccess struct {
	Permission TeamPermission              `json:"permission,omitzero"`
	Units      map[TeamUnit]TeamPermission `json:"units,omitzero"`
}

TeamAccess sets a team's permissions. Exactly one form applies:

  • Permission admin: admin on every unit; Units must be empty.
  • Units set: per-unit permissions (none, read or write); Permission must be empty.
  • Permission read or write with no Units: that level on every unit.

type TeamInfo added in v0.2.0

type TeamInfo struct {
	Team
	Members []User `json:"members"`
	Repos   []Repo `json:"repos"`
	// Incomplete is nil when every part was read; see UserInfo.Incomplete.
	Incomplete error       `json:"-"`
	Missing    []PartError `json:"missing,omitzero"` // see UserInfo.Missing
}

TeamInfo is a team with its members and repositories.

type TeamPermission

type TeamPermission string

TeamPermission is a team's access level, overall or for one unit.

const (
	TeamPermissionNone  TeamPermission = "none"
	TeamPermissionRead  TeamPermission = "read"
	TeamPermissionWrite TeamPermission = "write"
	TeamPermissionAdmin TeamPermission = "admin"
	// TeamPermissionOwner is reported for an organisation's owner team; it
	// cannot be assigned.
	TeamPermissionOwner TeamPermission = "owner"
)

type TeamUnit

type TeamUnit string

TeamUnit is a repository feature a team can be granted access to.

const (
	TeamUnitCode           TeamUnit = "repo.code"
	TeamUnitIssues         TeamUnit = "repo.issues"
	TeamUnitExternalIssues TeamUnit = "repo.ext_issues"
	TeamUnitWiki           TeamUnit = "repo.wiki"
	TeamUnitExternalWiki   TeamUnit = "repo.ext_wiki"
	TeamUnitPulls          TeamUnit = "repo.pulls"
	TeamUnitReleases       TeamUnit = "repo.releases"
	TeamUnitProjects       TeamUnit = "repo.projects"
	TeamUnitPackages       TeamUnit = "repo.packages"
	TeamUnitActions        TeamUnit = "repo.actions"
)

type Teams

type Teams interface {
	List(ctx context.Context, org string, opts ListOptions) (Page[Team], error)
	Get(ctx context.Context, id int64) (*Team, error)
	// GetByName returns the team of org with exactly that name
	// (case-insensitive), or a 404 *APIError.
	GetByName(ctx context.Context, org, name string) (*Team, error)
	Create(ctx context.Context, org string, opts CreateTeamOptions) (*Team, error)
	// Edit changes a team. Renaming the owner team or changing its access
	// returns ErrOwnerTeam.
	Edit(ctx context.Context, id int64, opts EditTeamOptions) (*Team, error)
	// Delete removes a team. Deleting the owner team returns ErrOwnerTeam.
	Delete(ctx context.Context, id int64) error

	Members(ctx context.Context, id int64, opts ListOptions) (Page[User], error)
	IsMember(ctx context.Context, id int64, user string) (bool, error)
	// AddMember adds user to the team, which also makes them a member of
	// the organisation.
	AddMember(ctx context.Context, id int64, user string) error
	RemoveMember(ctx context.Context, id int64, user string) error

	Repos(ctx context.Context, id int64, opts ListOptions) (Page[Repo], error)
	AddRepo(ctx context.Context, id int64, owner, repo string) error
	RemoveRepo(ctx context.Context, id int64, owner, repo string) error
}

Teams manages an organisation's teams, their members and repositories. Teams are addressed by ID; use GetByName to look one up.

type UnsupportedVersionError

type UnsupportedVersionError struct {
	Backend Backend `json:"backend"`
	Version string  `json:"version"`
	Minimum string  `json:"minimum"`
}

UnsupportedVersionError is returned when a server is older than the minimum version the library supports.

func (*UnsupportedVersionError) Error

func (e *UnsupportedVersionError) Error() string

type User

type User struct {
	ID            int64           `json:"id"`
	Login         string          `json:"login"`
	FullName      string          `json:"fullName"`
	Email         string          `json:"email"`
	Description   string          `json:"description"`
	Website       string          `json:"website"`
	Location      string          `json:"location"`
	Visibility    OwnerVisibility `json:"visibility"`
	IsAdmin       bool            `json:"isAdmin"`
	Active        bool            `json:"active"`
	Restricted    bool            `json:"restricted,omitzero"`
	ProhibitLogin bool            `json:"prohibitLogin,omitzero"`
	HTMLURL       string          `json:"htmlUrl"`
	AvatarURL     string          `json:"avatarUrl"`
	Company       string          `json:"company,omitzero"`  // GitHub only
	Pronouns      string          `json:"pronouns,omitzero"` // Forgejo only
	Language      string          `json:"language,omitzero"` // interface language; Forgejo only
	Followers     int             `json:"followers"`
	Following     int             `json:"following"`
	StarredRepos  int             `json:"starredRepos,omitzero"` // Forgejo only
	CreatedAt     time.Time       `json:"createdAt,omitzero"`
	LastLogin     time.Time       `json:"lastLogin,omitzero"` // zero if the user never signed in
}

User is a user account.

type UserInfo added in v0.2.0

type UserInfo struct {
	User
	Orgs  []Org  `json:"orgs"`  // organisations the user belongs to
	Repos []Repo `json:"repos"` // repositories the user owns
	// Incomplete is nil when every part was read. Otherwise it describes the
	// parts the server refused (401, 403, 404) or the backend cannot list
	// (ErrNotSupported); those fields are left empty. It is not serialised:
	// Missing carries the same information as data.
	Incomplete error `json:"-"`
	// Missing lists the parts recorded in Incomplete, one entry each.
	Missing []PartError `json:"missing,omitzero"`
}

UserInfo is a user with the organisations and repositories the caller can see.

type UserSettings added in v0.2.1

type UserSettings struct {
	Theme               string `json:"theme"`
	DiffViewStyle       string `json:"diffViewStyle"` // "unified" or "split"
	HideEmail           bool   `json:"hideEmail"`
	HideActivity        bool   `json:"hideActivity"`
	HidePronouns        bool   `json:"hidePronouns"`
	EnableRepoUnitHints bool   `json:"enableRepoUnitHints"`
}

UserSettings are a Forgejo user's account preferences.

type Users

type Users interface {
	Get(ctx context.Context, login string) (*User, error)
	List(ctx context.Context, opts ListOptions) (Page[User], error)
	Create(ctx context.Context, opts CreateUserOptions) (*User, error)
	// Edit applies opts. If the server ignores a visibility change (Forgejo
	// 15.0.x cannot switch a user back to public), Edit returns the updated
	// user together with an error matching ErrNotSupported.
	Edit(ctx context.Context, login string, opts EditUserOptions) (*User, error)
	// Rename changes a user's login. The old login keeps redirecting to the
	// new one, so Get(oldLogin) returns the renamed user.
	Rename(ctx context.Context, login, newLogin string) error
	Delete(ctx context.Context, login string, opts DeleteUserOptions) error
}

Users manages user accounts. All methods except Get require a site-admin token.

type Visibility

type Visibility string

Visibility is the visibility of a repository. The zero value means "use the backend default" in option structs.

const (
	VisibilityPublic  Visibility = "public"
	VisibilityPrivate Visibility = "private"
	// VisibilityInternal is visible to all members of a GitHub enterprise.
	// Forgejo and Bitbucket repositories only have a private flag, so those
	// backends return ErrNotSupported for it.
	VisibilityInternal Visibility = "internal"
)

func (Visibility) Valid

func (v Visibility) Valid() bool

Valid reports whether v is one of the named visibilities.

type Webhook

type Webhook struct {
	ID          int64           `json:"id"`
	URL         string          `json:"url"`
	ContentType HookContentType `json:"contentType"`
	// Events lists the subscribed events. Forgejo may add finer-grained
	// events implied by the requested ones (e.g. issue_assign with issues);
	// those keep Forgejo's names.
	Events       []HookEvent `json:"events"`
	Active       bool        `json:"active"`
	BranchFilter string      `json:"branchFilter,omitzero"` // Forgejo only
	CreatedAt    time.Time   `json:"createdAt,omitzero"`
	UpdatedAt    time.Time   `json:"updatedAt,omitzero"`
}

Webhook is a configured webhook. The secret is never returned.

type Webhooks

type Webhooks interface {
	List(ctx context.Context, scope HookScope, opts ListOptions) (Page[Webhook], error)
	Get(ctx context.Context, scope HookScope, id int64) (*Webhook, error)
	// Create adds a webhook. Forgejo silently drops event names it does not
	// know; Create then returns the webhook together with an error.
	Create(ctx context.Context, scope HookScope, opts CreateWebhookOptions) (*Webhook, error)
	// Edit changes a webhook; dropped events are reported as in Create.
	Edit(ctx context.Context, scope HookScope, id int64, opts EditWebhookOptions) (*Webhook, error)
	Delete(ctx context.Context, scope HookScope, id int64) error
	// Ping asks the server to send a test delivery: a "ping" event on
	// GitHub, a "push" of the latest commit on Forgejo (repositories only).
	Ping(ctx context.Context, scope HookScope, id int64) error
}

Webhooks manages repository and organisation webhooks. Receiving and verifying deliveries is done by the webhook sub-package.

Directories

Path Synopsis
Package bitbucket is the Bitbucket Cloud backend (REST API 2.0).
Package bitbucket is the Bitbucket Cloud backend (REST API 2.0).
Package forgejo is the Forgejo backend.
Package forgejo is the Forgejo backend.
Package github is the GitHub backend, built on google/go-github.
Package github is the GitHub backend, built on google/go-github.
internal
bitbucketapi
Package bitbucketapi is the HTTP transport for the Bitbucket Cloud backend (REST API 2.0).
Package bitbucketapi is the HTTP transport for the Bitbucket Cloud backend (REST API 2.0).
contracttest
Package contracttest holds behaviour checks shared by every backend's integration tests, so all backends are held to the same contract.
Package contracttest holds behaviour checks shared by every backend's integration tests, so all backends are held to the same contract.
forgejoapi
Package forgejoapi is the HTTP transport for the Forgejo backend.
Package forgejoapi is the HTTP transport for the Forgejo backend.
partial
Package partial helps backends build Directory info results from several reads, keeping the parts the caller may not see out of the result instead of failing the whole call.
Package partial helps backends build Directory info results from several reads, keeping the parts the caller may not see out of the result instead of failing the whole call.
Package webhook receives webhook deliveries from Forgejo, GitHub and Bitbucket Cloud: it verifies their signature, identifies the forge and event, and decodes the common payloads.
Package webhook receives webhook deliveries from Forgejo, GitHub and Bitbucket Cloud: it verifies their signature, identifies the forge and event, and decodes the common payloads.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL