Documentation
¶
Overview ¶
Package g2 talks to the aqua-registry-g2 repository.
Index ¶
- Constants
- func ClaimDefinition(pkgName string) string
- func ConsolidatedEntries(pkgs []*LegacyPackage) []*gogithub.TreeEntry
- func EncodePackageName(name string) string
- func ErrNoBranchToRename(err error) bool
- func HeadBranchID(branch string) (string, bool)
- func HeadBranchName(id string) string
- func IgnorePackage(content, pkgName, reason string) (string, bool, error)
- func IsClaim(cfg *aquag2.Config) bool
- func IsID(s string) bool
- func IsVersionHeadBranch(id, branch string) bool
- func MarshalConfig(cfg *aquag2.Config) (string, error)
- func MintID(now time.Time, taken map[string]struct{}) string
- func PackageDir(id string) string
- func RemoveBranchName(id string) string
- func RenderVersionsList(logger *slog.Logger, source string, files map[string]string) (string, error)
- func ReplacesPublished(read string) string
- func Shard(id string) string
- func VersionHeadBranchName(id, version string) string
- func WaitingHeadBranchName(id string) string
- type Blobs
- type Breadth
- type Client
- func (c *Client) BranchSHA(ctx context.Context, branch string) (string, error)
- func (c *Client) Commit(ctx context.Context, branch, parent, message string, files []*File) error
- func (c *Client) CommitEntries(ctx context.Context, branch, parent, message string, ...) error
- func (c *Client) CommitPackage(ctx context.Context, logger *slog.Logger, ...) error
- func (c *Client) CommitTree(ctx context.Context, parent, message string, entries []*gogithub.TreeEntry) (string, error)
- func (c *Client) CommitVersions(ctx context.Context, pkgName, branch, parent, message string, files []*File) error
- func (c *Client) Config(ctx context.Context, pkgName string) (*aquag2.Config, error)
- func (c *Client) ConfigOnRef(ctx context.Context, ref, pkgName string) (*aquag2.Config, error)
- func (c *Client) CreateIndexPullRequest(ctx context.Context, logger *slog.Logger, base, title, body string) (*gogithub.PullRequest, error)
- func (c *Client) CreatePullRequest(ctx context.Context, logger *slog.Logger, pkgName, title, body string) (*gogithub.PullRequest, error)
- func (c *Client) CreatePullRequestFrom(ctx context.Context, logger *slog.Logger, head, base, title, body string) (*gogithub.PullRequest, error)
- func (c *Client) CreateVersionsPullRequest(ctx context.Context, logger *slog.Logger, base, title, body string) (*gogithub.PullRequest, error)
- func (c *Client) Dir(pkgName string) (string, bool)
- func (c *Client) File(ctx context.Context, ref, path string) (string, error)
- func (c *Client) HeadBranch(pkgName string) (string, bool)
- func (c *Client) Index(ctx context.Context, ref string) (*aquag2.Index, error)
- func (c *Client) IndexPullRequest(ctx context.Context) (*gogithub.PullRequest, error)
- func (c *Client) IsVersionHeadBranch(pkgName, branch string) bool
- func (c *Client) Label(ctx context.Context, logger *slog.Logger, number int, name string)
- func (c *Client) LegacyPackages(ctx context.Context) ([]*LegacyPackage, error)
- func (c *Client) MoveBranch(ctx context.Context, branch, commit string) error
- func (c *Client) PackageBase(ctx context.Context, pkgName string) (string, error)
- func (c *Client) PackagesInFlight(ctx context.Context) (map[string]struct{}, error)
- func (c *Client) RegistryConfig(ctx context.Context, ref string) (*RegistryConfig, error)
- func (c *Client) RemoveBranch(pkgName string) (string, bool)
- func (c *Client) RenamePackage(ctx context.Context, logger *slog.Logger, from, to string) (*aquag2.Config, error)
- func (c *Client) StaleVersionsLists(ctx context.Context, logger *slog.Logger, blobs Blobs) ([]string, error)
- func (c *Client) UseIdentities(ids *Identities)
- func (c *Client) Version(ctx context.Context, pkgName, version string) (*aquag2.Registry, error)
- func (c *Client) VersionFiles(ctx context.Context, pkgName string) ([]string, error)
- func (c *Client) VersionHeadBranch(pkgName, version string) (string, bool)
- func (c *Client) Versions(ctx context.Context, logger *slog.Logger, pkgName string) (map[string]struct{}, error)
- func (c *Client) VersionsListFile(ctx context.Context, logger *slog.Logger, ref, id string) (*File, error)
- func (c *Client) VersionsOnRef(ctx context.Context, logger *slog.Logger, ref, pkgName string) (map[string]struct{}, error)
- func (c *Client) VersionsPullRequest(ctx context.Context) (*gogithub.PullRequest, error)
- func (c *Client) WaitingHeadBranch(pkgName string) (string, bool)
- func (c *Client) WaitingPullRequest(ctx context.Context, pkgName string) (*gogithub.PullRequest, error)
- type Definitions
- type File
- type Identities
- func (i *Identities) Dir(pkgName string) (string, bool)
- func (i *Identities) HeadBranch(pkgName string) (string, bool)
- func (i *Identities) ID(pkgName string) (string, bool)
- func (i *Identities) IsVersionHeadBranch(pkgName, branch string) bool
- func (i *Identities) Mint(pkgName string) string
- func (i *Identities) Package(id string) (string, bool)
- func (i *Identities) RemoveBranch(pkgName string) (string, bool)
- func (i *Identities) VersionHeadBranch(pkgName, version string) (string, bool)
- func (i *Identities) WaitingHeadBranch(pkgName string) (string, bool)
- type IgnoredPackage
- type LegacyPackage
- type RegistryConfig
Constants ¶
const ConfigFileName = aquag2.ConfigFileName
ConfigFileName is the definition in a package's directory, the file registry.json is generated from.
const ConsolidateBranch = HeadBranchPrefix + "consolidate"
ConsolidateBranch is the head branch of the pull request that moves the packages.
const DefaultBranch = "main"
DefaultBranch is the branch the registry is read from and every pull request targets.
const HeadBranchPrefix = "ar2_"
HeadBranchPrefix marks the branches ar2 opens pull requests from. They are separate from the default branch so that a ruleset protecting it doesn't have to make an exception for the branch a pull request comes from.
const IndexBranch = HeadBranchPrefix + "index"
IndexBranch is where an update to the catalogue is committed.
One fixed branch rather than one per run: the catalogue is only ever added to, so two runs writing to the same branch produce the same thing as two runs one after the other. A run whose pull request is still open adds to it instead of opening another, which is what keeps a scheduled reconciliation from leaving a trail of them behind.
const IndexFileName = aquag2.IndexFileName
IndexFileName is the catalogue on the default branch.
const NeedsDefinitionLabel = "needs-definition"
NeedsDefinitionLabel marks the pull requests whose versions are waiting for a definition.
What it is for is finding them together: they are the one kind of pull request that doesn't merge itself, and a maintainer who has half an hour for the registry wants the list.
const PackagesDir = "pkgs"
PackagesDir is the directory on the default branch holding every package.
const RegistryConfigFileName = "ar2.yaml"
RegistryConfigFileName is the registry's own configuration, on the default branch.
It says what ar2 should do differently for this registry, which is nothing about any one package's contents: those live in the package's directory. Today that is the list of packages to leave alone.
const ReplacesPublishedLabel = "replaces-published"
ReplacesPublishedLabel marks a pull request that changes or removes a file the registry already serves. ar2 puts it on such a pull request when opening it and doesn't set it to merge itself, and the checks fail one that is set to: what lets it merge is a person merging it, and the label is there to say so to whoever reads the list.
const VersionsBranch = HeadBranchPrefix + "versions"
VersionsBranch is where an update to the packages' lists of versions is committed.
One fixed branch, as the catalogue has: a list is made from what the default branch holds, so two runs writing to it produce what the second would have alone, and a run whose pull request is still open adds to it instead of opening another.
Variables ¶
This section is empty.
Functions ¶
func ClaimDefinition ¶ added in v0.1.0
ClaimDefinition is a definition holding the name of the package and nothing else.
It is what a package branch used to be created holding, before its definition arrived, so that the branch named after an id said which package it held. Nothing writes one any more, and the packages copied from those branches may still hold one.
func ConsolidatedEntries ¶ added in v0.11.0
func ConsolidatedEntries(pkgs []*LegacyPackage) []*gogithub.TreeEntry
ConsolidatedEntries are the tree entries that put each package in its directory on the default branch.
Each names the object the branch already holds -- the blob of a file, the tree of the versions directory -- so nothing is uploaded and nothing is rewritten: what each package serves is the same bytes it served from its branch, and versions.json's source, the sha of the versions directory, is still the directory it describes.
func EncodePackageName ¶
EncodePackageName escapes a package name so it can be used as a git ref.
Every character outside [A-Za-z0-9.-] becomes an underscore followed by two lowercase hex digits. Escaping the underscore itself as well makes the mapping reversible, which "/" -> "__" is not: 12 package names already contain an underscore, so that scheme is ambiguous in principle.
cli/cli -> cli_2fcli ipinfo/cli/grepip -> ipinfo_2fcli_2fgrepip sr.ht/~charles/rq -> sr.ht_2f_7echarles_2frq po3rin/github_link_creator -> po3rin_2fgithub_5flink_5fcreator
The result stays within [A-Za-z0-9._-], so it needs no further escaping in a URL. Percent-encoding would not: a branch named with "%7E" has to be written "%257E" in a raw URL, because the server decodes the escape before looking the ref up.
The encoded name also contains no "/", so it is a single ref segment. That removes the directory/file conflict that would otherwise make "ipinfo/cli" and "ipinfo/cli/grepip" unable to coexist as branches; aqua-registry has 30 such pairs.
func ErrNoBranchToRename ¶ added in v0.0.27
ErrNoBranchToRename says the rename failed because the registry doesn't hold the package.
Which is not a failure of the rename so much as a rename with nothing to do: what the caller has to move is the package's place in its own records, and the registry only ever sees the new name.
func HeadBranchID ¶ added in v0.11.0
HeadBranchID returns the id of the package a head branch is for, and false for a branch that isn't one of a package's: the catalogue's, or one ar2 didn't make.
Both the package's own head branch and one of its version branches name it, the second followed by the version.
func HeadBranchName ¶
HeadBranchName returns the branch a pull request about the package as a whole is opened from: tidying its definition, regenerating what it holds, adding it, taking versions out.
It carries no version, and it is one branch per package, because these pull requests write the package's versions.json or its definition, which two at once would conflict on. A run adding versions opens one per version instead: see VersionHeadBranchName.
func IgnorePackage ¶ added in v0.0.25
IgnorePackage returns the registry's configuration with the package added to ignored_packages, and reports whether it was added.
The file is spliced rather than parsed and written back. It is read by people and carries comments and folded prose that a round trip through a YAML encoder would reformat, so what comes back differs from what went in only by the lines added.
The entry goes at the top of the list. The list is read as a set -- nothing depends on the order -- and inserting at the top means the only line that has to be found is the one the list starts on, which is the one thing a parser can give exactly.
func IsClaim ¶ added in v0.1.0
IsClaim reports whether a definition is only a claim to a package, rather than a definition to generate from.
A definition says where the package comes from; the claim says nothing but its name.
func IsVersionHeadBranch ¶ added in v0.0.37
IsVersionHeadBranch reports whether the branch is one of the package's version branches.
A prefix match isn't enough, because one id can be the beginning of another: 1790772680 starts with 179077268. What tells them apart is what follows the separator -- an encoded version, in which an underscore only ever begins an escape.
func MarshalConfig ¶ added in v0.12.0
MarshalConfig renders a definition the way the registry stores it.
repo_id goes right after repo_name, where somebody reading the definition looks for which repository the package is. aqua's type holds it apart from the fields it inlines, so left to the encoder it would come after everything else.
func MintID ¶ added in v0.0.41
MintID returns an identifier for a package that no other package has.
A package's directory is named after this rather than after the package, because a name is not an identity: a repository can be renamed, and the name it leaves behind can be taken by a different repository. What the identifier has to be is unchanging, unique, and mintable without asking anybody -- not random, and not meaningful.
So it is the time it was minted, in seconds. Ten characters, in an order that is the order packages were taken over, and readable with `date -r`. The randomness a UUID carries would be 122 bits spent on a few thousand identifiers that are minted one at a time, and it would be paid for in the table a consumer resolves through: high-entropy strings don't compress, and there is one per package in it.
The layout depends on it too. A package's directory is sharded by the id's last two digits (see PackageDir), which spread evenly only because they are the low digits of a clock: an id minted any other way -- rounded, or counted from a round number -- would pile packages into a few shards.
Uniqueness doesn't rest on the clock. Whoever mints holds the catalogue, so taken says which identifiers are already spoken for, and a second that is taken is stepped past. Nothing else needs a lock: what would make two packages share a branch is two identical identifiers, and that is a question this can answer before it answers anything else.
func PackageDir ¶ added in v0.11.0
PackageDir returns the directory holding the package whose id this is, such as pkgs/69/1790772769.
The packages are spread over a hundred directories rather than kept in one, because a directory is a tree object that every commit under it writes again: one holding thousands of packages would be rewritten whole by every version added to any of them, and GitHub recommends keeping a directory under 3,000 entries.
What spreads them is the id's last two digits. An id is the second it was minted, so its leading digits are a time bucket -- every package taken over in the same few years shares them -- while its trailing digits are as good as uniform. The leaf is the whole id rather than what follows the shard, so an id read out of names.json is found as it is.
func RemoveBranchName ¶ added in v0.0.25
RemoveBranchName returns the branch the pull request that stops serving the package is opened from.
Its own branch rather than the one a version's pull request uses, because it goes the other way: into the default branch, carrying the registry's configuration and the catalogue. A package could have both open at once, and they must not be the same ref.
func RenderVersionsList ¶ added in v0.12.0
func RenderVersionsList(logger *slog.Logger, source string, files map[string]string) (string, error)
RenderVersionsList renders versions.json for the files a package's versions directory holds -- each version's registry.json, keyed by the version -- made from the tree whose sha is source. It is what CommitPackage writes, for a caller that has every file already.
func ReplacesPublished ¶ added in v0.14.0
ReplacesPublished is the part of a pull request's description saying that it is left for a person to merge and what to have read before merging it.
func Shard ¶ added in v0.11.0
Shard is the directory under PackagesDir the package whose id this is sits in.
func VersionHeadBranchName ¶ added in v0.0.34
VersionHeadBranchName returns the branch the pull request adding one version is opened from.
Each version has a pull request of its own, so that one that has to be looked at keeps no other from merging. They don't conflict with each other: each adds its own version's directory, and none writes the package's versions.json, which is brought up to date after they merge.
func WaitingHeadBranchName ¶ added in v0.15.0
WaitingHeadBranchName returns the branch the pull request of a package's versions waiting for a definition is opened from.
They are waiting for one thing said once in the definition -- the layout of an era of the release -- so they are one pull request, and the definition goes on its branch.
Types ¶
type Blobs ¶ added in v0.15.5
type Blobs interface {
Blobs(ctx context.Context, logger *slog.Logger, expressions []string) (map[string]string, error)
}
Blobs reads the text of files, keyed by the expression naming each.
type Breadth ¶ added in v0.0.15
type Breadth struct {
// Versions ends the turn once the package has that many. Default 5.
Versions int `yaml:"versions,omitempty"`
// Attempts ends the turn after that many versions have been tried, whether or
// not they worked.
//
// A release with no assets, or one whose signature can't be verified yet,
// produces nothing, and the newest versions are the likeliest to -- which are
// the ones a turn starts from. Without this a package stops short of Versions
// every turn and takes one every lap forever.
//
// Unset, a turn tries exactly as many versions as it wants and no more, so a
// version that fails costs the package a lap.
Attempts int `yaml:"attempts,omitempty"`
}
Breadth is how far a run goes with a package the registry holds little of.
A run is bounded, and every package wants all of its versions. Spending the whole run on the first one leaves the rest with nothing at all, and a package with nothing can't be installed from the registry; so a package short of Versions gets enough of a turn to reach it and the run moves on.
What the right number is changes. While the registry is being filled it wants to be small, so that every package gets its newest versions before any package gets its history. Once that is done the packages arriving are new ones, and a new package with two usable versions is barely better than one with none, so it wants to be larger. The registry says which it is, because nothing here can tell.
func (*Breadth) GetAttempts ¶ added in v0.0.15
GetAttempts is how many versions may be tried to get there, or zero for as many as are wanted and no more.
func (*Breadth) GetVersions ¶ added in v0.0.15
GetVersions is how many versions ends a package's turn.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client reads and writes aqua-registry-g2.
func (*Client) BranchSHA ¶
BranchSHA returns the commit a branch points at, or an empty string when the branch doesn't exist.
func (*Client) Commit ¶
Commit writes the files onto a new commit on top of parent and points branch at it. The paths are from the root of the repository.
The commit is built through the Git data API rather than a checkout. The default branch holds every package, so cloning it to write one file would be the expensive way to do this.
GitHub signs the commits it creates this way when the caller is a GitHub App installation or GitHub Actions, which is how ar2 runs, so they satisfy a ruleset requiring signatures. A user access token produces unsigned commits, so a local run can't produce something a signature ruleset accepts; that only affects trying ar2 out by hand.
It is the pull request's client that writes, not the reading one. A commit onto a branch that already has an open pull request is a synchronize event, and one made with GITHUB_TOKEN leaves that pull request's checks waiting for approval.
It forces, because a head branch left behind by an earlier run was written against a base that has since moved, so what it holds is stale.
func (*Client) CommitEntries ¶ added in v0.11.0
func (c *Client) CommitEntries(ctx context.Context, branch, parent, message string, entries []*gogithub.TreeEntry) error
CommitEntries writes tree entries onto a new commit on top of parent and points branch at it. The entries name objects the repository already holds, or carry content.
func (*Client) CommitPackage ¶ added in v0.11.0
func (c *Client) CommitPackage(ctx context.Context, logger *slog.Logger, pkgName, branch, parent, message string, files []*File) error
CommitPackage writes the package's files onto a new commit on top of parent and points branch at it. The paths are from the package's directory, such as versions/v1.2.3/registry-1.json.
A commit that changes the versions also writes versions.json, the list of them, so that the list arrives in the same pull request as what it lists and is never behind the registry. Two commits rather than one: the list records the sha of the versions directory it was made from, which is known only once there is a tree holding them. The pull request is squashed when it merges, so the default branch gets one.
Everything Commit says about how and by whom applies here too.
func (*Client) CommitTree ¶ added in v0.12.0
func (c *Client) CommitTree(ctx context.Context, parent, message string, entries []*gogithub.TreeEntry) (string, error)
CommitTree writes tree entries onto a new commit on top of parent and returns it, without pointing any branch at it.
func (*Client) CommitVersions ¶ added in v0.15.0
func (c *Client) CommitVersions(ctx context.Context, pkgName, branch, parent, message string, files []*File) error
CommitVersions writes the package's files onto a new commit on top of parent and points branch at it, the way CommitPackage does, but leaves versions.json alone.
It is for a pull request adding versions while others for the same package are open: the pull request of one version, and the one of the versions waiting for a definition. The list records the sha of the versions directory it was made from, so two pull requests writing it would conflict with whichever of them merged first. Left alone, the list is behind once they merge, and update-versions brings it up to date.
func (*Client) Config ¶
Config returns the package's definition, or nil when the registry holds none.
A package without one is a package aqua-registry-g2 hasn't taken over yet: its definition still lives in aqua-registry, and the next pull request for it carries the converted one along with the generated files.
func (*Client) ConfigOnRef ¶ added in v0.0.34
ConfigOnRef returns the package's definition on a ref, or nil when it holds none.
The ref matters when the definition being generated from isn't the one the registry has merged: a pull request that carries a definition somebody has just written is the only place that version of it exists.
func (*Client) CreateIndexPullRequest ¶
func (c *Client) CreateIndexPullRequest(ctx context.Context, logger *slog.Logger, base, title, body string) (*gogithub.PullRequest, error)
CreateIndexPullRequest opens a pull request updating the catalogue.
func (*Client) CreatePullRequest ¶
func (c *Client) CreatePullRequest(ctx context.Context, logger *slog.Logger, pkgName, title, body string) (*gogithub.PullRequest, error)
CreatePullRequest opens a pull request from the package's head branch into the default branch.
func (*Client) CreatePullRequestFrom ¶ added in v0.0.25
func (c *Client) CreatePullRequestFrom(ctx context.Context, logger *slog.Logger, head, base, title, body string) (*gogithub.PullRequest, error)
CreatePullRequestFrom opens a pull request from head into base.
It is the pull request client that opens it rather than the reading one, whatever the branches are: a pull request opened with GITHUB_TOKEN gets its checks in an approval-required state, so nothing would check it until a person pressed a button.
func (*Client) CreateVersionsPullRequest ¶ added in v0.15.0
func (c *Client) CreateVersionsPullRequest(ctx context.Context, logger *slog.Logger, base, title, body string) (*gogithub.PullRequest, error)
CreateVersionsPullRequest opens a pull request updating the lists of versions.
func (*Client) Dir ¶ added in v0.11.0
Dir is the directory holding the package, and false when the registry holds none.
func (*Client) File ¶ added in v0.0.19
File returns a file of the repository, or an empty string when there is none.
Absent isn't a failure. A file the registry hasn't been written with yet -- one added to what a run maintains after the registry was created -- is missing rather than wrong, and what reads it is deciding whether to write it.
func (*Client) HeadBranch ¶ added in v0.1.0
HeadBranch is the branch a pull request for the package is opened from, and false when the registry holds no such package.
func (*Client) Index ¶
Index returns the catalogue, or an empty one when the repository has none yet.
func (*Client) IndexPullRequest ¶
IndexPullRequest returns the open pull request updating the catalogue, or nil.
func (*Client) IsVersionHeadBranch ¶ added in v0.1.0
IsVersionHeadBranch reports whether the branch is one of the package's version branches.
func (*Client) Label ¶ added in v0.0.34
Label puts a label on a pull request, making it first when the repository hasn't got it.
Said rather than failed for, like the label of the release: what the pull request carries matters more than what it is filed under.
func (*Client) LegacyPackages ¶ added in v0.11.0
func (c *Client) LegacyPackages(ctx context.Context) ([]*LegacyPackage, error)
LegacyPackages is every package still on a branch of its own, in id order.
A request per hundred branches to list them, and one per branch for the root of its tree: the root is three entries, and the versions directory is copied by its sha rather than listed.
func (*Client) MoveBranch ¶ added in v0.12.0
MoveBranch points the branch at the commit, creating it when it doesn't exist.
func (*Client) PackageBase ¶ added in v0.11.0
PackageBase gives the package an id when the registry doesn't hold it yet, and returns the commit a pull request for it is written on top of: the default branch's.
The id is minted here and nowhere else, which is the moment the package is taken over. Nothing is written for it until the pull request is: the head branch named after the id is what the next reading of the registry finds it by until that merges.
func (*Client) PackagesInFlight ¶
PackagesInFlight returns the packages that already have an open pull request.
Asking the repository which versions it holds can't see a pull request that hasn't merged yet, so without this a run would open a second pull request for work that is already waiting — including work waiting precisely because its CI failed.
Every open pull request is listed once per run rather than checking each package, because a run touches many packages and there are rarely many pull requests.
func (*Client) RegistryConfig ¶ added in v0.0.9
RegistryConfig returns the registry's configuration, or an empty one when the repository has none. A registry that asks for nothing different needs no file.
func (*Client) RemoveBranch ¶ added in v0.1.0
RemoveBranch is the branch the pull request that stops serving the package is opened from.
func (*Client) RenamePackage ¶ added in v0.0.20
func (c *Client) RenamePackage(ctx context.Context, logger *slog.Logger, from, to string) (*aquag2.Config, error)
RenamePackage puts the package's definition under the name its repository has now, in a pull request into the default branch.
The package's directory doesn't move, which is what naming it after an id is for: a rename used to carry the whole package over, and everything that had written the old name down was left pointing at nothing. What has to change is the definition, because the definition is the only thing that says which package the directory holds -- one still naming the old package would be found under a name nobody uses, and a run asking for the new name would find nothing and take the package over a second time.
The old name becomes an alias, which is how a configuration still asking for it resolves.
It returns the definition as the pull request writes it, and nil when there was nothing to do: a definition that already names the new package is what a second run of the same rename sees.
func (*Client) StaleVersionsLists ¶ added in v0.15.5
func (c *Client) StaleVersionsLists(ctx context.Context, logger *slog.Logger, blobs Blobs) ([]string, error)
StaleVersionsLists returns the ids of the packages whose versions.json on the default branch isn't the list of what their versions directory holds: one whose source isn't the directory's sha, which is also one with versions and no list, one with a list and no versions, and one whose list can't be read.
It is asked of every package, from what the default branch holds rather than from what changed, so nothing has to be remembered between runs: whichever runs next finds what a run that didn't happen would have.
Which packages there are and what each versions directory is come from one read of the tree under pkgs, and the lists from blobs, a hundred to a query.
func (*Client) UseIdentities ¶ added in v0.1.0
func (c *Client) UseIdentities(ids *Identities)
UseIdentities tells the client which id each package is kept under.
Read once, before anything is read or written, because every package this addresses is in a directory named after its id. A client that was never told holds no package as far as the readers are concerned, and refuses to mint an id rather than inventing one.
func (*Client) Version ¶
Version returns the registry.json the repository holds for one version of a package, or nil when it holds none.
func (*Client) VersionFiles ¶ added in v0.0.25
VersionFiles returns every file the package holds under versions/, as paths from the package's directory.
Every file rather than the registry.json of each version. What has to go when a package stops being served is whatever is there, and a version directory holding something this doesn't know about is exactly what would be left behind by a list built from names.
func (*Client) VersionHeadBranch ¶ added in v0.1.0
VersionHeadBranch is the branch a pull request for one version alone is opened from.
func (*Client) Versions ¶
func (c *Client) Versions(ctx context.Context, logger *slog.Logger, pkgName string) (map[string]struct{}, error)
Versions returns the versions of the package whose registry.json the registry holds.
The repository is asked rather than a local record of what has been generated, because what matters is whether a version is merged, not whether it was once produced. A pull request that fails CI is never merged, and a record of "already generated" would stop it from ever being retried — exactly for the packages that need attention. Asking the repository makes a run idempotent instead.
The Git Data API rather than the Contents API, which stops at 1,000 entries in a directory and says so only by returning fewer: a package with more versions than that would have looked as though the ones it didn't return were missing, and been generated again on every run.
func (*Client) VersionsListFile ¶ added in v0.15.0
func (c *Client) VersionsListFile(ctx context.Context, logger *slog.Logger, ref, id string) (*File, error)
VersionsListFile is the versions.json the package whose id this is should hold, made from the versions directory on ref, or nil when what ref holds already says it.
It is for a list that fell behind: a pull request adding one version leaves the list alone, since two of them for one package would conflict on it, and the list is brought up to date after they merge. The list ref holds is the starting point, and only the versions it lacks are read and the ones gone taken out; a list that can't be read is made again from every version.
func (*Client) VersionsOnRef ¶ added in v0.0.34
func (c *Client) VersionsOnRef(ctx context.Context, logger *slog.Logger, ref, pkgName string) (map[string]struct{}, error)
VersionsOnRef returns the versions of the package a ref holds a registry.json for.
Which for the default branch is what the registry holds, and for the head branch of a pull request is what that pull request would add. The second is what a regeneration of something not yet merged works from: the versions are on the branch and nowhere else.
func (*Client) VersionsPullRequest ¶ added in v0.15.0
VersionsPullRequest returns the open pull request updating the lists of versions, or nil when there is none.
func (*Client) WaitingHeadBranch ¶ added in v0.15.0
WaitingHeadBranch is the branch the pull request of the package's versions waiting for a definition is opened from.
func (*Client) WaitingPullRequest ¶ added in v0.0.34
func (c *Client) WaitingPullRequest(ctx context.Context, pkgName string) (*gogithub.PullRequest, error)
WaitingPullRequest returns the package's open pull request of versions waiting for a definition, or nil when it has none.
It is the one from the package's waiting branch: see WaitingHeadBranchName.
type Definitions ¶ added in v0.1.0
type Definitions interface {
// Subtrees is the directories two levels under the tree an expression names.
Subtrees(ctx context.Context, expression string) ([]string, error)
// Blobs is the text of the file each expression names, keyed by the expression.
Blobs(ctx context.Context, logger *slog.Logger, expressions []string) (map[string]string, error)
// OpenPullRequestHeads is the head branch of every open pull request.
OpenPullRequestHeads(ctx context.Context) ([]string, error)
}
Definitions reads what the identities are read out of.
type File ¶
type File struct {
// Path is where the file goes: from the root of the repository for Commit, and from
// the package's directory for CommitPackage, such as versions/v1.2.3/registry-1.json.
Path string
Content string
// Deleted takes the path out of the tree instead of writing it. The entry is sent
// with a null sha, which is how the Git data API says a path is gone.
Deleted bool
}
File is a file to commit.
func CatalogueFiles ¶ added in v0.0.25
CatalogueFiles renders the files the catalogue is made of.
The table that resolves a name is written with it rather than beside it. It is the catalogue read the other way round -- a name, and every name a package used to have, to where the package is -- so rendering them together is what keeps them from describing different registries.
type Identities ¶ added in v0.1.0
type Identities struct {
// contains filtered or unexported fields
}
Identities is the id each package is kept under.
An id doesn't say which package it is, so this is read from the packages themselves: the directory carries the id and the definition in it carries the package's name. Every package answers for itself, where a table kept anywhere else -- the catalogue, say -- could disagree with what the directories hold and send a package's versions to another package's directory.
A package the table doesn't have is one the registry doesn't hold yet. Taking it over mints its id, and the pull request that brings its definition is where the next reading finds it.
func NewIdentities ¶ added in v0.1.0
func NewIdentities(logger *slog.Logger, held, pending map[string]string) *Identities
NewIdentities reads the table out of the definitions, keyed by id: held is what the default branch holds and pending what open pull requests bring.
What the default branch says wins. A pull request naming a package the default branch already holds under another id is one that would add a second copy of it, and is left to the review it is waiting for.
func ReadIdentities ¶ added in v0.1.0
func ReadIdentities(ctx context.Context, logger *slog.Logger, defs Definitions) (*Identities, map[string]string, error)
ReadIdentities reads which id every package is kept under, and returns the definition each package on the default branch holds, keyed by id, along with it.
The definitions come back because they are what the table was read out of: a caller that works through every definition -- the tidy, the reconciliation -- would otherwise read them again.
A package whose definition is still in an open pull request is in the table too. Its id was minted by the run that opened the pull request, and nothing is on the default branch for it until that merges, so without reading the pull request the next run would mint it a second id and open a second pull request.
func (*Identities) Dir ¶ added in v0.11.0
func (i *Identities) Dir(pkgName string) (string, bool)
Dir is the directory holding the package, and false when the registry holds none.
func (*Identities) HeadBranch ¶ added in v0.1.0
func (i *Identities) HeadBranch(pkgName string) (string, bool)
HeadBranch is the branch a pull request for the package is opened from.
func (*Identities) ID ¶ added in v0.1.0
func (i *Identities) ID(pkgName string) (string, bool)
ID is the id the package is kept under, and false for a package the registry doesn't hold.
func (*Identities) IsVersionHeadBranch ¶ added in v0.1.0
func (i *Identities) IsVersionHeadBranch(pkgName, branch string) bool
IsVersionHeadBranch reports whether the branch is one of the package's version branches.
func (*Identities) Mint ¶ added in v0.1.0
func (i *Identities) Mint(pkgName string) string
Mint gives a package the registry doesn't hold the id it will be kept under, and records it so that the next one steps past it.
func (*Identities) Package ¶ added in v0.1.0
func (i *Identities) Package(id string) (string, bool)
Package is the package kept under the id, and false when no definition says it is one.
func (*Identities) RemoveBranch ¶ added in v0.1.0
func (i *Identities) RemoveBranch(pkgName string) (string, bool)
RemoveBranch is the branch the pull request that stops serving the package is opened from.
func (*Identities) VersionHeadBranch ¶ added in v0.1.0
func (i *Identities) VersionHeadBranch(pkgName, version string) (string, bool)
VersionHeadBranch is the branch a pull request for one version alone is opened from.
func (*Identities) WaitingHeadBranch ¶ added in v0.15.0
func (i *Identities) WaitingHeadBranch(pkgName string) (string, bool)
WaitingHeadBranch is the branch the pull request of the package's versions waiting for a definition is opened from.
type IgnoredPackage ¶ added in v0.0.9
type IgnoredPackage struct {
// Name is the package's name, exactly.
Name string `yaml:"name,omitempty"`
// NameRegexp is a regular expression the whole name has to match, for leaving alone
// every package of an organization with one entry: aquasecurity/.* for one whose IP
// allow list refuses the API to the runners. A run adds the packages aqua-registry
// gains to the order, so an entry for each would need another every time the
// organization gains one.
//
// It is a field of its own rather than a way of reading Name: a name is full of dots,
// and read as a regular expression every one of them would match any character.
NameRegexp string `yaml:"name_regexp,omitempty"`
// Reason is why, in prose. The next person to wonder why a package isn't in the
// registry reads this file and nothing else, so an entry without one says only
// that somebody decided something.
Reason string `yaml:"reason,omitempty"`
// contains filtered or unexported fields
}
IgnoredPackage is a package a run doesn't look at, or a set of them.
type LegacyPackage ¶ added in v0.11.0
type LegacyPackage struct {
ID string
Branch string
// Entries are the branch's definition, its list of versions and its versions
// directory, as the root of its tree names them. What else the branch holds -- its
// README, its workflows -- stays behind with it.
Entries []*gogithub.TreeEntry
}
LegacyPackage is a package still on a branch of its own, and what that branch holds that moves with it.
type RegistryConfig ¶ added in v0.0.9
type RegistryConfig struct {
// IgnoredPackages are the packages a run doesn't look at.
//
// A package that can't be generated is tried again on every run: it costs API
// calls, and it fills the summary of what wasn't published with the same names
// until whoever reads it stops reading. A repository that was deleted or renamed
// will never generate, and a package somebody decided not to migrate never
// should, and neither is a thing to rediscover every half hour.
IgnoredPackages []*IgnoredPackage `yaml:"ignored_packages,omitempty"`
// Breadth is how much of a run one package may take while it has little in the
// registry.
Breadth *Breadth `yaml:"breadth,omitempty"`
}
RegistryConfig is what RegistryConfigFileName holds.
func (*RegistryConfig) Ignores ¶ added in v0.15.9
func (c *RegistryConfig) Ignores(pkgName string) bool
Ignores says whether the registry leaves the package alone: an entry names it, or its name_regexp matches the whole name.