release

package
v0.0.0-...-02e3363 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package release implements VersionGate's Release domain concept: a published version of an Application for its platform (specs/domain/release.md). VersionGate does not distribute binaries — a Release is metadata only. Like internal/application, this package has no dependency on any specific storage technology.

Index

Constants

This section is empty.

Variables

View Source
var ErrAlreadyExists = errors.New("release: version and build number already published for this application")

ErrAlreadyExists is returned by Create when the (Application, version, build number) triple already has a Release — this is the same invariant enforced by the database's unique constraint (specs/domain/release.md's Duplicate releases). It does not by itself distinguish an idempotent retry from a genuine conflict; that resolution is Publish's job (see publish.go).

View Source
var ErrApplicationInactive = errors.New("release: application is not active")

ErrApplicationInactive is returned by Publish when the target Application exists but is deactivated. Per specs/protocols/release-publishing.md, an unknown or inactive Application is a validation failure, not a not-found — distinct from how a direct Application lookup (specs/domain/application.md, #27) reports a missing Application.

View Source
var ErrApplicationNotFound = errors.New("release: application not found")

ErrApplicationNotFound is returned by Create when applicationID does not reference an existing Application. A Release cannot exist without an owning Application.

View Source
var ErrConflict = errors.New("release: version and build number already published with different metadata")

ErrConflict is returned by Publish when the (version, build number) pair already has a Release under this Application, but with different metadata (a different policy) than the request — a genuine conflict, distinct from an idempotent retry (specs/protocols/release-publishing.md's Duplicate publishing).

View Source
var ErrInvalidBuildNumber = errors.New("release: build number must be non-negative")

ErrInvalidBuildNumber is returned by Publish when buildNumber is negative.

View Source
var ErrInvalidPolicy = errors.New("release: policy must be optional or required")

ErrInvalidPolicy is returned by Publish when policy is not one of the known Policy values.

View Source
var ErrNotFound = errors.New("release: not found")

ErrNotFound is returned by GetByVersion when no Release matches the requested (Application, version, build number).

Functions

This section is empty.

Types

type ID

type ID string

ID identifies a Release. Like application.ID, it is assigned by a Repository at creation time.

type Policy

type Policy string

Policy is the update behavior a Release implies for clients relative to their reported version — optional (notify) or mandatory (require update). This is a closed set, not a free-form string.

const (
	PolicyOptional Policy = "optional"
	PolicyRequired Policy = "required"
)

func (Policy) Valid

func (p Policy) Valid() bool

Valid reports whether p is one of the known policies.

type Release

type Release struct {
	ID            ID
	ApplicationID application.ID
	Version       version.Version
	BuildNumber   int
	Policy        Policy
	CreatedAt     time.Time
}

Release is a published version of an Application. Publishing is a single, atomic act — there is no mutable "in progress" state (specs/domain/release.md's Release lifecycle). Once created, a Release's Version, BuildNumber, and Policy are immutable: this package exposes no way to change them after Create. Revocation (specs/domain/release.md's Revocation section) is explicitly out of scope for this package — see #28's issue scope.

func Publish

func Publish(
	ctx context.Context,
	releases Repository,
	applications application.Repository,
	projectID project.ID,
	applicationID application.ID,
	v version.Version,
	buildNumber int,
	policy Policy,
) (Release, bool, error)

Publish implements the idempotent publish decision from specs/protocols/release-publishing.md:

  1. Validate the request (build number, policy, and — via applications — that the target Application exists, is active, and belongs to projectID).
  2. Attempt to create the Release directly, relying on the database's uniqueness constraint (see Repository.Create) rather than checking for existence first — a check-then-insert would race under concurrent or retried requests.
  3. If creation hits an existing (version, build number) pair, resolve the ambiguity by reading back what's actually stored: identical metadata is a safe no-op (the publisher's request already happened), different metadata is a conflict.

v is expected to already be validated (e.g. via version.Parse) — Publish does not re-validate its structure, only that it is accompanied by a valid build number and policy.

The returned bool is true if this call created a new Release, and false if it resolved to an idempotent no-op against an existing one — both are success outcomes (specs/protocols/http.md), but callers (e.g. the HTTP layer) may want to distinguish 201 from 200.

type Repository

type Repository interface {
	Create(ctx context.Context, applicationID application.ID, v version.Version, buildNumber int, policy Policy) (Release, error)
	GetByVersion(ctx context.Context, applicationID application.ID, v version.Version, buildNumber int) (Release, error)

	// ListByApplication returns applicationID's current non-revoked
	// Releases, for update policy evaluation
	// (specs/domain/update-policy.md). Revocation doesn't exist yet (see
	// #28's issue scope), so today this is simply every Release under
	// the Application; a caller filters once revocation lands.
	ListByApplication(ctx context.Context, applicationID application.ID) ([]Release, error)
}

Repository persists and retrieves Releases, scoped to an Application. Infrastructure provides the implementation; this package only declares what it needs from it. Create is expected to rely on a database-level uniqueness constraint on (applicationID, version, buildNumber) rather than a check-then-insert race — see Publish.

Jump to

Keyboard shortcuts

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