ci

package
v0.24.0 Latest Latest
Warning

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

Go to latest
Published: May 30, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package ci detects the CI/CD platform the CLI is currently running under and exposes the base/head commit refs it needs to compute changed dependencies.

Implementations are registered in priority order in registry.go. Detect() returns the first provider whose env-var signature matches; the Local fallback is last so an unrecognised CI still works off `git rev-parse` defaults.

Each provider reports a Platform value from the locally-defined set of constants below. When adding a provider, define its constant here and return it from Platform().

Index

Constants

This section is empty.

Variables

View Source
var ErrNoProvider = errors.New("no CI provider detected")

ErrNoProvider is returned by Detect when no registered provider matches — shouldn't happen in practice because the Local fallback always returns true, but declared so callers can assert on it.

Functions

This section is empty.

Types

type AWSCodeBuild

type AWSCodeBuild struct{}

AWSCodeBuild — https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html

Key envs:

CODEBUILD_BUILD_ID              signature
CODEBUILD_RESOLVED_SOURCE_VERSION  head
CODEBUILD_WEBHOOK_BASE_REF      base (webhook-triggered PRs)
CODEBUILD_SOURCE_REPO_URL       https://github.com/org/repo.git

func (*AWSCodeBuild) BaseRef

func (a *AWSCodeBuild) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*AWSCodeBuild) Detect

func (a *AWSCodeBuild) Detect() bool

func (*AWSCodeBuild) EnrichHeader

func (a *AWSCodeBuild) EnrichHeader(h http.Header)

func (*AWSCodeBuild) HeadRef

func (a *AWSCodeBuild) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*AWSCodeBuild) PRNumber

func (a *AWSCodeBuild) PRNumber() (int, bool)

func (*AWSCodeBuild) Platform

func (a *AWSCodeBuild) Platform() Platform

func (*AWSCodeBuild) RepoSlug

func (a *AWSCodeBuild) RepoSlug() (string, string, bool)

type AzureDevOps

type AzureDevOps struct{}

AzureDevOps — https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables

Key envs:

TF_BUILD=True                            signature
BUILD_SOURCEVERSION                      head commit
SYSTEM_PULLREQUEST_TARGETBRANCHNAME      target branch (PR builds)
SYSTEM_PULLREQUEST_PULLREQUESTNUMBER     PR number
BUILD_REPOSITORY_NAME                    repo name (no owner)
BUILD_BUILDID                            run id

func (*AzureDevOps) BaseRef

func (a *AzureDevOps) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*AzureDevOps) Detect

func (a *AzureDevOps) Detect() bool

func (*AzureDevOps) EnrichHeader

func (a *AzureDevOps) EnrichHeader(h http.Header)

func (*AzureDevOps) HeadRef

func (a *AzureDevOps) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*AzureDevOps) PRNumber

func (a *AzureDevOps) PRNumber() (int, bool)

func (*AzureDevOps) Platform

func (a *AzureDevOps) Platform() Platform

func (*AzureDevOps) RepoSlug

func (a *AzureDevOps) RepoSlug() (string, string, bool)

type BitbucketPipelines

type BitbucketPipelines struct{}

BitbucketPipelines — https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/

Key envs:

BITBUCKET_BUILD_NUMBER          signature
BITBUCKET_COMMIT                head
BITBUCKET_PR_DESTINATION_BRANCH target branch (PR builds)
BITBUCKET_PR_ID                 PR number
BITBUCKET_REPO_OWNER / REPO_SLUG

func (*BitbucketPipelines) BaseRef

func (b *BitbucketPipelines) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*BitbucketPipelines) Detect

func (b *BitbucketPipelines) Detect() bool

func (*BitbucketPipelines) EnrichHeader

func (b *BitbucketPipelines) EnrichHeader(h http.Header)

func (*BitbucketPipelines) HeadRef

func (b *BitbucketPipelines) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*BitbucketPipelines) PRNumber

func (b *BitbucketPipelines) PRNumber() (int, bool)

func (*BitbucketPipelines) Platform

func (b *BitbucketPipelines) Platform() Platform

func (*BitbucketPipelines) RepoSlug

func (b *BitbucketPipelines) RepoSlug() (string, string, bool)

type CircleCI

type CircleCI struct{}

CircleCI — https://circleci.com/docs/variables/

Key envs:

CIRCLECI=true
CIRCLE_SHA1                     head
CIRCLE_PR_NUMBER                PR number (only when triggered from a
                                forked-PR webhook)
CIRCLE_PULL_REQUEST             "https://github.com/org/repo/pull/N"
                                — parse to recover the PR number
                                for non-forked PRs too
CIRCLE_PROJECT_USERNAME/REPONAME
CIRCLE_WORKFLOW_ID              run id

func (*CircleCI) BaseRef

func (c *CircleCI) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*CircleCI) Detect

func (c *CircleCI) Detect() bool

func (*CircleCI) EnrichHeader

func (c *CircleCI) EnrichHeader(h http.Header)

