artifact

package
v1.19.3 Latest Latest
Warning

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

Go to latest
Published: Feb 11, 2026 License: MIT Imports: 7 Imported by: 0

README

Artifact Package

Go Version

Unified Go library for artifact version management across multiple platforms (GitHub, GitLab, JFrog Artifactory, AWS S3).


Table of Contents


Overview

This package provides a unified interface for managing software artifacts across different platforms. It abstracts version discovery, filtering, and retrieval operations into a consistent API.

Design Philosophy
  1. Platform Abstraction: Single interface for multiple repositories
  2. Semantic Versioning: Built on hashicorp/go-version
  3. Production Focus: Automatic pre-release filtering
  4. Flexible Matching: Substring and regex-based artifact search
  5. Test-Friendly: Zero external API calls in tests

Key Features

  • Multi-Platform Support: GitHub, GitLab, JFrog Artifactory, AWS S3
  • Semantic Versioning: Robust version parsing and comparison
  • Pre-Release Filtering: Automatic exclusion of alpha/beta/rc/dev versions
  • Flexible Matching: Substring and regex-based artifact search
  • Version Organization: Query by major/minor version numbers
  • Streaming Downloads: Direct artifact retrieval without intermediate storage
  • Pagination: Automatic handling of large result sets
  • Context Support: Cancellation and timeout management

Installation

go get github.com/nabbar/golib/artifact

Architecture

The package follows a layered architecture with clear separation of concerns:

┌─────────────────────────────────────────────────────┐
│              artifact.Client Interface              │
│  (ListReleases, GetArtifact, Download, etc.)        │
└─────────────────────────────────────────────────────┘
                         │
         ┌───────────────┼───────────────┐
         │               │               │
         ▼               ▼               ▼
┌────────────────┐ ┌──────────────┐ ┌──────────────┐
│   github/      │ │   gitlab/    │ │   jfrog/     │
│   s3aws/       │ │              │ │              │
└────────────────┘ └──────────────┘ └──────────────┘
         │               │               │
         └───────────────┼───────────────┘
                         ▼
         ┌───────────────────────────────┐
         │    client.ArtHelper           │
         │ (Helper - version organizing) │
         └───────────────────────────────┘
Core Components
1. Client Interface (artifact.Client)

The main interface exposing:

  • ListReleases(): Retrieve all available versions
  • GetArtifact(): Get download URL for specific artifact
  • Download(): Stream artifact content directly
  • Version management methods (via embedded client.ArtHelper)
2. Helper (client.Helper)

Internal component providing version organization:

  • Groups versions by major/minor numbers
  • Retrieves latest versions by criteria
  • Maintains sorted collections for efficient lookups
3. Platform Implementations
  • github: Uses google/go-github SDK
  • gitlab: Uses gitlab-org/api/client-go SDK
  • jfrog: Custom HTTP client with Artifactory Storage API
  • s3aws: Integration with AWS S3 via custom AWS wrapper
4. Helper Functions (artifact package)
  • CheckRegex(): Validate artifact names against patterns
  • ValidatePreRelease(): Filter out alpha/beta/rc versions

Quick Start

GitHub Example
package main

import (
    "context"
    "fmt"
    "net/http"

    "github.com/nabbar/golib/artifact/github"
)

func main() {
    ctx := context.Background()
    
    // Create GitHub artifact client
    client, err := github.NewGithub(ctx, &http.Client{}, "owner/repository")
    if err != nil {
        panic(err)
    }

    // List all stable versions
    versions, err := client.ListReleases()
    if err != nil {
        panic(err)
    }

    // Get latest version
    latest, err := client.GetLatest()
    if err != nil {
        panic(err)
    }
    fmt.Printf("Latest version: %s\n", latest.String())

    // Get download URL for specific artifact
    url, err := client.GetArtifact("linux-amd64", "", latest)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Download URL: %s\n", url)
}
GitLab Example
package main

import (
    "context"
    "github.com/nabbar/golib/artifact/gitlab"
)

