external

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Feb 17, 2026 License: GPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package external provides interfaces and types for integrating with external CI/CD systems to trigger and monitor test execution as promotion gates. This package defines a common abstraction (TestRunner) that allows the operator to work with multiple CI providers (Jenkins, GitHub Actions, GitLab CI) through a unified interface.

External tests are triggered when a PR reaches a specific environment (e.g., dev, staging) and must pass before promotion to the next environment. This enables automated quality gates across multi-environment deployment pipelines.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrTestNotFound indicates the test run doesn't exist or has expired.
	// This can occur if:
	//   - The run ID is invalid
	//   - The test run was deleted
	//   - The CI system's retention policy expired the run
	ErrTestNotFound = errors.New("test run not found")

	// ErrTestTimeout indicates the test exceeded its configured timeout.
	// The test may have been automatically cancelled by the CI system.
	ErrTestTimeout = errors.New("test run timed out")

	// ErrTriggerFailed indicates the test could not be started.
	// Common causes:
	//   - Job name doesn't exist
	//   - Invalid parameters
	//   - Job is disabled
	//   - Insufficient queue capacity
	ErrTriggerFailed = errors.New("failed to trigger test")

	// ErrAuthFailed indicates authentication failed.
	// Common causes:
	//   - Invalid credentials
	//   - Expired token
	//   - Insufficient permissions
	ErrAuthFailed = errors.New("authentication failed")
)

Common errors returned by TestRunner implementations.

Functions

func IsTerminalError

func IsTerminalError(err error) bool

IsTerminalError returns true if the error represents a terminal failure that should not be retried (authentication, not found, etc).

func SubstituteVariables

func SubstituteVariables(params map[string]string, context SubstitutionContext) map[string]string

SubstituteVariables replaces placeholders in parameters with values from context.

Supported placeholders:

  • ${pr.number} - PR number
  • ${pr.head.sha} - PR head commit SHA
  • ${pr.base.sha} - PR base commit SHA
  • ${pr.branch} - PR source branch
  • ${pr.base_branch} - PR target branch
  • ${pr.author} - PR author username
  • ${pr.title} - PR title
  • ${pr.repository} - Repository name
  • ${cd.environment} - Deployment environment
  • ${cd.version} - Application version
  • ${cd.cluster} - Kubernetes cluster
  • ${cd.namespace} - Kubernetes namespace
  • ${custom.KEY} - Custom values (where KEY is from Custom map)

Returns a new map with substitutions applied. Original map is unchanged. Unmatched placeholders are left as-is.

Example:

params := map[string]string{
    "PR_NUMBER": "${pr.number}",
    "COMMIT_SHA": "${pr.head.sha}",
    "ENV": "${cd.environment}",
}
ctx := SubstitutionContext{
    PR: PRContext{Number: 123, HeadSHA: "abc123"},
    Environment: "staging",
}
result := SubstituteVariables(params, ctx)
// result = {"PR_NUMBER": "123", "COMMIT_SHA": "abc123", "ENV": "staging"}

Types

type ClientError

type ClientError struct {
	Provider  string
	Operation string
	Err       error
}

ClientError represents an error from a CI provider client. Wraps the underlying error with provider and operation context.

func NewClientError

func NewClientError(provider, operation string, err error) *ClientError

NewClientError creates a new client error with context.

func (*ClientError) Error

func (e *ClientError) Error() string

Error implements the error interface.

func (*ClientError) Unwrap

func (e *ClientError) Unwrap() error

Unwrap allows error wrapping for use with errors.Is and errors.As.

type PRContext

type PRContext struct {
	// Number is the PR number.
	Number int

	// HeadSHA is the commit SHA of the PR head.
	HeadSHA string

	// BaseSHA is the commit SHA of the PR base.
	BaseSHA string

	// Branch is the PR source branch name.
	Branch string

	// BaseBranch is the PR target branch name.
	BaseBranch string

	// Author is the PR author username.
	Author string

	// Title is the PR title.
	Title string

	// Repository is the repository name (e.g., "owner/repo").
	Repository string
}

