v0.34.0 7c1886f

ci_artifact.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package ports
4
5import (
6	"context"
7	"io"
8	"time"
9
10	"bnema.dev/ermite/internal/domain"
11)
12
13// CIArtifactBlock is a staged block of a pending artifact.
14type CIArtifactBlock struct {
15	ArtifactID int64
16	// ID is the uploader's block id (1 to 64 bytes).
17	ID   []byte
18	Size int64
19	// File is the name of the block's file in CIArtifactFiles.
20	File string
21}
22
23// CIArtifactWrite is a change of the artifacts of one repository, written in
24// one atomic batch. The batch requires the usage record of the repository at
25// UsageVersion (0: none stored) and stores Used in it: every write of the
26// artifacts of a repository goes through that record, so two writes never both
27// succeed on the same state, and a write fails with domain.ErrConflict when
28// anything of the repository's artifacts changed since UsageVersion was read.
29//
30// Put stores records: one with Version 0 must not exist yet (the batch then
31// also requires the repository, domain.ErrNotFound once it is deleted), any
32// other must be at its Version. Delete removes records at their Version with
33// their staged blocks. PutBlocks stores blocks (replacing one of the same id),
34// DropBlocks removes all the blocks of the artifacts named.
35type CIArtifactWrite struct {
36	Repo         domain.RepoName
37	Used         int64
38	UsageVersion uint64
39	Put          []domain.CIArtifact
40	Delete       []domain.CIArtifact
41	PutBlocks    []CIArtifactBlock
42	DropBlocks   []int64
43}
44
45// CIArtifactStore keeps the records of the CI artifacts, never their contents.
46// *kvstore.CIArtifacts implements it; the records go with their repository.
47type CIArtifactStore interface {
48	// NextArtifactID takes the next artifact id: global, increasing, never
49	// reused.
50	NextArtifactID(ctx context.Context) (int64, error)
51	// ArtifactUsage returns the bytes charged to the artifacts of the
52	// repository and the version of the record (0, 0 when there is none).
53	ArtifactUsage(ctx context.Context, repo domain.RepoName) (used int64, version uint64, err error)
54	// GetArtifact returns an artifact by id, or domain.ErrNotFound.
55	GetArtifact(ctx context.Context, id int64) (domain.CIArtifact, error)
56	// RunArtifacts returns the artifacts of a run in every state, by id.
57	RunArtifacts(ctx context.Context, repo domain.RepoName, runID int64) ([]domain.CIArtifact, error)
58	// AllArtifacts returns every artifact, for the sweep.
59	AllArtifacts(ctx context.Context) ([]domain.CIArtifact, error)
60	// ArtifactBlocks returns the staged blocks of an artifact.
61	ArtifactBlocks(ctx context.Context, id int64) ([]CIArtifactBlock, error)
62	// BlockArtifactIDs returns the artifacts that have staged blocks, for the
63	// sweep of blocks left by a deleted artifact.
64	BlockArtifactIDs(ctx context.Context) ([]int64, error)
65	// ApplyArtifacts writes w in one batch.
66	ApplyArtifacts(ctx context.Context, w CIArtifactWrite) error
67	// DeleteBlocks removes the staged blocks of an artifact that no longer
68	// exists (left by a repository deleted during an upload).
69	DeleteBlocks(ctx context.Context, id int64) error
70}
71
72// CIArtifactRef names the files of one artifact.
73type CIArtifactRef struct {
74	RunID int64
75	ID    int64
76}
77
78// CIArtifactFiles reads and removes the artifacts recorded before the blob
79// store (ADR 0034); removed once they have all expired. *ciartifacts.Store
80// implements it. Files are named by ids only.
81type CIArtifactFiles interface {
82	// Open returns the content from offset, or domain.ErrNotFound.
83	Open(ctx context.Context, ref CIArtifactRef, offset int64) (io.ReadCloser, error)
84	// Remove deletes the content and the blocks of the artifact.
85	Remove(ctx context.Context, ref CIArtifactRef) error
86	// RemoveRuns deletes the files of the runs.
87	RemoveRuns(ctx context.Context, runIDs []int64) error
88	// RunIDs lists the runs that have a directory, ArtifactIDs the artifacts
89	// that have files in one, for the orphan sweep.
90	RunIDs(ctx context.Context) ([]int64, error)
91	ArtifactIDs(ctx context.Context, runID int64) ([]int64, error)
92}
93
94// ArtifactLimits are the settings of the artifacts of the server.
95type ArtifactLimits struct {
96	// Retention is the default and longest retention.
97	Retention time.Duration
98	// Quota is the space of the artifacts of one repository, MaxSize the size
99	// of one artifact.
100	Quota   int64
101	MaxSize int64
102}
103
104// CreatedArtifact is the answer of CreateJobArtifact.
105type CreatedArtifact struct {
106	ID        int64
107	ExpiresAt time.Time
108}
109
110// CreateJobArtifactParams begin an upload.
111type CreateJobArtifactParams struct {
112	JobID     string
113	Name      string
114	MediaType string
115	// ExpiresAt is the expiry asked for; zero for the default.
116	ExpiresAt time.Time
117}
118
119// ArtifactChunk is one message of a download: the artifact in the first one,
120// then data.
121type ArtifactChunk struct {
122	Artifact *domain.CIArtifact
123	Data     []byte
124}
125
126// JobArtifactService is the artifacts side of the runner protocol. The secret
127// is the job token; jobID must be its job (domain.ErrForbidden otherwise), the
128// job must not have ended (a *domain.JobEndedError), and the run is always the
129// job's. *usecase.CI implements it.
130type JobArtifactService interface {
131	CreateJobArtifact(ctx context.Context, secret string, params CreateJobArtifactParams) (CreatedArtifact, error)
132	// UploadJobArtifactBlock stores data as a block of a pending artifact of
133	// the job. An error of data is returned as it is.
134	UploadJobArtifactBlock(ctx context.Context, secret, jobID string, artifactID int64, blockID []byte, data io.Reader) (int64, error)
135	CommitJobArtifact(ctx context.Context, secret, jobID string, artifactID int64, blockIDs [][]byte) (size int64, digest string, err error)
136	FinalizeJobArtifact(ctx context.Context, secret, jobID, name string, size int64, digest string) (domain.CIArtifact, error)
137	ListJobArtifacts(ctx context.Context, secret, jobID, name string, artifactID int64) ([]domain.CIArtifact, error)
138	// DownloadJobArtifact calls send with the artifact, then with the content
139	// from offset in chunks of at most domain.CIArtifactChunk bytes.
140	DownloadJobArtifact(ctx context.Context, secret, jobID string, artifactID, offset int64, send func(ArtifactChunk) error) error
141	DeleteJobArtifact(ctx context.Context, secret, jobID, name string) (int64, error)
142}
143
144// ArtifactList are the artifacts of a run with the space of the repository.
145type ArtifactList struct {
146	Artifacts []domain.CIArtifact
147	Used      int64
148	Quota     int64
149}
150
151// ArtifactService is the owner side of the artifacts. Listing and downloading
152// need a signed-in caller with repo:read, even on a public repository;
153// deleting needs ci:write. *usecase.CI implements it.
154type ArtifactService interface {
155	ListArtifacts(ctx context.Context, p domain.Principal, repo domain.RepoName, runID int64) (ArtifactList, error)
156	// DownloadArtifact is DownloadJobArtifact for an owner.
157	DownloadArtifact(ctx context.Context, p domain.Principal, repo domain.RepoName, artifactID, offset int64, send func(ArtifactChunk) error) error
158	DeleteArtifact(ctx context.Context, p domain.Principal, repo domain.RepoName, artifactID int64) error
159}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 43

↑↓ moveenter openesc close