func main() {
    ctx := context.Background()
    
    // Create GitLab artifact client (projectID is an integer)
    client, err := gitlab.NewGitlab(ctx, "https://gitlab.com", "your-token", 12345)
    if err != nil {
        panic(err)
    }

    // Get latest version from major version 2
    latest, err := client.GetLatestMajor(2)
    if err != nil {
        panic(err)
    }
    
    // Download artifact
    size, reader, err := client.Download("darwin", "", latest)
    if err != nil {
        panic(err)
    }
    defer reader.Close()
    
    // Process artifact (size in bytes, reader is io.ReadCloser)
    fmt.Printf("Downloading %d bytes\n", size)
}
JFrog Artifactory Example
package main

import (
    "context"
    "net/http"
    "github.com/nabbar/golib/artifact/jfrog"
)

func main() {
    ctx := context.Background()
    client := &http.Client{}
    
    // Create JFrog client with regex to extract version
    // regex must have at least one capturing group for version
    art, err := jfrog.New(
        ctx,
        client.Do,
        "https://artifactory.example.com",
        []string{"repo-name", "path", "to", "artifacts"},
        `artifact-(\d+\.\d+\.\d+)\.tar\.gz`,  // Regex with version capture group
        1,  // Group index for version
    )
    if err != nil {
        panic(err)
    }

    // List versions matching the regex
    versions, err := art.ListReleases()
    if err != nil {
        panic(err)
    }
}
AWS S3 Example
package main

import (
    "context"
    "github.com/nabbar/golib/artifact/s3aws"
    "github.com/nabbar/golib/aws"  // Custom AWS wrapper
)

func main() {
    ctx := context.Background()
    
    // Configure AWS client (using custom golib/aws package)
    awsClient, err := aws.New(/* AWS configuration */)
    if err != nil {
        panic(err)
    }
    
    // Create S3 artifact client
    s3Client, err := s3aws.New(
        ctx,
        awsClient,
        `releases/myapp-v(\d+\.\d+\.\d+)\.zip`,  // Regex with version capture
        1,  // Group index for version
    )
    if err != nil {
        panic(err)
    }

    // Get latest artifact
    latest, err := s3Client.GetLatest()
    if err != nil {
        panic(err)
    }
}

Supported Platforms

Platform Package Authentication Notes
GitHub artifact/github Optional token via HTTP client Public repos work without auth
GitLab artifact/gitlab Token required Self-hosted and GitLab.com
JFrog Artifactory artifact/jfrog Credentials via HTTP client Uses Storage API
AWS S3 artifact/s3aws AWS credentials Requires golib/aws wrapper

Use Cases

1. Automated Deployment Systems

Check for new versions and deploy automatically:

latest, _ := client.GetLatest()
deployed, _ := version.NewVersion(getCurrentDeployedVersion())

if latest.GreaterThan(deployed) {
    url, _ := client.GetArtifact("linux-amd64", "", latest)
    downloadAndDeploy(url)
}
2. Version Pinning

Lock to specific major/minor versions:

// Always use latest patch of v2.1.x
v21Latest, _ := client.GetLatestMinor(2, 1)
3. Multi-Platform Binary Distribution

Retrieve platform-specific artifacts:

platforms := []string{"linux-amd64", "darwin-arm64", "windows-amd64.exe"}
for _, platform := range platforms {
    url, err := client.GetArtifact(platform, "", targetVersion)
    if err != nil {
        // Handle missing platform
        continue
    }
    downloadBinary(url, platform)
}
4. Artifact Mirroring

Download from one platform and upload to another:

size, reader, _ := sourceClient.Download("", `.*\.tar\.gz$`, version)
defer reader.Close()

// Upload to internal storage
uploadToInternalRepository(reader, size)
5. Version Auditing

Generate reports of available versions:

releases, _ := client.ListReleases()
for _, v := range releases {
    fmt.Printf("%s - %s\n", v.String(), getReleaseDat(v))
}

API Reference

