detached a025239

feat: add AttachmentReadinessTimeout config field

New deploy.attachment_readiness_timeout config option controls how long
Gordon waits for attachment containers (postgres, redis) to become ready
before starting the main app container.
commit
a02523919d9eb34926b823d056e51ab4747c39ce
author
brice · · 2026-03-23 19:06 UTC
parent
63e7f3a
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +55 -53
M internal/app/run.go +26 -25
@@ -1285,31 +1285,32 @@ func createContainerService(ctx context.Context, v *viper.Viper, cfg Config, svc
12851285 }
12861286
12871287 containerConfig := container.Config{
1288- RegistryAuthEnabled: cfg.Auth.Enabled,
1289- RegistryDomain: cfg.Server.RegistryDomain,
1290- RegistryPort: cfg.Server.RegistryPort,
1291- InternalRegistryUsername: svc.internalRegUser,
1292- InternalRegistryPassword: svc.internalRegPass,
1293- PullPolicy: v.GetString("deploy.pull_policy"),
1294- VolumeAutoCreate: v.GetBool("volumes.auto_create"),
1295- VolumePrefix: v.GetString("volumes.prefix"),
1296- VolumePreserve: v.GetBool("volumes.preserve"),
1297- NetworkIsolation: v.GetBool("network_isolation.enabled"),
1298- NetworkPrefix: v.GetString("network_isolation.network_prefix"),
1299- NetworkGroups: svc.configSvc.GetNetworkGroups(),
1300- Attachments: svc.configSvc.GetAttachments(),
1301- ReadinessDelay: v.GetDuration("deploy.readiness_delay"),
1302- ReadinessMode: v.GetString("deploy.readiness_mode"),
1303- HealthTimeout: v.GetDuration("deploy.health_timeout"),
1304- StabilizationDelay: v.GetDuration("deploy.stabilization_delay"),
1305- TCPProbeTimeout: v.GetDuration("deploy.tcp_probe_timeout"),
1306- HTTPProbeTimeout: v.GetDuration("deploy.http_probe_timeout"),
1307- DrainDelay: v.GetDuration("deploy.drain_delay"),
1308- DrainMode: v.GetString("deploy.drain_mode"),
1309- DrainTimeout: v.GetDuration("deploy.drain_timeout"),
1310- DefaultMemoryLimit: defaultMemoryLimit,
1311- DefaultNanoCPUs: defaultNanoCPUs,
1312- DefaultPidsLimit: cfg.Containers.PidsLimit,
1288+ RegistryAuthEnabled: cfg.Auth.Enabled,
1289+ RegistryDomain: cfg.Server.RegistryDomain,
1290+ RegistryPort: cfg.Server.RegistryPort,
1291+ InternalRegistryUsername: svc.internalRegUser,
1292+ InternalRegistryPassword: svc.internalRegPass,
1293+ PullPolicy: v.GetString("deploy.pull_policy"),
1294+ VolumeAutoCreate: v.GetBool("volumes.auto_create"),
1295+ VolumePrefix: v.GetString("volumes.prefix"),
1296+ VolumePreserve: v.GetBool("volumes.preserve"),
1297+ NetworkIsolation: v.GetBool("network_isolation.enabled"),
1298+ NetworkPrefix: v.GetString("network_isolation.network_prefix"),
1299+ NetworkGroups: svc.configSvc.GetNetworkGroups(),
1300+ Attachments: svc.configSvc.GetAttachments(),
1301+ ReadinessDelay: v.GetDuration("deploy.readiness_delay"),
1302+ ReadinessMode: v.GetString("deploy.readiness_mode"),
1303+ HealthTimeout: v.GetDuration("deploy.health_timeout"),
1304+ StabilizationDelay: v.GetDuration("deploy.stabilization_delay"),
1305+ TCPProbeTimeout: v.GetDuration("deploy.tcp_probe_timeout"),
1306+ HTTPProbeTimeout: v.GetDuration("deploy.http_probe_timeout"),
1307+ DrainDelay: v.GetDuration("deploy.drain_delay"),
1308+ DrainMode: v.GetString("deploy.drain_mode"),
1309+ DrainTimeout: v.GetDuration("deploy.drain_timeout"),
1310+ DefaultMemoryLimit: defaultMemoryLimit,
1311+ DefaultNanoCPUs: defaultNanoCPUs,
1312+ DefaultPidsLimit: cfg.Containers.PidsLimit,
1313+ AttachmentReadinessTimeout: v.GetDuration("deploy.attachment_readiness_timeout"),
13131314 }
13141315 if v.IsSet("deploy.drain_delay") {
13151316 containerConfig.DrainDelayConfigured = true
@@ -1285,31 +1285,32 @@ func createContainerService(ctx context.Context, v *viper.Viper, cfg Config, svc
1285 }1285 }
1286 1286
1287 containerConfig := container.Config{1287 containerConfig := container.Config{
1288- RegistryAuthEnabled: cfg.Auth.Enabled,1288+ RegistryAuthEnabled: cfg.Auth.Enabled,
1289- RegistryDomain: cfg.Server.RegistryDomain,1289+ RegistryDomain: cfg.Server.RegistryDomain,
1290- RegistryPort: cfg.Server.RegistryPort,1290+ RegistryPort: cfg.Server.RegistryPort,
1291- InternalRegistryUsername: svc.internalRegUser,1291+ InternalRegistryUsername: svc.internalRegUser,
1292- InternalRegistryPassword: svc.internalRegPass,1292+ InternalRegistryPassword: svc.internalRegPass,
1293- PullPolicy: v.GetString("deploy.pull_policy"),1293+ PullPolicy: v.GetString("deploy.pull_policy"),
1294- VolumeAutoCreate: v.GetBool("volumes.auto_create"),1294+ VolumeAutoCreate: v.GetBool("volumes.auto_create"),
1295- VolumePrefix: v.GetString("volumes.prefix"),1295+ VolumePrefix: v.GetString("volumes.prefix"),
1296- VolumePreserve: v.GetBool("volumes.preserve"),1296+ VolumePreserve: v.GetBool("volumes.preserve"),
1297- NetworkIsolation: v.GetBool("network_isolation.enabled"),1297+ NetworkIsolation: v.GetBool("network_isolation.enabled"),
1298- NetworkPrefix: v.GetString("network_isolation.network_prefix"),1298+ NetworkPrefix: v.GetString("network_isolation.network_prefix"),
1299- NetworkGroups: svc.configSvc.GetNetworkGroups(),1299+ NetworkGroups: svc.configSvc.GetNetworkGroups(),
1300- Attachments: svc.configSvc.GetAttachments(),1300+ Attachments: svc.configSvc.GetAttachments(),
1301- ReadinessDelay: v.GetDuration("deploy.readiness_delay"),1301+ ReadinessDelay: v.GetDuration("deploy.readiness_delay"),
1302- ReadinessMode: v.GetString("deploy.readiness_mode"),1302+ ReadinessMode: v.GetString("deploy.readiness_mode"),
1303- HealthTimeout: v.GetDuration("deploy.health_timeout"),1303+ HealthTimeout: v.GetDuration("deploy.health_timeout"),
1304- StabilizationDelay: v.GetDuration("deploy.stabilization_delay"),1304+ StabilizationDelay: v.GetDuration("deploy.stabilization_delay"),
1305- TCPProbeTimeout: v.GetDuration("deploy.tcp_probe_timeout"),1305+ TCPProbeTimeout: v.GetDuration("deploy.tcp_probe_timeout"),
1306- HTTPProbeTimeout: v.GetDuration("deploy.http_probe_timeout"),1306+ HTTPProbeTimeout: v.GetDuration("deploy.http_probe_timeout"),
1307- DrainDelay: v.GetDuration("deploy.drain_delay"),1307+ DrainDelay: v.GetDuration("deploy.drain_delay"),
1308- DrainMode: v.GetString("deploy.drain_mode"),1308+ DrainMode: v.GetString("deploy.drain_mode"),
1309- DrainTimeout: v.GetDuration("deploy.drain_timeout"),1309+ DrainTimeout: v.GetDuration("deploy.drain_timeout"),
1310- DefaultMemoryLimit: defaultMemoryLimit,1310+ DefaultMemoryLimit: defaultMemoryLimit,
1311- DefaultNanoCPUs: defaultNanoCPUs,1311+ DefaultNanoCPUs: defaultNanoCPUs,
1312- DefaultPidsLimit: cfg.Containers.PidsLimit,1312+ DefaultPidsLimit: cfg.Containers.PidsLimit,
1313+ AttachmentReadinessTimeout: v.GetDuration("deploy.attachment_readiness_timeout"),
1313 }1314 }
1314 if v.IsSet("deploy.drain_delay") {1315 if v.IsSet("deploy.drain_delay") {
1315 containerConfig.DrainDelayConfigured = true1316 containerConfig.DrainDelayConfigured = true
M internal/usecase/container/service.go +29 -28
@@ -26,34 +26,35 @@ import (
2626
2727 // Config holds configuration needed by the container service.
2828 type Config struct {
29- RegistryAuthEnabled bool
30- RegistryDomain string
31- RegistryPort int
32- ServiceTokenUsername string
33- ServiceToken string
34- InternalRegistryUsername string
35- InternalRegistryPassword string
36- PullPolicy string
37- VolumeAutoCreate bool
38- VolumePrefix string
39- VolumePreserve bool
40- NetworkIsolation bool
41- NetworkPrefix string
42- NetworkGroups map[string][]string
43- Attachments map[string][]string
44- ReadinessDelay time.Duration // Delay after container starts before considering it ready
45- ReadinessMode string // Readiness strategy: auto, docker-health, delay
46- HealthTimeout time.Duration // Max wait for health-based readiness
47- DrainDelay time.Duration // Grace period after cache invalidation before stopping old container
48- DrainDelayConfigured bool // True when deploy.drain_delay was explicitly configured
49- DrainMode string // Drain strategy: auto, inflight, delay
50- DrainTimeout time.Duration // Max wait for in-flight requests to drain
51- StabilizationDelay time.Duration // Post-switch monitoring window (default 2s)
52- TCPProbeTimeout time.Duration // TCP probe timeout (default 30s)
53- HTTPProbeTimeout time.Duration // HTTP probe timeout (default 60s)
54- DefaultMemoryLimit int64 // Default memory limit in bytes for containers (0 = no limit)
55- DefaultNanoCPUs int64 // Default CPU quota in nanoseconds for containers (0 = no limit)
56- DefaultPidsLimit int64 // Default max PIDs for containers (0 = no limit)
29+ RegistryAuthEnabled bool
30+ RegistryDomain string
31+ RegistryPort int
32+ ServiceTokenUsername string
33+ ServiceToken string
34+ InternalRegistryUsername string
35+ InternalRegistryPassword string
36+ PullPolicy string
37+ VolumeAutoCreate bool
38+ VolumePrefix string
39+ VolumePreserve bool
40+ NetworkIsolation bool
41+ NetworkPrefix string
42+ NetworkGroups map[string][]string
43+ Attachments map[string][]string
44+ ReadinessDelay time.Duration // Delay after container starts before considering it ready
45+ ReadinessMode string // Readiness strategy: auto, docker-health, delay
46+ HealthTimeout time.Duration // Max wait for health-based readiness
47+ DrainDelay time.Duration // Grace period after cache invalidation before stopping old container
48+ DrainDelayConfigured bool // True when deploy.drain_delay was explicitly configured
49+ DrainMode string // Drain strategy: auto, inflight, delay
50+ DrainTimeout time.Duration // Max wait for in-flight requests to drain
51+ StabilizationDelay time.Duration // Post-switch monitoring window (default 2s)
52+ TCPProbeTimeout time.Duration // TCP probe timeout (default 30s)
53+ HTTPProbeTimeout time.Duration // HTTP probe timeout (default 60s)
54+ AttachmentReadinessTimeout time.Duration // Max wait for attachment readiness (default 30s)
55+ DefaultMemoryLimit int64 // Default memory limit in bytes for containers (0 = no limit)
56+ DefaultNanoCPUs int64 // Default CPU quota in nanoseconds for containers (0 = no limit)
57+ DefaultPidsLimit int64 // Default max PIDs for containers (0 = no limit)
5758 }
5859
5960 var tracer = otel.Tracer("gordon.container")
@@ -26,34 +26,35 @@ import (
26 26
27 // Config holds configuration needed by the container service.27 // Config holds configuration needed by the container service.
28 type Config struct {28 type Config struct {
29- RegistryAuthEnabled bool29+ RegistryAuthEnabled bool
30- RegistryDomain string30+ RegistryDomain string
31- RegistryPort int31+ RegistryPort int
32- ServiceTokenUsername string32+ ServiceTokenUsername string
33- ServiceToken string33+ ServiceToken string
34- InternalRegistryUsername string34+ InternalRegistryUsername string
35- InternalRegistryPassword string35+ InternalRegistryPassword string
36- PullPolicy string36+ PullPolicy string
37- VolumeAutoCreate bool37+ VolumeAutoCreate bool
38- VolumePrefix string38+ VolumePrefix string
39- VolumePreserve bool39+ VolumePreserve bool
40- NetworkIsolation bool40+ NetworkIsolation bool
41- NetworkPrefix string41+ NetworkPrefix string
42- NetworkGroups map[string][]string42+ NetworkGroups map[string][]string
43- Attachments map[string][]string43+ Attachments map[string][]string
44- ReadinessDelay time.Duration // Delay after container starts before considering it ready44+ ReadinessDelay time.Duration // Delay after container starts before considering it ready
45- ReadinessMode string // Readiness strategy: auto, docker-health, delay45+ ReadinessMode string // Readiness strategy: auto, docker-health, delay
46- HealthTimeout time.Duration // Max wait for health-based readiness46+ HealthTimeout time.Duration // Max wait for health-based readiness
47- DrainDelay time.Duration // Grace period after cache invalidation before stopping old container47+ DrainDelay time.Duration // Grace period after cache invalidation before stopping old container
48- DrainDelayConfigured bool // True when deploy.drain_delay was explicitly configured48+ DrainDelayConfigured bool // True when deploy.drain_delay was explicitly configured
49- DrainMode string // Drain strategy: auto, inflight, delay49+ DrainMode string // Drain strategy: auto, inflight, delay
50- DrainTimeout time.Duration // Max wait for in-flight requests to drain50+ DrainTimeout time.Duration // Max wait for in-flight requests to drain
51- StabilizationDelay time.Duration // Post-switch monitoring window (default 2s)51+ StabilizationDelay time.Duration // Post-switch monitoring window (default 2s)
52- TCPProbeTimeout time.Duration // TCP probe timeout (default 30s)52+ TCPProbeTimeout time.Duration // TCP probe timeout (default 30s)
53- HTTPProbeTimeout time.Duration // HTTP probe timeout (default 60s)53+ HTTPProbeTimeout time.Duration // HTTP probe timeout (default 60s)
54- DefaultMemoryLimit int64 // Default memory limit in bytes for containers (0 = no limit)54+ AttachmentReadinessTimeout time.Duration // Max wait for attachment readiness (default 30s)
55- DefaultNanoCPUs int64 // Default CPU quota in nanoseconds for containers (0 = no limit)55+ DefaultMemoryLimit int64 // Default memory limit in bytes for containers (0 = no limit)
56- DefaultPidsLimit int64 // Default max PIDs for containers (0 = no limit)56+ DefaultNanoCPUs int64 // Default CPU quota in nanoseconds for containers (0 = no limit)
57+ DefaultPidsLimit int64 // Default max PIDs for containers (0 = no limit)
57 }58 }
58 59
59 var tracer = otel.Tracer("gordon.container")60 var tracer = otel.Tracer("gordon.container")

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