PRContext provides pull request metadata for variable substitution.

type Provider

type Provider string

Provider identifies the CI system type.

const (
	// ProviderJenkins represents Jenkins CI.
	// JobName format: "folder/subfolder/job-name" or "job-name" for root jobs.
	// Requires CSRF token handling (crumb issuer).
	// Authentication: Basic auth or API token.
	ProviderJenkins Provider = "jenkins"

	// ProviderGitHubActions represents GitHub Actions.
	// JobName format: workflow filename (e.g., "test.yml") or workflow ID.
	// Requires repository context (owner/repo).
	// Authentication: GitHub token with actions:write scope.
	// ProviderConfig must include: "owner", "repo", "ref" (branch/tag).
	ProviderGitHubActions Provider = "github-actions"

	// ProviderGitLab represents GitLab CI/CD.
	// JobName format: project ID (e.g., "12345").
	// Requires ref (branch/tag) to trigger pipeline.
	// Authentication: Personal access token or project token.
	// ProviderConfig must include: "project_id", "ref".
	ProviderGitLab Provider = "gitlab"
)

type ProviderConfig

type ProviderConfig struct {
	// Type identifies the provider (jenkins, github-actions, gitlab).
	Type string

	// Endpoint is the base URL for the CI system API.
	// Examples:
	//   - Jenkins: "https://jenkins.example.com"
	//   - GitLab: "https://gitlab.example.com/api/v4"
	//   - GitHub Actions: "https://api.github.com"
	Endpoint string

	// Token is the API authentication token.
	// Should be loaded from Kubernetes Secrets, not stored in config files.
	Token string

	// Username is the username for basic auth (Jenkins only).
	// GitHub Actions and GitLab use token-only auth.
	Username string

	// Timeout is the default timeout for API requests.
	// Zero means use the package default (30 seconds).
	Timeout time.Duration

	// Additional provider-specific configuration can be stored here.
	// Examples: TLS settings, proxy configuration, etc.
	Extra map[string]string
}

ProviderConfig contains provider-specific configuration for a TestRunner. Each provider implementation defines its own config requirements.

type SubstitutionContext

type SubstitutionContext struct {
	// PR contains pull request metadata.
	PR PRContext

	// Environment is the deployment environment (e.g., "staging", "production").
	Environment string

	// Version is the application version being tested.
	Version string

	// Cluster is the Kubernetes cluster name.
	Cluster string

	// Namespace is the Kubernetes namespace.
	Namespace string

	// Custom allows arbitrary key-value substitutions.
	// Keys should be namespaced (e.g., "custom.my_value").
	Custom map[string]string
}

SubstitutionContext provides values for variable substitution in test parameters.

Used by SubstituteVariables() to replace placeholders like ${pr.number} with actual values. All fields are optional - missing fields result in empty substitution.

type TestConfig

type TestConfig struct {
	// JobName is the name of the test job, workflow, or pipeline to trigger.
	// Format is provider-specific (see struct documentation above).
	JobName string

	// Parameters contains job/workflow parameters as key-value pairs.
	// These are passed to the CI system and may include:
	//   - ENVIRONMENT: target environment (dev/staging/prod)
	//   - VERSION: version to test
	//   - COMMIT_SHA: Git commit SHA to test
	// Supports variable substitution (${pr.number}, ${pr.head.sha}, ${cd.version}, etc.)
	Parameters map[string]string

	// Ref is the Git reference (SHA, branch, tag) to test.
	// For GitHub Actions, this determines which workflow file version to use.
	// For Jenkins/GitLab, this may be passed as a parameter.
	Ref string

	// Timeout is the maximum duration to wait for test completion.
	// If the test doesn't complete within this time, it's marked as timed out.
	// Zero means use the provider's default timeout.
	Timeout time.Duration

	// Provider identifies the CI system (Jenkins, GitHubActions, GitLab).
	Provider Provider

	// ProviderConfig holds provider-specific configuration (repo, branch, etc).
	// Contents depend on the Provider value.
	ProviderConfig map[string]string
}