artifact.Client Interface
type Client interface {
    // ListReleases returns all stable versions (pre-releases filtered)
    ListReleases() (hscvrs.Collection, error)
    
    // GetArtifact retrieves download URL
    // containName: substring match in artifact name
    // regexName: regex pattern match (takes precedence)
    GetArtifact(containName, regexName string, release *hscvrs.Version) (string, error)
    
    // Download streams artifact content
    Download(containName, regexName string, release *hscvrs.Version) (int64, io.ReadCloser, error)
    
    // Version management methods (from client.ArtHelper)
    ListReleasesOrder() (map[int]map[int]hscvrs.Collection, error)
    ListReleasesMajor(major int) (hscvrs.Collection, error)
    ListReleasesMinor(major, minor int) (hscvrs.Collection, error)
    GetLatest() (*hscvrs.Version, error)
    GetLatestMajor(major int) (*hscvrs.Version, error)
    GetLatestMinor(major, minor int) (*hscvrs.Version, error)
}
Helper Functions
// CheckRegex validates artifact name against regex pattern
func CheckRegex(name, regex string) bool

// ValidatePreRelease filters out non-production versions
// Returns false for: alpha, beta, rc, dev, test, draft, master, main
func ValidatePreRelease(version *hscvrs.Version) bool

Performance

API Rate Limits
  • GitHub: 60 req/hour (unauthenticated), 5000 req/hour (authenticated)
  • GitLab: Varies by plan (typically 10 req/second)
  • JFrog: Depends on server configuration
  • S3: No specific rate limits, but cost per request applies
Pagination

Platform implementations automatically handle pagination:

  • GitHub: 100 releases per page
  • GitLab: 100 releases per page
  • JFrog: Single request retrieves file list
  • S3: Configurable page size
Caching Strategy

The package does NOT implement caching. For production use:

// Example caching wrapper
type CachedClient struct {
    client artifact.Client
    cache  map[string]interface{}
    ttl    time.Duration
}

func (c *CachedClient) ListReleases() (hscvrs.Collection, error) {
    if cached, ok := c.cache["releases"]; ok {
        return cached.(hscvrs.Collection), nil
    }
    
    releases, err := c.client.ListReleases()
    if err == nil {
        c.cache["releases"] = releases
        go c.expireAfter("releases", c.ttl)
    }
    return releases, err
}
Memory Usage

Version collections use hashicorp/go-version which is memory-efficient:

  • ~100 bytes per version entry
  • 1000 versions ≈ 100KB memory

Best Practices

Use Context for Timeouts

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

versions, err := client.ListReleases()

Cache Version Lists

// Avoid repeated API calls - cache results
type CachedClient struct {
    client artifact.Client
    cache  map[string]interface{}
    ttl    time.Duration
}

Handle Pre-releases Appropriately

// Pre-releases are automatically filtered by ListReleases()
// To include them, use platform-specific methods if available

Check for Multiple Platforms

platforms := []string{"linux-amd64", "darwin-arm64", "windows-amd64.exe"}
for _, platform := range platforms {
    url, err := client.GetArtifact(platform, "", version)
    if err != nil {
        continue // Handle missing platform gracefully
    }
}

Testing

Test Suite: 45 specs using Ginkgo v2 and Gomega

# Run tests
go test ./...

# With coverage
go test -cover ./...

# Using Ginkgo
ginkgo -r -cover

Coverage

Package Coverage Notes
artifact 100% Helper functions
artifact/client 98.6% Version organization
artifact/github 8.6% No external API calls
artifact/gitlab 14.4% No external API calls
artifact/jfrog 6.8% No external API calls
artifact/s3aws 2.0% No external API calls

Note: Lower coverage in platform packages is intentional to avoid billing and external dependencies in CI/CD.

See TESTING.md for detailed testing documentation.


Contributing

Contributions are welcome! Please follow these guidelines:

Code Contributions

  • Do not use AI to generate package implementation code
  • AI may assist with tests, documentation, and bug fixing
  • All contributions must pass ginkgo -r
  • Maintain or improve test coverage
  • Follow existing code style and patterns

Pull Request Process

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for your changes
  4. Ensure all tests pass
  5. Update documentation
  6. Submit PR with clear description

See CONTRIBUTING.md for detailed guidelines.


Future Enhancements

Potential improvements for future versions:

Caching & Performance

  • Built-in TTL-based caching layer
  • Parallel downloads for multiple artifacts
  • GraphQL support for GitHub (better performance)

Reliability

  • Checksum verification
  • Retry logic with exponential backoff
  • Circuit breaker pattern

Observability

  • OpenTelemetry integration
  • Metrics and tracing
  • Structured logging

Platform Support

  • Container registries (Docker Hub, GHCR, GCR)
  • Maven/NPM repositories
  • Cloud storage providers (Azure Blob, GCS)