func (*CircleCI) HeadRef

func (c *CircleCI) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*CircleCI) PRNumber

func (c *CircleCI) PRNumber() (int, bool)

func (*CircleCI) Platform

func (c *CircleCI) Platform() Platform

func (*CircleCI) RepoSlug

func (c *CircleCI) RepoSlug() (string, string, bool)

type GitHubActions

type GitHubActions struct{}

GitHubActions — https://docs.github.com/en/actions/learn-github-actions/variables

Key envs we rely on:

GITHUB_ACTIONS=true       signature
GITHUB_SHA                head commit
GITHUB_EVENT_NAME=pull_request  + GITHUB_BASE_REF (target branch name)
GITHUB_REPOSITORY         owner/name
GITHUB_RUN_ID + GITHUB_RUN_ATTEMPT

PR base is tricky: GITHUB_BASE_REF is just the target branch NAME, not a commit. BaseRef() resolves it by running `git rev-parse origin/<base>` which assumes the runner fetched origin (the standard actions/checkout@v4 does).

func (*GitHubActions) BaseRef

func (g *GitHubActions) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*GitHubActions) Detect

func (g *GitHubActions) Detect() bool

func (*GitHubActions) EnrichHeader

func (g *GitHubActions) EnrichHeader(h http.Header)

func (*GitHubActions) HeadRef

func (g *GitHubActions) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*GitHubActions) PRNumber

func (g *GitHubActions) PRNumber() (int, bool)

func (*GitHubActions) Platform

func (g *GitHubActions) Platform() Platform

func (*GitHubActions) RepoSlug

func (g *GitHubActions) RepoSlug() (string, string, bool)

type GitLabCI

type GitLabCI struct{}

GitLabCI — https://docs.gitlab.com/ci/variables/predefined_variables.html

Key envs:

GITLAB_CI=true
CI_COMMIT_SHA                   head
CI_MERGE_REQUEST_TARGET_BRANCH_SHA   base (MR builds)
CI_COMMIT_BEFORE_SHA            base (push builds)
CI_MERGE_REQUEST_IID            PR number
CI_PROJECT_PATH                 owner/name
CI_PIPELINE_ID                  run id

func (*GitLabCI) BaseRef

func (g *GitLabCI) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*GitLabCI) Detect

func (g *GitLabCI) Detect() bool

func (*GitLabCI) EnrichHeader

func (g *GitLabCI) EnrichHeader(h http.Header)

func (*GitLabCI) HeadRef

func (g *GitLabCI) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*GitLabCI) PRNumber

func (g *GitLabCI) PRNumber() (int, bool)

func (*GitLabCI) Platform

func (g *GitLabCI) Platform() Platform

func (*GitLabCI) RepoSlug

func (g *GitLabCI) RepoSlug() (string, string, bool)

type GoogleCloudBuild

type GoogleCloudBuild struct{}

GoogleCloudBuild — https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values

GCB's predefined substitutions are prefixed COMMIT_SHA, BUILD_ID, PROJECT_ID, REPO_NAME. When triggered via the GitHub mirror integration we also get _PR_NUMBER. No standard "target branch" variable — rely on NULLIFY_BASE_REF when running against PR diffs.

func (*GoogleCloudBuild) BaseRef

func (g *GoogleCloudBuild) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*GoogleCloudBuild) Detect

func (g *GoogleCloudBuild) Detect() bool

Detect: Google Cloud Build doesn't expose a single CI=true-style flag; BUILD_ID + PROJECT_ID together are a reasonable signature.

func (*GoogleCloudBuild) EnrichHeader

func (g *GoogleCloudBuild) EnrichHeader(h http.Header)

func (*GoogleCloudBuild) HeadRef

func (g *GoogleCloudBuild) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*GoogleCloudBuild) PRNumber

func (g *GoogleCloudBuild) PRNumber() (int, bool)

func (*GoogleCloudBuild) Platform

func (g *GoogleCloudBuild) Platform() Platform

func (*GoogleCloudBuild) RepoSlug

func (g *GoogleCloudBuild) RepoSlug() (string, string, bool)

type Jenkins

type Jenkins struct{}

Jenkins — https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables

Jenkins has no canonical "target branch" variable — different pipeline setups expose different things. We read the common Multibranch / GitHub-branch-source envs + fall back to NULLIFY_BASE_REF for anything the operator prefers to set by hand.

Key envs:

JENKINS_URL                     signature
GIT_COMMIT                      head
CHANGE_ID                       PR number (Multibranch)
CHANGE_TARGET                   PR target branch
BUILD_NUMBER                    run id

func (*Jenkins) BaseRef

func (j *Jenkins) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*Jenkins) Detect

func (j *Jenkins) Detect() bool

func (*Jenkins) EnrichHeader

func (j *Jenkins) EnrichHeader(h http.Header)

func (*Jenkins) HeadRef

func (j *Jenkins) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*Jenkins) PRNumber

func (j *Jenkins) PRNumber() (int, bool)

func (*Jenkins) Platform

