circleci

package
v0.25.2 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package circleci is a minimal client for the CircleCI API. marge uses it to look behind a failing "ci/circleci: <job>" commit status and tell a build that really failed apart from one CircleCI cancelled itself, and to rerun the latter so the same commit gets a real verdict.

Builds are read through the v1.1 API; reruns go through the v2 workflow rerun endpoint, which also releases the jobs the cancel left blocked.

Only the handful of fields marge needs are modelled. The v1.1 build JSON is public for public projects; private projects and every rerun endpoint need an API token, sent as the Circle-Token header (never as basic auth or a query parameter).

Index

Constants

View Source
const DefaultBaseURL = "https://circleci.com"

DefaultBaseURL is the CircleCI API host.

Variables

This section is empty.

Functions

func LoadToken

func LoadToken() string

LoadToken returns the CircleCI API token from the CIRCLECI_CLI_TOKEN environment variable or, failing that, from the token line of the CircleCI CLI's own config file (~/.circleci/cli.yml). It returns "" when neither is set, in which case only public projects can be inspected and no build can be retried.

Types

type APIError

type APIError struct {
	StatusCode int
	// Message is the "message" field of the error body, when present.
	Message string
	// Authenticated is true when the request carried a token. Without one,
	// a 401/403/404 on a build usually means a private project, which the
	// error message points out.
	Authenticated bool
}

APIError is a non-2xx answer from the CircleCI API.

func (*APIError) Error

func (e *APIError) Error() string

type Action

type Action struct {
	Name     string `json:"name"`
	Status   string `json:"status"`
	Canceled bool   `json:"canceled"`
	Failed   bool   `json:"failed"`
	// Step and Index address the action's console output.
	Step  int `json:"step"`
	Index int `json:"index"`
	// HasOutput reports whether the action printed anything.
	HasOutput bool `json:"has_output"`
	// OutputURL is a presigned link to the same output. The API returns it
	// for some actions only, so it is a shortcut, never the only path.
	OutputURL string `json:"output_url"`
}

Action is the outcome of one step on one container.

type Build

type Build struct {
	BuildNum    int      `json:"build_num"`
	BuildURL    string   `json:"build_url"`
	Branch      string   `json:"branch"`
	Status      string   `json:"status"`
	Outcome     string   `json:"outcome"`
	Lifecycle   string   `json:"lifecycle"`
	VCSRevision string   `json:"vcs_revision"`
	Canceled    bool     `json:"canceled"`
	Steps       []Step   `json:"steps"`
	Workflows   Workflow `json:"workflows"`
}

Build is the subset of a v1.1 build that marge inspects.

func (*Build) AutoCancelled

func (b *Build) AutoCancelled() bool

AutoCancelled reports whether the build ended because it was cancelled rather than because a step failed.

Verified against the live v1.1 API: when CircleCI auto-cancels a running build (a newer pipeline started on the same branch, or a redundant workflow was detected) it records the build with status and outcome "failed" and the top-level canceled flag false -- indistinguishable from a real failure at that level. The steps tell the two apart: an auto-cancelled build has every action "success" up to the point of cancellation and only "canceled" actions from there on, while a real failure has an action with status "failed". A build cancelled before any step ran carries status/outcome "canceled" instead.

The verdict is conservative: a build with a failed step that was cancelled afterwards, a timed-out step or an infrastructure failure is not an auto-cancel.

type BuildRef

type BuildRef struct {
	// VCS is the API path segment for the VCS provider: "github" or
	// "bitbucket".
	VCS   string
	Owner string
	Repo  string
	Num   int
}

BuildRef identifies one CircleCI job -- a "build" in v1.1 terms -- by the path components the API uses.

func ParseBuildURL

func ParseBuildURL(raw string) (ref BuildRef, ok bool)

ParseBuildURL extracts the build reference from the target_url CircleCI attaches to its commit statuses. Two shapes are recognised:

https://circleci.com/gh/<owner>/<repo>/<build_num>
https://app.circleci.com/pipelines/github/<owner>/<repo>/<pipeline>/workflows/<id>/jobs/<build_num>

Anything else -- another CI system, a CircleCI URL without a build number -- returns ok == false.

type Client

type Client struct {
	HTTPClient *http.Client
	BaseURL    string
	// Token is sent as the Circle-Token header on every request when set.
	// Public projects can be read without one; private projects and the
	// retry endpoint require it.
	Token string
}

Client talks to the CircleCI v1.1 API. The zero value is not usable; use NewClient, or set BaseURL and HTTPClient explicitly (tests do).

func NewClient

func NewClient() *Client

NewClient returns a client for circleci.com whose token, if any, comes from LoadToken.

func (*Client) Build

func (c *Client) Build(ctx context.Context, ref BuildRef) (*Build, error)

Build fetches the v1.1 build behind ref.

func (*Client) HasToken

func (c *Client) HasToken() bool

HasToken reports whether requests will be authenticated.

func (*Client) RerunWorkflowFromFailed added in v0.10.1

func (c *Client) RerunWorkflowFromFailed(ctx context.Context, workflowID string) error

RerunWorkflowFromFailed asks CircleCI to run the workflow again from its failed jobs. Unlike Retry it also releases the jobs that depend on the failed one, so a repository whose branch protection requires those downstream contexts gets them.

CircleCI reruns from a failed job, so it needs one: a workflow cancelled before any job failed has none and the endpoint answers 400. The id of the new workflow run is not read; the caller identifies the rerun by the workflow it asked for. The endpoint requires a token.

func (*Client) Retry

func (c *Client) Retry(ctx context.Context, ref BuildRef) (*Build, error)

Retry asks CircleCI to run the single build again on the same commit and returns the new build. The endpoint requires a token.

A build retried this way runs on its own: the jobs that the workflow had left blocked or not run because of the cancel stay where they are. Prefer RerunWorkflowFromFailed whenever the build carries a workflow id.

func (*Client) StepOutput added in v0.14.0

func (c *Client) StepOutput(ctx context.Context, ref BuildRef, action Action) ([]OutputLine, error)

StepOutput returns the console output of one action of a build. An action that printed nothing yields no lines.

type OutputLine added in v0.14.0

type OutputLine struct {
	Message string `json:"message"`
	Type    string `json:"type"`
}

OutputLine is one line of an action's console output.

type Step

type Step struct {
	Name    string   `json:"name"`
	Actions []Action `json:"actions"`
}

Step is one named step of a build; a step has one action per parallel container.

type Workflow added in v0.10.1

type Workflow struct {
	JobName string `json:"job_name"`
	// WorkflowID is the handle the v2 rerun endpoint takes.
	WorkflowID   string `json:"workflow_id"`
	WorkflowName string `json:"workflow_name"`
}

Workflow is the workflow run a build belongs to. A build outside a workflow carries an empty one.

Jump to

Keyboard shortcuts

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