Suggestions welcome via GitHub issues.


AI Transparency Notice

In accordance with Article 50.4 of the EU AI Act, AI assistance has been used for testing, documentation, and bug fixing under human supervision.


License

MIT License - See LICENSE file for details.


Resources

Documentation

Index

Constants

View Source
const (
	MinArtifactGitlab = subUp + liberr.MinPkgArtifact // GitLab error code base
	MinArtifactGithub = subUp + MinArtifactGitlab     // GitHub error code base
	MinArtifactJfrog  = subUp + MinArtifactGithub     // JFrog error code base
	MinArtifactS3AWS  = subUp + MinArtifactJfrog      // AWS S3 error code base
)

Error code ranges for artifact package and subpackages. Each platform implementation has its own error code range to facilitate debugging.

Variables

This section is empty.

Functions

func CheckRegex

func CheckRegex(name, regex string) bool

CheckRegex validates an artifact name against a regex pattern. This function is commonly used to match artifact filenames against expected patterns, such as platform-specific binary names or versioned release files.

Example:

CheckRegex("myapp-1.2.3-linux-amd64.tar.gz", `myapp-\d+\.\d+\.\d+-linux-amd64\.tar\.gz`)
// Returns: true

func DownloadRelease deprecated

func DownloadRelease(link string) (file os.File, err error)

DownloadRelease downloads an artifact from a URL and saves it to a file. This function is not yet implemented and will panic if called.

Deprecated: Use Client.Download() method instead for streaming downloads.

func ValidatePreRelease

func ValidatePreRelease(version *hscvrs.Version) bool

ValidatePreRelease filters out non-production release versions. Returns true only for GA (General Availability) versions or versions with custom prerelease tags that don't match development/testing patterns.

Rejected patterns (returns false):

  • alpha, beta, rc (release candidate)
  • dev, test, draft
  • master, main (branch tags)
  • Single letter abbreviations: "a" or "b"

Accepted patterns (returns true):

  • GA versions (no prerelease): "1.2.3"
  • Custom tags: "1.2.3-stable", "1.2.3-hotfix", "1.2.3-final"

Example:

ValidatePreRelease(version.NewVersion("1.2.3"))        // true (GA)
ValidatePreRelease(version.NewVersion("1.2.3-beta"))   // false
ValidatePreRelease(version.NewVersion("1.2.3-stable")) // true

Types

type Client

type Client interface {
	artcli.ArtHelper

	// ListReleases retrieves all stable versions from the artifact repository.
	// Pre-release versions (alpha, beta, rc, etc.) are automatically filtered out.
	// Returns a sorted collection of semantic versions.
	ListReleases() (releases hscvrs.Collection, err error)

	// GetArtifact retrieves the download URL for a specific artifact.
	// Matching is performed using either substring (containName) or regex (regexName).
	// If both are provided, regex takes precedence.
	//
	// Parameters:
	//   - containName: substring to match in artifact name (e.g., "linux-amd64")
	//   - regexName: regex pattern to match artifact name (e.g., `.*-linux-amd64\.tar\.gz$`)
	//   - release: target version to download
	//
	// Returns the download URL or an error if the artifact is not found.
	GetArtifact(containName string, regexName string, release *hscvrs.Version) (link string, err error)

	// Download streams the artifact content directly without intermediate storage.
	// Returns the content size, a ReadCloser for the content, and any error.
	// The caller is responsible for closing the ReadCloser.
	//
	// Parameters:
	//   - containName: substring to match in artifact name
	//   - regexName: regex pattern to match artifact name (takes precedence)
	//   - release: target version to download
	Download(containName string, regexName string, release *hscvrs.Version) (int64, io.ReadCloser, error)
}

Client defines the unified interface for artifact management across different platforms. It embeds ArtHelper for version organization and adds platform-specific operations.

Implementations:

  • github.Github: GitHub Releases integration
  • gitlab.Gitlab: GitLab Releases integration
  • jfrog.Artifactory: JFrog Artifactory integration
  • s3aws.S3: AWS S3 integration

The interface provides:

  • Version discovery and filtering (via ArtHelper)
  • Artifact URL retrieval (GetArtifact)
  • Direct streaming downloads (Download)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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