Skip to content
This repository was archived by the owner on Apr 15, 2026. It is now read-only.

Commit 20c4e36

Browse files
jmgilmanclaude
andauthored
refactor(instance): remove container image label support (#51)
* refactor(instance): remove container image label support Current behavior: Container runtime flags could be configured via OCI image labels (io.headjack.init, io.headjack.podman.flags, io.headjack.docker.flags). The instance manager fetched image metadata from the registry and merged label-based flags with config file flags. New behavior: Runtime flags are now exclusively configured via the config file (runtime.flags in config.yaml). The registry package and all label parsing code have been removed. This simplifies the codebase and removes the dependency on registry metadata fetching. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(docs): remove labels.md from sidebar Current behavior: Sidebar referenced the deleted labels.md file, causing Docusaurus build to fail on Cloudflare. New behavior: Sidebar only references the overview page for container images. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent ebb321c commit 20c4e36

13 files changed

Lines changed: 57 additions & 1128 deletions

File tree

docs/docs/reference/images/labels.md

Lines changed: 0 additions & 205 deletions
This file was deleted.

docs/docs/reference/images/overview.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,3 @@ For complete image specifications, see the Dockerfiles in the repository:
113113
- [Base Dockerfile](https://github.com/GilmanLab/headjack/blob/master/images/base/Dockerfile)
114114
- [Systemd Dockerfile](https://github.com/GilmanLab/headjack/blob/master/images/systemd/Dockerfile)
115115
- [Docker-in-Docker Dockerfile](https://github.com/GilmanLab/headjack/blob/master/images/dind/Dockerfile)
116-
117-
## See Also
118-
119-
- [OCI Labels](labels.md) - Labels for custom image configuration

docs/sidebars.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ const sidebars: SidebarsConfig = {
118118
},
119119
items: [
120120
'reference/images/overview',
121-
'reference/images/labels',
122121
],
123122
},
124123
],

images/systemd/Dockerfile

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,5 @@ STOPSIGNAL SIGRTMIN+3
4343
# Volume for cgroups (required for systemd)
4444
VOLUME ["/sys/fs/cgroup"]
4545

46-
# =============================================================================
47-
# Headjack Runtime Configuration Labels
48-
# =============================================================================
49-
50-
# These labels inform Headjack how to run the image:
51-
# - io.headjack.init: Command to run as PID 1 (overrides "sleep infinity" default)
52-
# - io.headjack.podman.flags: Space-separated key=value pairs for Podman flags
53-
# - io.headjack.docker.flags: Space-separated key=value pairs for Docker flags
54-
LABEL io.headjack.init="/lib/systemd/systemd"
55-
LABEL io.headjack.podman.flags="systemd=always"
56-
LABEL io.headjack.docker.flags="privileged=true cgroupns=host volume=/sys/fs/cgroup:/sys/fs/cgroup:rw"
57-
5846
# systemd as init system
5947
CMD ["/lib/systemd/systemd"]

internal/cmd/root.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/jmgilman/headjack/internal/git"
2222
"github.com/jmgilman/headjack/internal/instance"
2323
"github.com/jmgilman/headjack/internal/multiplexer"
24-
"github.com/jmgilman/headjack/internal/registry"
2524
)
2625

2726
// baseDeps lists the external binaries that must always be available.
@@ -176,19 +175,16 @@ func initManager() error {
176175
// Use tmux as the terminal multiplexer
177176
mux := multiplexer.NewTmux(executor)
178177

179-
// Create registry client for fetching image metadata
180-
regClient := registry.NewClient(registry.ClientConfig{})
181-
182178
// Map runtime name to RuntimeType
183179
runtimeType := runtimeNameToType(runtimeName)
184180

185-
// Parse config flags for merging with image label flags
181+
// Parse config flags
186182
configFlags, err := getConfigFlags()
187183
if err != nil {
188184
return err
189185
}
190186

191-
mgr = instance.NewManager(store, runtime, opener, mux, regClient, instance.ManagerConfig{
187+
mgr = instance.NewManager(store, runtime, opener, mux, instance.ManagerConfig{
192188
WorktreesDir: worktreesDir,
193189
LogsDir: logsDir,
194190
RuntimeType: runtimeType,

internal/flags/flags.go

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"errors"
66
"fmt"
77
"sort"
8-
"strings"
98
)
109

1110
// Flags represents runtime flags as a key-value map.
@@ -55,61 +54,6 @@ func FromConfig(cfg map[string]any) (Flags, error) {
5554
return result, nil
5655
}
5756

58-
// FromLabel parses a space-separated string of key=value pairs into Flags.
59-
// Format: "key1=value1 key2=value2 boolkey=true barekey"
60-
//
61-
// Rules:
62-
// - "key=value" → string value
63-
// - "key=true" or "key=false" → bool value
64-
// - "key" (bare, no =) → bool true
65-
// - Repeated keys become []string (e.g., "vol=/a vol=/b" → {"vol": ["/a", "/b"]})
66-
// - Values containing = are handled correctly (splits on first = only)
67-
func FromLabel(label string) (Flags, error) {
68-
result := make(Flags)
69-
if label == "" {
70-
return result, nil
71-
}
72-
73-
for _, part := range strings.Fields(label) {
74-
key, value, hasEquals := strings.Cut(part, "=")
75-
if key == "" {
76-
continue // Skip empty keys
77-
}
78-
79-
if !hasEquals {
80-
// Bare key treated as boolean true (e.g., "privileged")
81-
result[key] = true
82-
continue
83-
}
84-
85-
// Check for boolean string values
86-
switch strings.ToLower(value) {
87-
case "true":
88-
result[key] = true
89-
continue
90-
case "false":
91-
result[key] = false
92-
continue
93-
}
94-
95-
// Handle repeated keys by converting to array
96-
if existing, ok := result[key]; ok {
97-
switch e := existing.(type) {
98-
case string:
99-
result[key] = []string{e, value}
100-
case []string:
101-
result[key] = append(e, value)
102-
default:
103-
// Overwrite non-string values (e.g., bool) with the new string
104-
result[key] = value
105-
}
106-
} else {
107-
result[key] = value
108-
}
109-
}
110-
return result, nil
111-
}
112-
11357
// Merge combines two Flags maps with override taking precedence.
11458
// Keys in override replace keys in base.
11559
func Merge(base, override Flags) Flags {

0 commit comments

Comments
 (0)