Documentation
¶
Overview ¶
Package source fetches an app's source and exposes it read-only.
R-020: the source tree is strictly read-only input. Pando looks at it and never asks it for permission — there is no pando.yaml, and nothing in a repo can change how Pando behaves.
Index ¶
- Constants
- func AllowLocalRepositories()
- func AppFrom(ctx context.Context) string
- func ForApp(ctx context.Context, appID string) context.Context
- func GuardTransport(t *http.Transport) *http.Transport
- func RefusedAddress(err error) bool
- func SetGuard(g Guard)
- type Access
- type Checkout
- type Credentials
- type Guard
- type HostPort
- type Purpose
- type Sources
- func (s Sources) DiscardUpload(appID string) error
- func (s Sources) Fetch(ctx context.Context, src spec.Source) (*Checkout, error)
- func (s Sources) Probe(ctx context.Context, src spec.Source) error
- func (s Sources) ResolveRef(ctx context.Context, src spec.Source) (string, error)
- func (s Sources) ResolveTracked(ctx context.Context, src spec.Source, ad spec.AutoDeploy) (Tracked, error)
- func (s Sources) StoreUpload(appID string, r io.Reader) (string, error)
- type Tracked
Constants ¶
const DefaultUploadDir = "/var/lib/pando/uploads"
DefaultUploadDir is where a server keeps uploaded sources.
Variables ¶
This section is empty.
Functions ¶
func AllowLocalRepositories ¶ added in v0.8.0
func AllowLocalRepositories()
AllowLocalRepositories lets a repository on this machine's disk be fetched, for tests that build one in a temporary directory. Pando never calls it: a local path is not a source a person can give.
func ForApp ¶
ForApp records which app a fetch is for, so a source connection's use is audited against it.
func GuardTransport ¶ added in v0.14.0
GuardTransport is t with every connection it opens checked against the same guard as a repository fetch: on the address dialed, redirects included, and through a proxy on the destination's host as well. For other reads made at an address a person gave — an image's registry — so that one reaches what a repository may (a registry on the LAN or this machine) and is refused what a repository is (link-local addresses, where a cloud's metadata service answers, and Pando's own port and database).
func RefusedAddress ¶ added in v0.14.0
RefusedAddress reports whether err is the guard refusing a connection, however a client wrapped it.
Types ¶
type Access ¶
type Access struct {
Credential api.GitCredential
// Connection names the source connection it came from, for messages:
// "the source connection 'GitHub (acme)'".
Connection string
}
Access is what a repository is read with.
type Checkout ¶
type Checkout struct {
// Dir is the root of the working tree.
Dir string
// Commit is the resolved SHA. R-120: Ref is what the user asked for, Commit
// is what runs, and it is written back into the spec so a redeploy of the
// same revision builds the same code.
Commit string
// Digest names an uploaded source, which has no commit: the SHA-256 of the
// archive it was unpacked from, as "sha256:<hex>". Never written into the
// spec as a commit (R-120) — it is how a scan knows the same archive when
// it sees it again (R-312).
Digest string
// contains filtered or unexported fields
}
Checkout is a fetched source tree on disk.
type Credentials ¶
type Credentials interface {
Access(ctx context.Context, src spec.Source, purpose Purpose) (*Access, error)
}
Credentials finds what a repository is read with. Nil Access with no error means read it anonymously.
type Guard ¶ added in v0.8.0
type Guard struct {
// OwnPorts are the ports Pando listens on. Refused on loopback and on
// every address of this machine's interfaces.
OwnPorts []uint16
// Database is where Pando's state store is, as host and port. A host
// name is resolved when a dial is checked, since it may be a Compose
// service name whose address changes.
Database []HostPort
// Resolve looks a database host up. net.DefaultResolver when nil.
Resolve func(ctx context.Context, host string) ([]netip.Addr, error)
// LocalAddrs lists this machine's interface addresses.
// net.InterfaceAddrs when nil.
LocalAddrs func() ([]netip.Addr, error)
}
Guard is the endpoints a fetch must not reach beyond the fixed classes.
type Purpose ¶
type Purpose int
Purpose is why a repository is being read, so a use that matters — a clone whose code will run — can be audited and a poll for new commits is not.
type Sources ¶
type Sources struct {
// UploadDir is where uploaded sources are kept.
UploadDir string
// WorkDir is where a clone or an unpacked upload is made while a deploy or
// a detection reads it: server.work_dir, beside Pando's other working
// files, rather than the system temporary directory, which is often a
// small tmpfs that a few concurrent clones fill (issue #72). Empty means
// the system temporary directory, for tests and embeddings.
WorkDir string
// Credentials finds what a repository is read with, from the install's
// source connections (R-091, issue #127). Nil reads every repository
// anonymously, which is what a public one needs.
Credentials Credentials
}
Sources fetches an app's source, and keeps the sources that were uploaded rather than cloned (R-262).
A value handed to each caller rather than a package variable: the upload directory used to be one, and two servers in one process — which is what a parallel test run is — wrote their uploads into each other's (issue #31).
The zero value fetches git and image sources. An upload needs UploadDir.
func (Sources) DiscardUpload ¶
DiscardUpload removes a deleted app's stored upload.
The archive is kept for the app's next deploy, and a deleted app has none: a restore goes to an app created again, with an upload of its own (R-206). It had been kept forever (issue #55). A missing archive is not an error — an app built from git never had one.
func (Sources) Fetch ¶
Fetch clones an app's source.
The caller must have checked the source allowlist first (R-092) — by the time this runs, disk has been written to, which is exactly why that check belongs before it and not inside it.
func (Sources) Probe ¶
Probe checks that src can be read, with the credential its connection gives or anonymously, without cloning it. It is how creating an app from a private repository fails at once, saying why, rather than at detection.
The caller has checked the source allowlist first (R-092).
func (Sources) ResolveRef ¶
ResolveRef returns the commit a ref currently points at, without cloning.
Auto-deploy runs this every five minutes for every app tracking a branch, and the answer is usually "the same as last time". Cloning to find that out would make Pando's largest source of network traffic a question it almost never needs to act on.
func (Sources) ResolveTracked ¶
func (s Sources) ResolveTracked(ctx context.Context, src spec.Source, ad spec.AutoDeploy) (Tracked, error)
ResolveTracked answers "what would auto-deploy deploy now" for an app's source and its auto-deploy settings (R-141), without cloning.
The branch trigger follows AutoDeploy.Branch, or the ref the app was deployed from when that is empty. The release trigger follows the newest tag that counts as a release (NewestRelease).
With the credential the app's source connection gives, as every other read of the repository is (issue #127), so a private repository auto-deploys.
type Tracked ¶
type Tracked struct {
// Ref is fully qualified: refs/heads/main or refs/tags/v1.2.0. It goes in
// the revision's Source.Ref, so the revision says what it was cut from.
Ref string
Commit string
}
Tracked is what an auto-deploy trigger currently points at: the ref it found and the commit under it. Both empty when there is nothing to deploy.
func NewestRelease ¶
NewestRelease picks the newest release tag from a remote's refs.
With no pattern, a release is a stable semantic version tag. With one, it is any tag whose name matches the pattern as a glob (path.Match: `release-*`, `v*`), because plenty of projects tag releases without following semver (issue #40).
Newest is by version order, not by date: a remote's ref list carries no dates, and reading them would mean cloning. Names are compared a run of digits at a time as numbers, so release-10 is newer than release-9 and 2026.10.1 is newer than 2026.9.30.