autoupdate

package
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Dec 3, 2024 License: AGPL-3.0 Imports: 26 Imported by: 0

Documentation

Overview

Package autoupdate provides a merge queue for GitHub.

Index

Constants

View Source
const DefStaleTimeout = 3 * time.Hour

DefStaleTimeout is the default stale timeout. A pull request is considered as stale, when it is the first element in the queue it's state has not changed for longer then this timeout.

Variables

View Source
var (
	ErrAlreadyExists = errors.New("already exist")
	ErrNotFound      = errors.New("not found")
)

Functions

This section is empty.

Types

type Autoupdater

type Autoupdater struct {
	*Config
	// contains filtered or unexported fields
}

Autoupdater implements processing webhook events, querying the GitHub API and enqueueing/dequeuing/triggering updating pull requests with the base-branch. Pull request branch updates are serialized per base-branch.

func NewAutoupdater

func NewAutoupdater(cfg Config) *Autoupdater

NewAutoupdater creates an Autoupdater instance. Only webhook events for repositories listed in monitoredRepositories are processed. At least one trigger (triggerOnAutomerge or a label in triggerLabels) must be provided to trigger enqueuing pull requests for autoupdates via webhook events. When multiple event triggers are configured, the autoupdater reacts on each received Event individually. headLabel is the name of the GitHub label that is applied to the PR that is the first in the queue.

func (*Autoupdater) ChangeBaseBranch

func (a *Autoupdater) ChangeBaseBranch(
	ctx context.Context,
	oldBaseBranch, newBaseBranch *BaseBranch,
	prNumber int,
) error

ChangeBaseBranch dequeues a Pull Request from the queue oldBaseBranch and enqueues it at the queue for newBaseBranch.

func (*Autoupdater) Dequeue

func (a *Autoupdater) Dequeue(_ context.Context, baseBranch *BaseBranch, prNumber int) (*PullRequest, error)

Dequeue removes the pull request with number prNumber from the autoupdate queue of baseBranch. This disables keeping the pull request update with baseBranch. If no pull request is queued with prNumber a ErrNotFound error is returned.

If the pull request was the only element in the baseBranch queue, the queue is removed.

func (*Autoupdater) Enqueue

func (a *Autoupdater) Enqueue(_ context.Context, baseBranch *BaseBranch, pr *PullRequest) error

Enqueue appends the pull request to the autoupdate queue for baseBranch. When it becomes the first element in the queue, it will be kept uptodate with it's baseBranch. If the pr is already enqueued a ErrAlreadyExists error is returned.

If no queue for the baseBranch exist, it will be created.

func (*Autoupdater) HTTPService

func (a *Autoupdater) HTTPService() *HTTPService

func (*Autoupdater) InitSync

func (a *Autoupdater) InitSync(ctx context.Context) error

InitSync does an initial synchronization of the autoupdater queues with the pull request state at GitHub. This is intended to be run before Autoupdater is started. Pull request information is queried from github. If a PR meets a condition to be enqueued for auto-updates it is enqueued. If it meets a condition for not being autoupdated, it is dequeued. If a PR has the [a.headLabel] set it is removed.

func (*Autoupdater) Resume

func (a *Autoupdater) Resume(_ context.Context, baseBranch *BaseBranch, prNumber int) error

Resume resumes updates for a pull request. If the pull request is not queued for updates and in suspended state ErrNotFound is returned.

func (*Autoupdater) ResumeIfStatusPositive

func (a *Autoupdater) ResumeIfStatusPositive(ctx context.Context, owner, repo string, branchNames []string)

ResumeIfStatusPositive calls ScheduleResumePRIfStatusPositive for all queued PRs of the passed branchNames.

func (*Autoupdater) SetPRStaleSinceIfNewer

func (a *Autoupdater) SetPRStaleSinceIfNewer(
	_ context.Context,
	baseBranch *BaseBranch,
	prNumber int,
	updatedAt time.Time,
) error

SetPRStaleSinceIfNewer sets the staleSince timestamp of the PR to updatedAt, if it is newer then the current staleSince timestamp. If the PR is not queued for autoupdates, ErrNotFound is returned.

func (*Autoupdater) SetPRStaleSinceIfNewerByBranch