func (j *Jenkins) Platform() Platform

func (*Jenkins) RepoSlug

func (j *Jenkins) RepoSlug() (string, string, bool)

type Local

type Local struct{}

Local is the fallback when no CI env vars match — useful when developers run `nullify deps analyze` on their laptop before pushing. Always returns true from Detect(), so it MUST be the last entry in the registry list.

Defaults:

BaseRef = origin/HEAD (the remote's default-branch tip)
HeadRef = HEAD

Operators can override either via NULLIFY_BASE_REF / NULLIFY_HEAD_REF env vars if their local-dev workflow needs something specific.

func (*Local) BaseRef

func (l *Local) BaseRef(ctx context.Context, repoPath string) (string, error)

func (*Local) Detect

func (l *Local) Detect() bool

func (*Local) EnrichHeader

func (l *Local) EnrichHeader(h http.Header)

func (*Local) HeadRef

func (l *Local) HeadRef(ctx context.Context, repoPath string) (string, error)

func (*Local) PRNumber

func (l *Local) PRNumber() (int, bool)

func (*Local) Platform

func (l *Local) Platform() Platform

func (*Local) RepoSlug

func (l *Local) RepoSlug() (string, string, bool)

type Platform

type Platform string

Platform is the canonical identifier for a CI/CD platform. Values are stamped onto the X-Nullify-CI-Provider header so scpm's audit log can attribute a CLI run to its CI environment.

const (
	PlatformGitHubActions      Platform = "GITHUB_ACTIONS"
	PlatformGitLabCI           Platform = "GITLAB_CI"
	PlatformCircleCI           Platform = "CIRCLECI"
	PlatformBitbucketPipelines Platform = "BITBUCKET_PIPELINES"
	PlatformJenkins            Platform = "JENKINS"
	PlatformAzureDevOps        Platform = "AZURE_DEVOPS"
	PlatformGoogleCloudBuild   Platform = "GOOGLE_CLOUD_BUILD"
	PlatformAWSCodeBuild       Platform = "AWS_CODEBUILD"
	PlatformOther              Platform = "OTHER"
)

func (Platform) String

func (p Platform) String() string

type Provider

type Provider interface {
	// Platform returns this provider's Platform constant.
	Platform() Platform

	// Detect returns true when the current process env matches this
	// provider's signature. Detect MUST NOT touch the network or
	// filesystem — env var inspection only.
	Detect() bool

	// BaseRef returns the commit or ref (short sha, full sha, or
	// branch name) the CI declared as the base of the current build,
	// resolved against the git repository at repoPath. For PR builds,
	// this is the PR target branch's HEAD at PR open time; for push
	// builds, it's the previous HEAD of the pushed branch. Fall back to
	// "origin/<default-branch>" when CI doesn't expose a specific base.
	BaseRef(ctx context.Context, repoPath string) (string, error)

	// HeadRef returns the commit the current build is running against,
	// resolved against the git repository at repoPath. For PR builds,
	// this is the PR's head commit; for push builds, the pushed commit.
	HeadRef(ctx context.Context, repoPath string) (string, error)

	// PRNumber returns the pull-request number if the current build is
	// a PR, and (0, false) otherwise. Used for diagnostic logging + as
	// the idempotency-key prefix in scpm calls.
	PRNumber() (int, bool)

	// RepoSlug returns (owner, name) for GitHub/GitLab/Bitbucket-style
	// coordinates. Returns (_, _, false) when the provider doesn't
	// expose it (eg. Jenkins, self-hosted CI).
	RepoSlug() (owner, name string, ok bool)

	// EnrichHeader adds CI-specific headers to outbound HTTP requests
	// (commit SHA, PR number, run ID) so scpm's audit log can tie a
	// specific CLI run back to a CI invocation. Called once per HTTP
	// request built by the workflow.
	EnrichHeader(h http.Header)
}

Provider identifies one CI/CD platform and exposes the information the CLI's deps-analyze + containers-analyze workflows need. All methods are expected to be cheap — provider detection happens on every CLI invocation.

func Default

func Default() []Provider

Default returns the full list of providers in detection priority. Exposed as a constructor (not a package-level var) so tests can build a truncated list without touching shared state.

func Detect

func Detect(providers []Provider) (Provider, error)

Detect walks providers in order and returns the first one whose Detect() matches. Returns ErrNoProvider only if the caller passed a custom list without Local.

func NewAWSCodeBuild

func NewAWSCodeBuild() Provider

func NewAzureDevOps

func NewAzureDevOps() Provider

func NewBitbucketPipelines

func NewBitbucketPipelines() Provider

func NewCircleCI

func NewCircleCI() Provider

func NewGitHubActions

func NewGitHubActions() Provider

func NewGitLabCI

func NewGitLabCI() Provider

func NewGoogleCloudBuild

func NewGoogleCloudBuild() Provider

func NewJenkins

func NewJenkins() Provider

func NewLocal

func NewLocal() Provider

Jump to

Keyboard shortcuts

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