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

circleciapp

package
v8.162.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package circleciapp sets a repository up on a CircleCI GitHub App pipeline, as the person running devctl: a pipeline definition reading .circleci/config.yml through the CircleCI GitHub App, an all-pushes trigger on it, and optionally the OAuth pipeline's triggers deleted.

CircleCI has no service accounts, so the writes are the person's, with their devctl CircleCI login (granted Write). Afterwards nobody is load-bearing: checkout, events and statuses go through the App's installation, and the pipeline keeps building when its creator leaves. That is what an OAuth follow cannot do, whose builds run through the follower's GitHub grant.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefinitionName

func DefinitionName(repo string) string

DefinitionName is the name of the GitHub App pipeline Ensure creates, <repository>-app: what the CircleCI UI suggests, and what the pipelines set up by hand on 2026-10-22 and 2026-11-02 are named.

func IsNoConfig

func IsNoConfig(err error) bool

IsNoConfig asserts noConfigError: the repository's default branch carries no CircleCI configuration.

func IsProjectNotFound

func IsProjectNotFound(err error) bool

IsProjectNotFound asserts projectNotFoundError: CircleCI knows no project for the repository.

func OpenAsPerson

func OpenAsPerson(ctx context.Context, owner string, warn func(string)) (GitHub, CircleCI, error)

