gitea
The forge, and the mesh's npm package registry: it claims the git and npm-package-registry seats.
Its tools, its events and the provisioner of registry accounts are the TypeScript bundle (index.ts,
tools/, provisioner/). This README covers the Go bundle beside it.
Announcing pull requests to the merge check (novox/hq to-be 45 §9, issue 347)
Every new head of an open pull request is announced as pull.updated, once, and the controller has it checked.
- Which repositories a pass looks at. Each that moved since the last pass, less a minute's margin (issue 250); each holding a pull request updated since then, found by the forge's own search — opening, reopening or retargeting a pull request moves its own update time and not its repository's, and a pull request opened more than a minute after its push was never announced (issue 347); and every repository on a sweep, every ten minutes, or when the search fails.
- A pull request nobody checks is said — by the delivery's owner, not here.
gitea_open_pullsanswers every open pull request from the forge itself, with the statuses its base requires and the ones its head has. Themesh-deliverymodule asks it every five minutes, and a head on a base requiringmesh/merge-gateormesh/repo-checkwith neither for ten minutes since it first saw it so is a delivery held past its bound (delivery.<id>.stalled, stateunannounced), which the controller raises like any other (issue 347). - How to see it work. A pull request opened more than a minute after its branch was pushed — this fix's own
was one, and the announcer it fixes never saw it — has
mesh/merge-gatepending within a pass of the next sweep at the latest, andmesh-controller.conditionsnames none for it. - A pull request or issue number that is not one is refused before the forge is asked: a tool called with a
misnamed argument sent
pulls/NaN.
The package registry's retention (novox/hq ADR 0251 §4, to-be 51)
Every publish adds a version to the registry, and until this nothing removed one. The Go bundle
cmd/npm-registry says which versions each package holds, what keeps each one, and — asked with a why —
deletes the versions nothing keeps.
| tool | what | |
|---|---|---|
npm_packages |
r | every package of the registry's owner, each version newest first with its publish time, its size and why it is kept |
npm_retention |
a | the versions retention would delete, and the bytes. A dry run unless dry_run is false; a real run needs why |
A version is kept when:
- a lockfile on the default branch of any repository on the forge names it —
package-lock.json(every lockfile version),npm-shrinkwrap.json,yarn.lock(classic and berry) andpnpm-lock.yaml(by each resolvedname@versionorname/version), whatever the version's age; - it is the highest published version satisfying a range that a
package.jsonthere names in its dependencies, development, peer or optional dependencies (annpm:alias counts for the package it stands for; a path, a URL, git or a workspace is not a range on this registry). npm itself installs thelatestdist-tag when it satisfies the range; that version is kept by its dist-tag; - a dist-tag names it — and a range that is a dist-tag's name keeps that tag's version;
- it is among the newest
keepof its package, five by default (the artifact store's five builds, ADR 0189 §3), by semantic-version order. Pre-releases count among the newest.
A version that is not a semantic version is never ordered, so it is kept. A range that cannot be read,
or a package whose dist-tags cannot be read, keeps every version of its package, and the answer says
why under keeps_all.
Nothing is deleted on partial knowledge. A repository whose files could not be listed, or a
manifest or lockfile that could not be fetched, is named under repositories_unread in every answer,
and a real run then deletes nothing at all. A file that was fetched but is not readable (broken JSON) is
named under files_not_read, and so is a lockfile entry of a shape the reader does not know (the rest of
that file is still read); what it would have named is not known, so a real run then deletes nothing at all
either. Under node_modules nothing is read: that is what a lockfile already says. An empty
repository, or one without its default branch, holds nothing to read and is not a failure.
A real run deletes each version through the forge's own interface (DELETE /api/v1/packages/{owner}/npm/{name}/{version}), says what it deleted and what the forge refused, and a
version already gone counts as deleted.
How it reaches the forge
Over the forge's HTTP interface on the machine (MESH_GITEA_URL), as the admin account the vault
delivered (MESH_GITEA_ADMIN_USER, the password in MESH_GITEA_ADMIN_PASSWORD_FILE — the same file
the TypeScript bundle mints its token with), by basic authentication: this bundle mints no token and
keeps nothing. The password is read per call and never logged, answered or put in an error. The
registry's owner is MESH_NPM_OWNER, the owner in the seat's npm-path.
Calls to the forge run eight at a time, and one tool call reads for at most 50 seconds, inside a module's 60-second ask.
Why the manifest lists no tools
The TypeScript bundle's tools are served without a tools list, and a claim without serves offers
the module's tools as the seat's verbs — so a list here would make these two tools verbs of both the
git and the npm-package-registry seats. The two names are kept in ToolNames, and a test holds them
to this README and to what the bundle serves.
Tests
go test ./...
Against a fake forge (httptest): what keeps a version (a lockfile whatever its age, the highest
version satisfying a range, a dist-tag, the newest keep); a dry run deleting nothing; a real run
without why refused; a real run deleting only what nothing keeps; an unread repository stopping a real
run before anything is deleted; an unreadable range keeping its whole package; a wrong password failing
without saying the password. And the range matcher against npm's rules — exact, ^, ~, x and *,
comparisons with partial versions, hyphen ranges, ||, and the pre-release rule — and each lockfile
format.