Documentation
¶
Overview ¶
Package reference provides testing utilities for validating pipeline import/build round-trips against real GitLab CI examples.
Index ¶
- func SemanticCompare(original, rebuilt []byte) ([]string, error)
- func ShouldExcludeSample(sampleName string, excludeList []string) bool
- type FailureCategories
- type ParallelValidationResult
- type ParallelValidator
- type ProgressReporter
- type RoundTripResult
- type Sample
- type Summary
- type TestResult
- type Tester
- type ValidationConfig
- type ValidationStatistics
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SemanticCompare ¶
SemanticCompare compares two YAML documents semantically. Returns a list of differences, or empty if they're equivalent.
func ShouldExcludeSample ¶
ShouldExcludeSample checks if a sample matches any exclusion pattern.
Example ¶
ExampleShouldExcludeSample demonstrates pattern matching for exclusions.
package main
import (
"fmt"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
excludeList := []string{
"Python.gitlab-ci.yml", // Exact match
"Security/*", // Wildcard pattern
}
// Test various samples
samples := []string{
"Go.gitlab-ci.yml",
"Python.gitlab-ci.yml",
"Security/SAST.gitlab-ci.yml",
"Security/Secret-Detection.gitlab-ci.yml",
"Docker.gitlab-ci.yml",
}
for _, sample := range samples {
excluded := reference.ShouldExcludeSample(sample, excludeList)
status := "included"
if excluded {
status = "excluded"
}
fmt.Printf("%s: %s\n", sample, status)
}
}
Output: Go.gitlab-ci.yml: included Python.gitlab-ci.yml: excluded Security/SAST.gitlab-ci.yml: excluded Security/Secret-Detection.gitlab-ci.yml: excluded Docker.gitlab-ci.yml: included
Types ¶
type FailureCategories ¶
type FailureCategories struct {
ImportFailures []string `json:"import_failures"`
BuildFailures []string `json:"build_failures"`
}
FailureCategories groups failures by stage.
func CategorizeFailures ¶
func CategorizeFailures(results []TestResult) FailureCategories
CategorizeFailures groups failures by type.
Example ¶
ExampleCategorizeFailures demonstrates grouping failures by type.
package main
import (
"fmt"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
// Create test results with different failure types
results := []reference.TestResult{
{Sample: reference.Sample{Name: "import-fail.yml"}, ImportOK: false, BuildOK: false},
{Sample: reference.Sample{Name: "build-fail.yml"}, ImportOK: true, BuildOK: false},
{Sample: reference.Sample{Name: "success.yml"}, ImportOK: true, BuildOK: true},
{Sample: reference.Sample{Name: "another-import-fail.yml"}, ImportOK: false, BuildOK: false},
}
// Categorize failures
categories := reference.CategorizeFailures(results)
// Print categorized failures
fmt.Printf("Import Failures (%d):\n", len(categories.ImportFailures))
for _, name := range categories.ImportFailures {
fmt.Printf(" - %s\n", name)
}
fmt.Printf("\nBuild Failures (%d):\n", len(categories.BuildFailures))
for _, name := range categories.BuildFailures {
fmt.Printf(" - %s\n", name)
}
}
Output: Import Failures (2): - import-fail.yml - another-import-fail.yml Build Failures (1): - build-fail.yml
type ParallelValidationResult ¶
type ParallelValidationResult struct {
Statistics ValidationStatistics `json:"statistics"`
Results []TestResult `json:"results"`
Excluded []string `json:"excluded,omitempty"`
}
ParallelValidationResult holds results from parallel validation.
Example (Export) ¶
This example shows how to write validation results to a file for CI integration.
package main
import (
"encoding/json"
"fmt"
"os"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
// Create example result
result := &reference.ParallelValidationResult{
Statistics: reference.ValidationStatistics{
Total: 20,
Passed: 18,
Failed: 2,
ImportSucceeded: 19,
BuildSucceeded: 18,
SuccessRate: 90.0,
Duration: "1m30s",
},
Results: []reference.TestResult{
{
Sample: reference.Sample{Name: "Go.gitlab-ci.yml"},
ImportOK: true,
BuildOK: true,
},
{
Sample: reference.Sample{Name: "Python.gitlab-ci.yml"},
ImportOK: true,
BuildOK: false,
Errors: []string{"build failed: missing dependencies"},
},
},
Excluded: []string{"Security/*"},
}
// Marshal to JSON
jsonData, err := json.MarshalIndent(result, "", " ")
if err != nil {
fmt.Printf("Failed to marshal: %v\n", err)
return
}
// Write to file (in real usage)
// os.WriteFile("results.json", jsonData, 0644)
// Print to demonstrate
fmt.Println(string(jsonData))
// Output would be formatted JSON with full validation results
_ = os.Stdout
}
type ParallelValidator ¶
type ParallelValidator struct {
// contains filtered or unexported fields
}
ParallelValidator runs validation tests in parallel.
Example ¶
ExampleParallelValidator demonstrates using the parallel validator to test GitLab CI templates.
package main
import (
"fmt"
"path/filepath"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
// Configure validation
config := reference.ValidationConfig{
Workers: 4,
Verbose: false,
ExcludeList: []string{
"Security/SAST.gitlab-ci.yml", // Exclude Security templates with hidden jobs
"Security/*", // Exclude all Security templates
},
}
// Create validator
templatesDir := "testdata/gitlab-templates"
validator := reference.NewParallelValidator(templatesDir, config)
// Set project root for local development
projectRoot, _ := filepath.Abs("../..")
validator.SetProjectRoot(projectRoot)
// Run validation (commented out for example - would require actual binary)
// Build the wetwire-gitlab binary first
// wetwireBin := "/path/to/wetwire-gitlab"
// result, err := validator.ValidateAll(wetwireBin)
// if err != nil {
// fmt.Printf("Validation failed: %v\n", err)
// return
// }
// Create example result for demonstration
result := &reference.ParallelValidationResult{
Statistics: reference.ValidationStatistics{
Total: 10,
Passed: 8,
Failed: 2,
ImportSucceeded: 9,
BuildSucceeded: 8,
SuccessRate: 80.0,
Duration: "45s",
},
Excluded: []string{"Security/SAST.gitlab-ci.yml", "Security/*"},
}
// Print summary
fmt.Printf("Validation Summary:\n")
fmt.Printf(" Total: %d\n", result.Statistics.Total)
fmt.Printf(" Passed: %d (%.1f%%)\n", result.Statistics.Passed, result.Statistics.SuccessRate)
fmt.Printf(" Failed: %d\n", result.Statistics.Failed)
fmt.Printf(" Duration: %s\n", result.Statistics.Duration)
}
Output: Validation Summary: Total: 10 Passed: 8 (80.0%) Failed: 2 Duration: 45s
func NewParallelValidator ¶
func NewParallelValidator(samplesDir string, config ValidationConfig) *ParallelValidator
NewParallelValidator creates a new parallel validator.
func (*ParallelValidator) SetProjectRoot ¶
func (v *ParallelValidator) SetProjectRoot(path string)
SetProjectRoot sets the path to wetwire-gitlab-go for local testing.
func (*ParallelValidator) ValidateAll ¶
func (v *ParallelValidator) ValidateAll(wetwireBin string) (*ParallelValidationResult, error)
ValidateAll runs validation on all discovered samples in parallel.
type ProgressReporter ¶
type ProgressReporter struct {
// contains filtered or unexported fields
}
ProgressReporter tracks and reports validation progress.
Example ¶
ExampleProgressReporter demonstrates real-time progress tracking.
package main
import (
"fmt"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
// Create reporter for 5 samples
reporter := reference.NewProgressReporter(5, false)
// Start tracking
reporter.Start()
// Simulate processing samples
samples := []reference.Sample{
{Name: "test1.yml"},
{Name: "test2.yml"},
{Name: "test3.yml"},
{Name: "test4.yml"},
{Name: "test5.yml"},
}
for i, sample := range samples {
// Simulate: first 3 pass, last 2 fail
passed := i < 3
reporter.Update(sample, passed)
}
// Finish and get statistics
stats := reporter.Finish()
fmt.Printf("Progress Summary:\n")
fmt.Printf(" Total: %d\n", stats.Total)
fmt.Printf(" Passed: %d\n", stats.Passed)
fmt.Printf(" Failed: %d\n", stats.Failed)
fmt.Printf(" Success: %.1f%%\n", stats.SuccessRate)
}
Output: Progress Summary: Total: 5 Passed: 3 Failed: 2 Success: 60.0%
func NewProgressReporter ¶
func NewProgressReporter(total int, verbose bool) *ProgressReporter
NewProgressReporter creates a new progress reporter.
func (*ProgressReporter) Finish ¶
func (p *ProgressReporter) Finish() ValidationStatistics
Finish completes progress tracking and returns statistics.
func (*ProgressReporter) Update ¶
func (p *ProgressReporter) Update(sample Sample, passed bool)
Update records a completed test.
type RoundTripResult ¶
type RoundTripResult struct {
Summary Summary `json:"summary"`
Results []TestResult `json:"results"`
}
RoundTripResult holds the full round-trip test results.
type Sample ¶
type Sample struct {
Name string `json:"name"`
Source string `json:"source"` // URL or path to the original
Path string `json:"path"` // Local path to the sample file
}
Sample represents a reference pipeline sample.
func FilterExcludedSamples ¶
FilterExcludedSamples removes excluded samples from the list.
Example ¶
ExampleFilterExcludedSamples demonstrates filtering samples with exclusion patterns.
package main
import (
"fmt"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
samples := []reference.Sample{
{Name: "Go.gitlab-ci.yml", Path: "/templates/Go.gitlab-ci.yml"},
{Name: "Python.gitlab-ci.yml", Path: "/templates/Python.gitlab-ci.yml"},
{Name: "Security/SAST.gitlab-ci.yml", Path: "/templates/Security/SAST.gitlab-ci.yml"},
{Name: "Security/Secret-Detection.gitlab-ci.yml", Path: "/templates/Security/Secret-Detection.gitlab-ci.yml"},
{Name: "Docker.gitlab-ci.yml", Path: "/templates/Docker.gitlab-ci.yml"},
}
// Exclude patterns
excludeList := []string{
"Python.gitlab-ci.yml", // Exclude specific template
"Security/*", // Exclude all Security templates
}
// Filter samples
filtered := reference.FilterExcludedSamples(samples, excludeList)
// Print results
fmt.Printf("Original: %d samples\n", len(samples))
fmt.Printf("Filtered: %d samples\n", len(filtered))
fmt.Printf("Remaining templates:\n")
for _, sample := range filtered {
fmt.Printf(" - %s\n", sample.Name)
}
}
Output: Original: 5 samples Filtered: 2 samples Remaining templates: - Go.gitlab-ci.yml - Docker.gitlab-ci.yml
type Summary ¶
type Summary struct {
Total int `json:"total"`
Passed int `json:"passed"`
Failed int `json:"failed"`
SuccessRate float64 `json:"success_rate"`
}
Summary provides aggregate test results.
type TestResult ¶
type TestResult struct {
Sample Sample `json:"sample"`
ImportOK bool `json:"import_ok"`
BuildOK bool `json:"build_ok"`
ValidateOK bool `json:"validate_ok"`
MatchOK bool `json:"match_ok"`
Errors []string `json:"errors,omitempty"`
}
TestResult holds the result of testing a single sample.
type Tester ¶
type Tester struct {
// contains filtered or unexported fields
}
Tester runs reference pipeline tests.
Example (RoundTrip) ¶
ExampleTester_roundTrip demonstrates full import/build/validate cycle.
package main
import (
"fmt"
"path/filepath"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
// Create tester
samplesDir := "testdata/samples"
tester := reference.NewTester(samplesDir)
// Set project root for local development
projectRoot := "/path/to/wetwire-gitlab-go"
tester.SetProjectRoot(projectRoot)
// Discover samples
samples, err := tester.DiscoverSamples()
if err != nil {
fmt.Printf("Failed to discover: %v\n", err)
return
}
fmt.Printf("Found %d samples\n", len(samples))
// For demonstration, create a mock sample
if len(samples) == 0 {
sample := reference.Sample{
Name: "example.gitlab-ci.yml",
Source: "https://example.com/example.gitlab-ci.yml",
Path: filepath.Join(samplesDir, "example.gitlab-ci.yml"),
}
samples = append(samples, sample)
}
// In real usage, you would test each sample:
// for _, sample := range samples {
// result := tester.TestSample(sample, "/path/to/wetwire-gitlab")
// fmt.Printf("%s: import=%v, build=%v\n", sample.Name, result.ImportOK, result.BuildOK)
// }
// Output would show test results for each sample
fmt.Printf("Sample: %s\n", samples[0].Name)
}
func (*Tester) DiscoverSamples ¶
DiscoverSamples finds all .gitlab-ci.yml samples in the samples directory.
func (*Tester) SetProjectRoot ¶
SetProjectRoot sets the path to wetwire-gitlab-go for local testing. This adds a replace directive to imported go.mod files.
func (*Tester) TestAll ¶
func (t *Tester) TestAll(wetwireBin string) (*RoundTripResult, error)
TestAll runs tests on all discovered samples.
func (*Tester) TestSample ¶
func (t *Tester) TestSample(sample Sample, wetwireBin string) TestResult
TestSample tests a single sample through the import/build/validate cycle.
type ValidationConfig ¶
type ValidationConfig struct {
Workers int // Number of parallel workers
Verbose bool // Enable verbose output
ExcludeList []string // Templates to exclude from testing
}
ValidationConfig holds configuration for parallel validation.
Example ¶
ExampleValidationConfig demonstrates configuration options.
package main
import (
"fmt"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
// Basic configuration
basicConfig := reference.ValidationConfig{
Workers: 4,
Verbose: false,
}
fmt.Printf("Basic Config:\n")
fmt.Printf(" Workers: %d\n", basicConfig.Workers)
fmt.Printf(" Verbose: %v\n", basicConfig.Verbose)
// Advanced configuration with exclusions
advancedConfig := reference.ValidationConfig{
Workers: 8,
Verbose: true,
ExcludeList: []string{
"Security/*",
"Jobs/SAST*",
"Complex-Rules.gitlab-ci.yml",
},
}
fmt.Printf("\nAdvanced Config:\n")
fmt.Printf(" Workers: %d\n", advancedConfig.Workers)
fmt.Printf(" Verbose: %v\n", advancedConfig.Verbose)
fmt.Printf(" Exclusions: %d patterns\n", len(advancedConfig.ExcludeList))
}
Output: Basic Config: Workers: 4 Verbose: false Advanced Config: Workers: 8 Verbose: true Exclusions: 3 patterns
type ValidationStatistics ¶
type ValidationStatistics struct {
Total int `json:"total"`
Passed int `json:"passed"`
Failed int `json:"failed"`
Skipped int `json:"skipped"`
ImportSucceeded int `json:"import_succeeded"`
BuildSucceeded int `json:"build_succeeded"`
SuccessRate float64 `json:"success_rate"`
Duration string `json:"duration"`
}
ValidationStatistics holds aggregate statistics from validation run.
func CalculateStatistics ¶
func CalculateStatistics(results []TestResult) ValidationStatistics
CalculateStatistics computes statistics from test results.
Example ¶
ExampleCalculateStatistics demonstrates computing validation statistics.
package main
import (
"fmt"
"github.com/lex00/wetwire-gitlab-go/internal/reference"
)
func main() {
// Create test results
results := []reference.TestResult{
{Sample: reference.Sample{Name: "test1.yml"}, ImportOK: true, BuildOK: true},
{Sample: reference.Sample{Name: "test2.yml"}, ImportOK: true, BuildOK: true},
{Sample: reference.Sample{Name: "test3.yml"}, ImportOK: true, BuildOK: false},
{Sample: reference.Sample{Name: "test4.yml"}, ImportOK: false, BuildOK: false},
}
// Calculate statistics
stats := reference.CalculateStatistics(results)
// Print statistics
fmt.Printf("Total: %d\n", stats.Total)
fmt.Printf("Passed: %d\n", stats.Passed)
fmt.Printf("Failed: %d\n", stats.Failed)
fmt.Printf("Import succeeded: %d\n", stats.ImportSucceeded)
fmt.Printf("Build succeeded: %d\n", stats.BuildSucceeded)
fmt.Printf("Success rate: %.1f%%\n", stats.SuccessRate)
}
Output: Total: 4 Passed: 2 Failed: 2 Import succeeded: 3 Build succeeded: 2 Success rate: 50.0%