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 ¶
- Variables
- func IsTerminalError(err error) bool
- func SubstituteVariables(params map[string]string, context SubstitutionContext) map[string]string
- type ClientError
- type PRContext
- type Provider
- type ProviderConfig
- type SubstitutionContext
- type TestConfig
- type TestResult
- type TestRun
- type TestRunner
- type TestStatus
Constants ¶
This section is empty.
Variables ¶
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 ¶
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 ¶
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. |