TestConfig contains the configuration for triggering a test run. This is passed to TriggerTest() and includes all parameters needed to start the test job/workflow in the external CI system.

The JobName format is provider-specific:

  • Jenkins: "folder/job-name" or "job-name" for root level jobs
  • GitHub Actions: workflow filename (e.g., "test.yml") or workflow ID
  • GitLab: project ID and pipeline configuration (e.g., "12345/pipeline")

Parameters support variable substitution using SubstituteVariables().

type TestResult

type TestResult struct {
	// Passed indicates whether all tests passed.
	Passed bool

	// Duration is the total test execution time.
	Duration time.Duration

	// FailureReason explains why tests failed (empty if Passed is true).
	FailureReason string

	// TestsPassed is the number of test cases that passed.
	TestsPassed int

	// TestsFailed is the number of test cases that failed.
	TestsFailed int

	// Artifacts contains URLs to generated artifacts (coverage, reports, etc).
	Artifacts map[string]string
}

TestResult represents the final outcome of a completed test.

Only present when TestStatus is Success, Failed, Cancelled, or Timeout.

type TestRun

type TestRun struct {
	// ID is the unique identifier for this test run in the CI system.
	// Used for status polling and log retrieval.
	// Format is provider-specific:
	//   - Jenkins: build number (e.g., "123")
	//   - GitHub Actions: run ID (e.g., "1234567890")
	//   - GitLab CI: pipeline ID (e.g., "987654321")
	ID string

	// Provider identifies the CI system (jenkins, github-actions, gitlab).
	// Used to route status checks to the correct TestRunner implementation.
	Provider Provider

	// JobName is the name of the job/workflow that was triggered.
	// Copied from TestConfig for reference.
	JobName string

	// URL is the web UI link to view the test run.
	// Displayed in GitHub PR comments and operator logs.
	URL string

	// StartedAt is when the test run was triggered.
	// Used for timeout calculations and metrics.
	StartedAt time.Time

	// CompletedAt is when the test run finished (success, failure, or timeout).
	// Zero value means the test is still running.
	CompletedAt time.Time

	// Status is the current status of the test run.
	Status TestStatus

	// Message contains additional context about the test run.
	// May include error messages, failure reasons, or summary information.
	Message string
}

TestRun represents a triggered test run with metadata for tracking and status polling. Returned by TriggerTest() and stored in the PullRequestTracker CRD status.

type TestRunner

type TestRunner interface {
	// TriggerTest starts a test job/workflow with the given configuration.
	// Returns a TestRun with the run ID and metadata needed for status polling.
	//
	// Common errors:
	//   - ErrAuthFailed: Authentication credentials are invalid
	//   - ErrTriggerFailed: Job trigger failed (job not found, invalid params)
	//   - context.DeadlineExceeded: Operation timeout
	TriggerTest(ctx context.Context, config TestConfig) (*TestRun, error)

	// GetStatus polls the current status of a running test.
	// Returns the current TestStatus and any error encountered during polling.
	// Should be called periodically until status is terminal (success/failure/timeout).
	// Implementations should be idempotent - safe to call repeatedly.
	//
	// Common errors:
	//   - ErrTestNotFound: Test run ID doesn't exist or expired
	//   - ErrAuthFailed: Authentication credentials are invalid
	//   - context.DeadlineExceeded: Operation timeout
	GetStatus(ctx context.Context, runID string) (TestStatus, error)

	// GetLogs retrieves the complete logs from a test run.
	// Returns raw log content as a string. May be empty if logs are not available yet.
	// For large logs, implementations may truncate or paginate results.
	//
	// Common errors:
	//   - ErrTestNotFound: Test run ID doesn't exist or logs expired
	//   - ErrAuthFailed: Authentication credentials are invalid
	GetLogs(ctx context.Context, runID string) (string, error)

	// Cancel attempts to cancel a running test.
	// Returns nil if cancellation was initiated successfully, even if the test is
	// already complete. Implementations should be idempotent.
	//
	// Common errors:
	//   - ErrTestNotFound: Test run ID doesn't exist
	//   - ErrAuthFailed: Authentication credentials are invalid
	Cancel(ctx context.Context, runID string) error
}

