reference

package
v1.10.0 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package reference provides testing utilities for validating pipeline import/build round-trips against real GitLab CI examples.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func SemanticCompare

func SemanticCompare(original, rebuilt []byte) ([]string, error)

SemanticCompare compares two YAML documents semantically. Returns a list of differences, or empty if they're equivalent.

func ShouldExcludeSample

func ShouldExcludeSample(sampleName string, excludeList []string) bool

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

Finish completes progress tracking and returns statistics.

func (*ProgressReporter) Start

func (p *ProgressReporter) Start()

Start begins tracking progress.

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

func FilterExcludedSamples(samples []Sample, excludeList []string) []Sample

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 NewTester

func NewTester(samplesDir string) *Tester

NewTester creates a new reference tester.

func (*Tester) DiscoverSamples

func (t *Tester) DiscoverSamples() ([]Sample, error)

DiscoverSamples finds all .gitlab-ci.yml samples in the samples directory.

func (*Tester) SetProjectRoot

func (t *Tester) SetProjectRoot(path string)

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%

Jump to

Keyboard shortcuts

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