func (a *Autoupdater) SetPRStaleSinceIfNewerByBranch(
	_ context.Context,
	owner, repo string,
	branchNames []string,
	updatedAt time.Time,
) (notFound []string)

SetPRStaleSinceIfNewerByBranch sets the staleSince timestamp of the PRs for the given branch names to updatdAt, if it is newer then the current staleSince timestamp. The method returns a list of branch names for that no queued PR could be found.

func (*Autoupdater) Start

func (a *Autoupdater) Start()

Start starts the event-loop in a go-routine. The event-loop reads events from the eventChan and processes them.

func (*Autoupdater) Stop

func (a *Autoupdater) Stop()

Stop stops the event-loop and waits until it terminates. All queues will be deleted, operations that are in progress will be canceled.

func (*Autoupdater) TriggerUpdateIfFirst

func (a *Autoupdater) TriggerUpdateIfFirst(
	ctx context.Context,
	baseBranch *BaseBranch,
	prSpec PRSpecifier,
	task Task,
) (*PullRequest, error)

TriggerUpdateIfFirst schedules the update operation for the first pull request in the queue if it matches prSpec. If an update was triggered, the PullRequest is returned. If the first PR does not match prSpec, ErrNotFound is returned.

func (*Autoupdater) TriggerUpdateIfFirstAllQueues

func (a *Autoupdater) TriggerUpdateIfFirstAllQueues(
	ctx context.Context,
	repoOwner string,
	repo string,
	prSpec PRSpecifier,
) (*PullRequest, error)

TriggerUpdateIfFirstAllQueues does the same then _triggerUpdateIfFirst but does not require to specify the base branch name.

type BaseBranch

type BaseBranch struct {
	BranchID
	Logfields []zap.Field
}

BaseBranch represents a base branch of a pull request

func NewBaseBranch

func NewBaseBranch(owner, repo, branch string) (*BaseBranch, error)

func (*BaseBranch) String

func (b *BaseBranch) String() string

type BranchID

type BranchID struct {
	RepositoryOwner string
	Repository      string
	Branch          string
}

BranchID identifies a github branch uniquely

func (*BranchID) String

func (b *BranchID) String() string

type CI added in v0.2.0

type CI struct {
	Client CIClient
	Jobs   []*jenkins.JobTemplate
	// contains filtered or unexported fields
}

func (*CI) RunAll added in v0.2.0

func (c *CI) RunAll(ctx context.Context, retryer Retryer, pr *PullRequest) error

type CIClient added in v0.2.0

type CIClient interface {
	fmt.Stringer
	Build(context.Context, *jenkins.Job) error
}

type Config added in v0.2.0

type Config struct {
	Logger *zap.Logger

	GitHubClient          GithubClient
	CI                    *CI
	EventChan             <-chan *github_prov.Event
	Retryer               Retryer
	MonitoredRepositories map[Repository]struct{}
	TriggerOnAutomerge    bool
	TriggerLabels         set.Set[string]
	HeadLabel             string
	// When DryRun is enabled all GitHub API operation that could result in
	// a change will be simulated and always succeed.
	DryRun bool
}

type DryCIClient added in v0.2.0

type DryCIClient struct {
	// contains filtered or unexported fields
}

func NewDryCIClient added in v0.2.0

func NewDryCIClient(logger *zap.Logger) *DryCIClient

func (*DryCIClient) Build added in v0.2.0

func (c *DryCIClient) Build(_ context.Context, job *jenkins.Job) error

func (*DryCIClient) String added in v0.2.0

func (c *DryCIClient) String() string

type DryGithubClient

type DryGithubClient struct {
	// contains filtered or unexported fields
}

DryGithubClient is a github-client that does not do any changes on github. All operations that could cause a change are simulated and always succeed. All all other operations are forwarded to a wrapped GithubClient.

func NewDryGithubClient

func NewDryGithubClient(clt GithubClient, logger *zap.Logger) *DryGithubClient

func (*DryGithubClient) AddLabel

func (*DryGithubClient) CreateIssueComment

func (c *DryGithubClient) CreateIssueComment(context.Context, string, string, int, string) error

func (*DryGithubClient) ListPullRequests

func (c *DryGithubClient) ListPullRequests(ctx context.Context, owner, repo, state, sort, sortDirection string) githubclt.PRIterator

