tiers

package module
v0.1.1 Latest Latest
Warning

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

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

README

tiers

Given a set of local package checkouts, tiers parses their manifests, keeps the dependency edges that stay inside the set, and layers the result so each package appears in a tier above every package it depends on. Tier 0 has no in-set dependencies; tier N depends only on tiers below N. Use it to compute a release order across a group of related repositories.

Manifest parsing is delegated to manifests, so any ecosystem where that library reports both a package's own name and its dependency names works here as-is: currently Go modules, RubyGems, Cargo, npm, Composer, Hex, and others (see the manifests README for the full list).

Install

go install github.com/git-pkgs/tiers/cmd/tiers@latest

CLI

tiers [flags] <dir>...
flag
-ecosystem ecosystem to operate on (golang, gem, npm, ...)
-json emit tiers as JSON
-dot emit the induced graph as graphviz
-v print each package's directory and in-set dependencies

Each run covers one ecosystem: when the input directories contain manifests for exactly one it is selected automatically; otherwise the run stops and lists the ecosystems present so you can pass -ecosystem. Formats that describe consumed tooling rather than a publishable package (Dockerfile, GitHub Actions workflows, .gitmodules, .pre-commit-config.yaml, .tool-versions, Brewfile) are always ignored.

Each argument is a directory containing a manifest at its root (a go.mod, a .gemspec, a Cargo.toml, and so on). A workspace file that points at nested members contributes each member as its own package. A manifest that lists dependencies but omits its own package name (a bare Gemfile, requirements.txt) becomes a package named after its directory so it still lands in the top tier as a consumer.

$ tiers ~/code/git-pkgs/*/
0  github.com/git-pkgs/cooldown  github.com/git-pkgs/managers  github.com/git-pkgs/pom  github.com/git-pkgs/vers  ...
1  github.com/git-pkgs/archives  github.com/git-pkgs/purl  ...
2  github.com/git-pkgs/manifests  github.com/git-pkgs/registries  github.com/git-pkgs/resolve  ...
3  github.com/git-pkgs/enrichment  github.com/git-pkgs/pin
4  github.com/git-pkgs/brief  github.com/git-pkgs/git-pkgs  github.com/git-pkgs/proxy

Only direct dependencies form edges; indirect requirements in a go.mod are ignored on the basis that some other package in the set already holds the direct edge. A dependency cycle stops the run with an error naming the packages involved.

Bumping

tiers bump walks the graph in tier order and, for each package, updates every in-set dependency that has a target version. The update is performed through managers.

tiers bump -set github.com/git-pkgs/vers=v0.7.1 -set github.com/git-pkgs/pom=v0.1.8 ~/code/git-pkgs/*/

-set name=version may be repeated; each name must be a package in the graph. -dry-run prints the commands and skips execution. -ecosystem restricts the graph as for the list command.

An ecosystem is refused with an error, before any command runs, when the mapped manager would write the requested version somewhere other than the manifest that discovery parsed. The error names the tracking issue. RubyGems are refused because bundle add writes to the Gemfile, leaving the gemspec constraint unchanged (#40).

Library

import "github.com/git-pkgs/tiers"

g, err := tiers.Discover("./purl", "./vers", "./manifests")
if err != nil {
    return err
}
layers, err := g.Tiers()
if err != nil {
    return err
}
for i, tier := range layers {
    for _, p := range tier {
        fmt.Printf("%d %s %s\n", i, p.Ecosystem, p.Name)
    }
}

Graph.Filter(ecosystem) returns a subgraph for one ecosystem. Package order within a tier is sorted by ecosystem then name, so repeated runs over the same inputs produce identical output.

License

MIT

Documentation

Overview

Package tiers computes a release order over a set of local package checkouts by parsing their manifests and layering the induced dependency graph. Tier 0 has no in-set dependencies; tier N depends only on tiers below N.

Index

Constants

This section is empty.

Variables

View Source
var Version = "dev"

Version is set at build time via ldflags. When unset (go install, go build without -ldflags), init falls back to the module version embedded by the Go toolchain.

Functions

This section is empty.

Types

type BumpResult

type BumpResult struct {
	Package Package
	Dep     string
	Version string
	Manager string
	// Commands holds every command the manager ran for this bump, in
	// order: the primary command followed by any then: chain steps.
	Commands [][]string
	ExitCode int
	Stderr   string
	Err      error
}

BumpResult records one attempted dependency bump.

type Bumper

type Bumper struct {
	// contains filtered or unexported fields
}

Bumper applies version bumps to packages in a Graph via the managers library.

func NewBumper

func NewBumper(runner managers.Runner) (*Bumper, error)

NewBumper builds a Bumper backed by the given Runner. Pass managers.NewExecRunner() to actually execute commands, or managers.NewMockRunner() to capture them.

func (*Bumper) Bump

func (b *Bumper) Bump(ctx context.Context, g *Graph, targets map[string]string) ([]BumpResult, error)

Bump updates each package's in-set dependencies to the versions given in targets. targets is keyed by dependency Name (e.g. "github.com/git-pkgs/purl" or "base"). A dependency without a target is left alone. Packages are visited in tier order so lower tiers are bumped before their dependents, though each Add operates only on that package's own directory.

type CycleError

type CycleError struct {
	Members []Package
}

CycleError is returned by Tiers when the graph contains a dependency cycle. Members holds only the packages that participate in a cycle, not packages that merely depend on one.

func (*CycleError) Error

func (e *CycleError) Error() string

type DuplicateError

type DuplicateError struct {
	Ecosystem string
	Name      string
	FirstDir  string
	SecondDir string
}

DuplicateError is returned by Discover when two input directories declare the same package identity.

func (*DuplicateError) Error

func (e *DuplicateError) Error() string

type ErrUnsupportedEcosystem

type ErrUnsupportedEcosystem struct {
	Ecosystem string
}

ErrUnsupportedEcosystem is returned by Bump when the graph contains a package whose ecosystem has no manager mapping.

func (*ErrUnsupportedEcosystem) Error

func (e *ErrUnsupportedEcosystem) Error() string

type Graph

type Graph struct {
	Packages []Package
}

Graph is the induced dependency graph over the input directories.

func Discover

func Discover(dirs ...string) (*Graph, error)

Discover parses the manifests in each directory and returns the induced dependency graph over the resulting packages. A directory contributes one Package per manifest that declares its own name; a manifest with dependencies but no self-name (Gemfile, requirements.txt) contributes a Package named after the directory.

func (*Graph) Ecosystems

func (g *Graph) Ecosystems() []string

Ecosystems returns the sorted set of ecosystems present in the graph.

func (*Graph) Filter

func (g *Graph) Filter(ecosystem string) *Graph

Filter returns a graph containing only packages from the given ecosystem. Cross-ecosystem edges never exist, so Deps are already correct.

func (*Graph) Tiers

func (g *Graph) Tiers() ([][]Package, error)

Tiers layers the graph so that every package's in-set dependencies sit in a strictly lower tier. Packages within a tier are sorted by ecosystem then name.

type Package

type Package struct {
	// Dir is the directory containing Manifest. For workspace members it
	// is the member directory, not the workspace root.
	Dir       string
	Ecosystem string
	Name      string
	// Manifest is the filename (no directory component) of the manifest
	// this package was parsed from, inside Dir.
	Manifest string
	// Deps holds the Names of other packages in the same graph that this
	// package depends on directly.
	Deps []string
}

Package is one publishable unit discovered from a manifest.

Directories

Path Synopsis
cmd
tiers command

Jump to

Keyboard shortcuts

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