OpenAsPerson builds the two clients Setup takes from the keychain: GitHub on the identity devctl pr wait picks for owner (the devctl App login for giantswarm, the person's gh login for every other owner), CircleCI on the person's devctl CircleCI login. warn receives the login's expiry warning.

Types

type CircleCI

type CircleCI interface {
	GetProject(ctx context.Context, org, repo string) (*circleciclient.Project, error)
	ListPipelineDefinitions(ctx context.Context, projectID string) ([]circleciclient.PipelineDefinition, error)
	CreatePipelineDefinition(ctx context.Context, projectID string, def circleciclient.PipelineDefinition) (*circleciclient.PipelineDefinition, error)
	ListTriggers(ctx context.Context, projectID, definitionID string) ([]circleciclient.Trigger, error)
	CreateTrigger(ctx context.Context, projectID, definitionID string, trigger circleciclient.Trigger) (*circleciclient.Trigger, error)
	DeleteTrigger(ctx context.Context, projectID, triggerID string) error
	RunPipeline(ctx context.Context, org, repo, definitionID string, ref circleciclient.Ref) (*circleciclient.Pipeline, error)
	GetPipeline(ctx context.Context, id string) (*circleciclient.PipelineDetail, error)
	GetProjectSettings(ctx context.Context, org, repo string) (*circleciclient.ProjectSettings, error)
	UpdateProjectSettings(ctx context.Context, org, repo string, settings circleciclient.ProjectSettings) (*circleciclient.ProjectSettings, error)
	ListPipelineWorkflows(ctx context.Context, pipelineID string) ([]circleciclient.Workflow, error)
}

CircleCI is what Ensure and Wait ask of CircleCI, as the person.

type GitHub

type GitHub interface {
	// Repository returns GitHub's id of owner/repo and its default branch.
	Repository(ctx context.Context, owner, repo string) (id int64, defaultBranch string, err error)
	// LatestRelease returns the repository's latest release, nil when it has
	// none.
	LatestRelease(ctx context.Context, owner, repo string) (*github.RepositoryRelease, error)
	// Releases returns the repository's published releases, drafts and
	// pre-releases left out.
	Releases(ctx context.Context, owner, repo string) ([]*github.RepositoryRelease, error)
	// CircleCIStatuses returns the CircleCI statuses of ref's commit, newest
	// first.
	CircleCIStatuses(ctx context.Context, owner, repo, ref string) ([]*github.RepoStatus, error)
	// HasConfig says whether ref carries .circleci/config.yml.
	HasConfig(ctx context.Context, owner, repo, ref string) (bool, error)
	// CommitSHA returns the commit ref points at.
	CommitSHA(ctx context.Context, owner, repo, ref string) (string, error)
}

GitHub is what Setup reads on GitHub.

func NewGitHub

func NewGitHub(client *github.Client) GitHub

NewGitHub is the GitHub of a go-github client.

type Options

type Options struct {
	// Migrate deletes the OAuth pipeline's triggers (Ensure).
	Migrate bool
	// Wait follows the runs Setup starts until they settle.
	Wait bool
	// Waiter follows them when Wait is set.
	Waiter Waiter
	// Progress receives one line per step; nil discards.
	Progress func(format string, args ...any)
	// Now is the clock; nil means time.Now.
	Now func() time.Time
}

Options are Setup's.

type Outcome

type Outcome struct {
	Pipeline circleciclient.Pipeline
	// Green says every workflow succeeded; Failed names the ones that did
	// not, with their status.
	Green  bool
	Failed []string
	// OnHold names the workflows waiting for an approval: settled as far as
	// the wait goes, a person approves them in the CircleCI UI.
	OnHold []string
}

Outcome is how a pipeline Wait followed ended.

type Report

type Report struct {
	Result *Result
	Runs   []Run
}

Report is what Setup found and did.

func Setup

func Setup(ctx context.Context, ci CircleCI, gh GitHub, owner, repo string, opts Options) (*Report, error)

Setup sets owner/repo up on a GitHub App pipeline as the person (Ensure) and runs what the pipeline has not built. First the release tags whose commit carries no status of their own build (reconcile.TagBuildStatuses on the App pipeline's statuses; any OAuth status after the release counts as built): a tag cut before the trigger existed reached no pipeline, as the scaffold's v0.1.0 of a new repository does. Then the default branch, when Ensure wrote anything or its head carries no App status, unless a tag run builds the branch's head already. A repository without .circleci/config.yml on its default branch is IsNoConfig, before any write. With Wait set the runs are followed until they settle.

func (*Report) Green

func (r *Report) Green() bool

Green says every run waited for succeeded.

type Repository

type Repository struct {
	Owner, Name string
	ID          int64
}

Repository is the GitHub repository to set up: its owner and name, and GitHub's id of it, which CircleCI names the repository by.

func (Repository) Slug

func (r Repository) Slug() string

Slug is owner/name.

type Result

type Result struct {
	ProjectID string
	// Definition is the GitHub App pipeline, found or created.
	Definition circleciclient.PipelineDefinition
	// CreatedDefinition and CreatedTrigger say Ensure created them.
	CreatedDefinition, CreatedTrigger bool
	// OAuthTriggers are the enabled triggers of the OAuth pipeline left in
	// place (without migrate): every push builds on both pipelines.
	OAuthTriggers []string
	// DeletedOAuthTriggers are the OAuth pipeline's triggers migrate
	// deleted.
	DeletedOAuthTriggers []string
	// EnabledSetupWorkflows says Ensure switched the project's setup
	// workflows on.
	EnabledSetupWorkflows bool
	// SetupWorkflowsUnread is why the setting could not be read or written,
	// empty when it was: CircleCI may refuse the person its project
	// settings, and a project created since late 2023 has them on anyway.
	SetupWorkflowsUnread string
}

Result is what Ensure found and did.

func Ensure

func Ensure(ctx context.Context, ci CircleCI, repo Repository, migrate bool) (*Result, error)

Ensure makes repo build on a GitHub App pipeline, idempotently: it finds the project's GitHub App definition or creates DefinitionName(repo), and gives it an all-pushes trigger unless it has an enabled trigger already. With migrate the OAuth pipeline's triggers are deleted after, so a push builds once, on the App; the OAuth definition itself is CircleCI's and stays. The project's setup workflows, which the generated dynamic configuration needs, are switched on when they are off; CircleCI refusing the person the settings (403) is noted in the result, not an error. A login that granted Read access only is refused with circleciclient.IsForbidden on the first write.

func (*Result) Changed

func (r *Result) Changed() bool

Changed says Ensure wrote anything.

type Run

type Run struct {
	Ref      circleciclient.Ref
	Pipeline circleciclient.Pipeline
	Outcome  *Outcome
}

Run is a pipeline Setup started, and how it ended when waited for.

type Waiter

type Waiter struct {
	CircleCI CircleCI
	// Sleep waits between reads; Interval is how long.
	Sleep    func(ctx context.Context, d time.Duration) error
	Interval time.Duration
}

Waiter follows one pipeline until it settles.

func (Waiter) Wait

func (w Waiter) Wait(ctx context.Context, id string) (*Outcome, error)

Wait reads the pipeline of id until its workflows are finished: a setup pipeline first runs its setup workflow, then the continuation creates the workflows that carry the build. The newest run of every workflow name counts. The caller's context bounds the wait.

Jump to

Keyboard shortcuts

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