v3.0.0-alpha.1 6fdddb8

apps.go RawHistoryFolder

1package in
2
3import (
4	"context"
5	"time"
6
7	"github.com/bnema/gordon/internal/domain"
8)
9
10// AppService is the driving port for the v3 app lifecycle:
11// apply + reads (list/show/diff), lifecycle verbs
12// (deploy/stop/start/restart/remove), op recovery by idempotency key,
13// and service-scoped secret value writes.
14//
15// The port owns its view structs and speaks domain types only — never
16// adapter DTOs. Secret VALUES cross SetSecrets by necessity (that is the
17// write path); every other method carries names, digests, and ids only.
18//
19// This is preparation: the interface is frozen here, unreachable.
20// The admin handler and the service implementation wire in at cutover;
21// until then no caller exists.
22type AppService interface {
23	// Apply validates a manifest spec and persists it as desired state,
24	// or validates without persistence when dryRun is set. source is the
25	// raw manifest bytes (hashed for audit, never re-read).
26	Apply(ctx context.Context, spec domain.AppSpec, source []byte, dryRun bool) (*AppApplyResult, *AppDryRunResult, error)
27
28	// List returns one summary per known app.
29	List(ctx context.Context) ([]AppSummary, error)
30
31	// Show inspects desired + active + intent + last op for one app.
32	Show(ctx context.Context, app string) (*AppDetail, error)
33
34	// Diff returns the normalized desired-vs-active diff for one app.
35	Diff(ctx context.Context, app string) (domain.AppDiff, error)
36
37	// Deploy activates a captured revision (empty revision means the
38	// desired head; empty service means all services).
39	Deploy(ctx context.Context, app, revision, service, idempotencyKey string) (*domain.AppOperation, error)
40
41	// Stop persists the durable stopped intent and stops exact containers.
42	Stop(ctx context.Context, app, idempotencyKey string) (*domain.AppOperation, error)
43
44	// Start clears the stopped intent and ensures running from active.
45	Start(ctx context.Context, app, idempotencyKey string) (*domain.AppOperation, error)
46
47	// Restart restarts from pinned digests without re-resolution.
48	// Empty service means all services.
49	Restart(ctx context.Context, app, service, idempotencyKey string) (*domain.AppOperation, error)
50
51	// Remove withdraws workloads; volumes and secrets are retained as
52	// owned orphans and the name stays reserved.
53	Remove(ctx context.Context, app, idempotencyKey string) (*domain.AppOperation, error)
54
55	// OperationByKey recovers an ambiguous mutation outcome by the
56	// client-supplied idempotency key.
57	OperationByKey(ctx context.Context, app, key string) (*domain.AppOperation, error)
58
59	// ListSecrets returns metadata-only desired and active registrations.
60	ListSecrets(ctx context.Context, app, service string) ([]AppSecretMetadata, error)
61
62	// SetSecrets writes secret values for pre-registered names in one
63	// service. service is required; every key must already exist in
64	// desired or active state.
65	SetSecrets(ctx context.Context, app, service string, values map[string]string) error
66
67	// DeleteSecret removes one secret value. Refused when referenced.
68	DeleteSecret(ctx context.Context, app, service, key string) error
69}
70
71// AppApplyResult describes one accepted (or no-op) apply.
72// AppSecretMetadata is a secret registration without its value.
73type AppSecretMetadata struct {
74	Service  string
75	Key      string
76	Name     string
77	Source   string
78	Presence string
79}
80
81type AppApplyResult struct {
82	App               string
83	FormerRevision    string
84	ResultingRevision string
85	Noop              bool
86	Pending           bool
87	Diff              domain.AppDiff
88	IntentID          string
89}
90
91// AppDryRunResult describes validation without persistence.
92// The resulting revision is a preview only and is never stored.
93type AppDryRunResult struct {
94	App   string
95	Valid bool
96	Diff  domain.AppDiff
97}
98
99// AppSummary is one row of the app list: revisions, acceptance status,
100// and the latest recorded outcome.
101type AppSummary struct {
102	App           string
103	Desired       string
104	DesiredStatus string
105	Active        string
106	Converged     bool
107	// Pending reports desired state that the active revision has not
108	// reached yet. It is derived from desired vs ACTIVE, never from a
109	// journal.
110	Pending     bool
111	Stopped     bool
112	LastOutcome string
113}
114
115// AppServiceView is one service's effective state for inspection.
116// Digest and container are ids, never secret values.
117type AppServiceView struct {
118	EffectiveRevision string
119	Digest            string
120	Container         string
121	RestartUnsafe     bool
122}
123
124// AppRetainedView lists the resources the app owns and would retain on
125// removal: runtime volume names, secret paths, and pinned image
126// references. It never carries secret values.
127type AppRetainedView struct {
128	Volumes []string
129	Secrets []string
130	Images  []string
131}
132
133// AppDetail inspects desired + active + intent + ownership + last op for
134// one app.
135type AppDetail struct {
136	App               string
137	DesiredRevision   string
138	DesiredStatus     string
139	Pending           bool
140	Converged         bool
141	ConvergedRevision string
142	Services          map[string]AppServiceView
143	Stopped           bool
144	Retained          AppRetainedView
145	LastOp            string
146	LastOpKind        string
147	LastOutcome       string
148	LastOpStartedAt   time.Time
149}

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 7

Tags 106

↑↓ moveenter openesc close