TestRunner defines the interface for triggering and monitoring external CI/CD tests. Implementations provide integration with specific CI systems (Jenkins, GitHub Actions, etc.). All methods are context-aware to support timeouts and cancellation.

Provider-specific implementations should:

  • Handle authentication (tokens, credentials, certificates)
  • Parse provider-specific responses into domain types
  • Implement retries for transient failures
  • Log operations for observability

Example usage:

runner := jenkins.NewRunner(config)
testRun, err := runner.TriggerTest(ctx, TestConfig{
    JobName: "folder/integration-tests",
    Parameters: map[string]string{"PR_NUMBER": "123"},
})
if err != nil {
    return fmt.Errorf("failed to trigger test: %w", err)
}

type TestStatus

type TestStatus string

TestStatus represents the current status of a test run. States are terminal except for Pending and Running, which require continued polling.

const (
	// StatusPending indicates the test is queued but not yet started.
	// The CI system has accepted the request but hasn't begun execution.
	StatusPending TestStatus = "pending"

	// StatusRunning indicates the test is currently executing.
	// Continue polling GetStatus() until a terminal state is reached.
	StatusRunning TestStatus = "running"

	// StatusSuccess indicates the test completed successfully with exit code 0.
	// All assertions passed and the promotion gate is satisfied.
	StatusSuccess TestStatus = "success"

	// StatusFailure indicates the test completed with failures or non-zero exit code.
	// One or more test cases failed or the job errored out.
	// Blocks promotion unless the test is marked as optional.
	StatusFailure TestStatus = "failure"

	// StatusFailed is an alias for StatusFailure for compatibility.
	// Use StatusFailure in new code.
	StatusFailed TestStatus = "failure"

	// StatusTimeout indicates the test exceeded its configured timeout.
	// The test may still be running in the CI system but is considered failed.
	// Blocks promotion.
	StatusTimeout TestStatus = "timeout"

	// StatusCancelled indicates the test was cancelled before completion.
	// May occur due to manual cancellation or operator shutdown.
	StatusCancelled TestStatus = "cancelled"

	// StatusUnknown indicates the status could not be determined.
	// May occur due to CI system unavailability or API errors.
	StatusUnknown TestStatus = "unknown"
)

func (TestStatus) IsFailure

func (s TestStatus) IsFailure() bool

IsFailure returns true if the test failed, timed out, or was cancelled. Any non-success terminal state is considered a failure for promotion gating.

func (TestStatus) IsSuccess

func (s TestStatus) IsSuccess() bool

IsSuccess returns true if the test passed successfully.

func (TestStatus) IsTerminal

func (s TestStatus) IsTerminal() bool

IsTerminal returns true if this status represents a completed test run. Terminal states do not require further polling.

func (TestStatus) String

func (s TestStatus) String() string

String returns the string representation of the status.

Directories

Path Synopsis
Package githubactions provides a GitHub Actions API client implementing the external.TestRunner interface.
Package githubactions provides a GitHub Actions API client implementing the external.TestRunner interface.
Package gitlab provides a GitLab CI API client implementing the external.TestRunner interface.
Package gitlab provides a GitLab CI API client implementing the external.TestRunner interface.
Package jenkins provides a Jenkins REST API client implementing the external.TestRunner interface.
Package jenkins provides a Jenkins REST API client implementing the external.TestRunner interface.

Jump to

Keyboard shortcuts

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