func (*DryGithubClient) ReadyForMerge

func (*DryGithubClient) RemoveLabel

func (*DryGithubClient) UpdateBranch

type GithubClient

type GithubClient interface {
	UpdateBranch(ctx context.Context, owner, repo string, pullRequestNumber int) (*githubclt.UpdateBranchResult, error)
	CreateIssueComment(ctx context.Context, owner, repo string, issueOrPRNr int, comment string) error
	ListPullRequests(ctx context.Context, owner, repo, state, sort, sortDirection string) githubclt.PRIterator
	ReadyForMerge(ctx context.Context, owner, repo string, prNumber int) (*githubclt.ReadyForMergeStatus, error)
	RemoveLabel(ctx context.Context, owner, repo string, pullRequestOrIssueNumber int, label string) error
	AddLabel(ctx context.Context, owner, repo string, pullRequestOrIssueNumber int, label string) error
}

GithubClient defines the methods of a GithubAPI Client that are used by the autoupdate implementation.

type HTTPService

type HTTPService struct {
	// contains filtered or unexported fields
}

func NewHTTPService

func NewHTTPService(autoupdater *Autoupdater) *HTTPService

func (*HTTPService) HandlerListFunc

func (h *HTTPService) HandlerListFunc(respWr http.ResponseWriter, _ *http.Request)

func (*HTTPService) HandlerStaticFiles

func (h *HTTPService) HandlerStaticFiles() http.Handler

func (*HTTPService) RegisterHandlers

func (h *HTTPService) RegisterHandlers(mux *http.ServeMux, endpoint string)

type PRBranch

type PRBranch struct {
	BranchName string
}

func (*PRBranch) LogField

func (p *PRBranch) LogField() zap.Field

func (*PRBranch) String

func (p *PRBranch) String() string

func (*PRBranch) Type

func (p *PRBranch) Type() PRSpecifierType

type PRNumber

type PRNumber struct {
	Number int
}

func (*PRNumber) LogField

func (p *PRNumber) LogField() zap.Field

func (*PRNumber) String

func (p *PRNumber) String() string

func (*PRNumber) Type

func (p *PRNumber) Type() PRSpecifierType

type PRSpecifier

type PRSpecifier interface {
	Type() PRSpecifierType
	String() string
	LogField() zap.Field
}

type PRSpecifierType

type PRSpecifierType uint8
const (
	PRSpecifierTypeUndefined PRSpecifierType = iota
	PullRequestNumber
	PullRequestBranch
)

type PullRequest

type PullRequest struct {
	Number    int
	Branch    string
	Author    string
	Title     string
	Link      string
	LogFields []zap.Field

	EnqueuedSince time.Time
	// contains filtered or unexported fields
}

func NewPullRequest

func NewPullRequest(nr int, branch, author, title, link string) (*PullRequest, error)

func NewPullRequestFromEvent

func NewPullRequestFromEvent(ev *github.PullRequest) (*PullRequest, error)

func (*PullRequest) Equal

func (p *PullRequest) Equal(other *PullRequest) bool

Equal returns true if p and other are of type PullRequest and its Number field contains the same value.

func (*PullRequest) GetStateUnchangedSince

func (p *PullRequest) GetStateUnchangedSince() time.Time

func (*PullRequest) SetStateUnchangedSince

func (p *PullRequest) SetStateUnchangedSince(t time.Time)

func (*PullRequest) SetStateUnchangedSinceIfNewer

func (p *PullRequest) SetStateUnchangedSinceIfNewer(t time.Time)

func (*PullRequest) SetStateUnchangedSinceIfZero

func (p *PullRequest) SetStateUnchangedSinceIfZero(t time.Time)

type Repository

type Repository struct {
	OwnerLogin     string
	RepositoryName string
}

Repository is a datastructure that uniquely identifies a GitHub Repository.

func (*Repository) String

func (r *Repository) String() string

type Retryer

type Retryer interface {
	Run(context.Context, func(context.Context) error, []zap.Field) error
}

Retryer defines methods for running GithubClient operations repeately if they fail with a temporary error.

type Task added in v0.2.0

type Task uint8
const (
	TaskNone Task = iota
	TaskTriggerCI
)

Directories

Path Synopsis
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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