Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,54 @@ jobs:

Pin to a specific date-stamped tag (e.g. `go1.26:20240419-42`) for fully reproducible workflows.

## Advanced Features

### Tool Installation Hooks

You can customize tool installation by adding pre-install or post-install hooks. Hooks are Go templates placed in the `hooks/` directory that inject additional Dockerfile commands before or after a tool is installed.

**Hook naming convention:**
- `hooks/{toolname}-pre.tmpl` - runs before tool installation
- `hooks/{toolname}-post.tmpl` - runs after tool installation

**Use cases:**
- Create directories or configuration files before installation
- Run custom install scripts that come with the tool
- Set up environment variables or permissions
- Clean up temporary files after installation

**Example pre-hook:**
```dockerfile
# hooks/mytool-pre.tmpl
RUN mkdir -p /opt/mytool-config
RUN echo "config_option=value" > /opt/mytool-config/settings.conf
```

**Example post-hook:**
```dockerfile
# hooks/mytool-post.tmpl
RUN /var/ci-tools/mytool/install.sh --daemon
RUN chmod +x /usr/local/bin/mytool
```

**Accessing tool files:** For tools that include install scripts or other files, set `install_to_path: false` in the `release:` block in `deps.yaml`. This extracts the tool to `/var/ci-tools/{toolname}/` instead of installing directly to `/usr/local/bin`, making all files available to hooks:

```yaml
tools:
- name: mytool
source: owner/repo
version: v1.0.0
checksums:
linux/amd64: "checksum-here"
linux/arm64: "checksum-here"
release:
download_template: "mytool-{version}-{os}-{arch}.tar.gz"
extract: "mytool-{version}-{os}-{arch}"
install_to_path: false # Extract to /var/ci-tools/mytool/ for hooks
```

Hook changes are automatically tracked in the changelog and `images-lock.yaml` with MD5 checksums, ensuring any modification triggers a rebuild of affected images.

---

For adding tools, new Go versions, or modifying the build system, see [CONTRIBUTING.md](CONTRIBUTING.md).
17 changes: 12 additions & 5 deletions dockerfiles/Dockerfile.charts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ RUN zypper -n refresh && \
zypper -n clean -a && \
rm -rf /var/log/{lastlog,tallylog,zypper.log,zypp/history,YaST2}

# Create runner group (GID 121) and user (UID 1001) early for use in tool installations.
# /var/ci-tools/ is set up with setgid (2755) so subdirectories inherit the runner group.
# This allows any user added to the runner group to access tools extracted to /var/ci-tools/.
RUN groupadd -g 121 runner && \
useradd -u 1001 -g 121 -m runner && \
mkdir -p /var/ci-tools && \
chown root:runner /var/ci-tools && \
chmod 2755 /var/ci-tools

# cosign v3.0.6
RUN case "${ARCH}" in \
amd64) CHECKSUM="c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74" ;; \
Expand Down Expand Up @@ -221,11 +230,9 @@ COPY dockerfiles/scripts/select-helm.sh /usr/local/bin/select-helm
COPY dockerfiles/scripts/ci-select.sh /usr/local/bin/ci-select
RUN chmod +x /usr/local/bin/select-helm && chmod +x /usr/local/bin/ci-select

# Create a new group with GID 121 and a new user with UID 1001, add the user
# to the group, create a home directory for the user.
# Also set up CI tool family infrastructure (requires runner group to exist).
RUN groupadd -g 121 runner && useradd -u 1001 -g 121 -m runner \
&& mkdir -p /var/ci-tools/active \

# Set up CI tool family infrastructure (runner user and group created earlier).
RUN mkdir -p /var/ci-tools/active \
&& mkdir -p /usr/local/share/ci-tools/families/helm \
&& touch /usr/local/share/ci-tools/families/helm/helmv3 \
&& touch /usr/local/share/ci-tools/families/helm/helmv4 \
Expand Down
17 changes: 12 additions & 5 deletions dockerfiles/Dockerfile.go1.25
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ RUN zypper -n refresh && \
zypper -n clean -a && \
rm -rf /var/log/{lastlog,tallylog,zypper.log,zypp/history,YaST2}

# Create runner group (GID 121) and user (UID 1001) early for use in tool installations.
# /var/ci-tools/ is set up with setgid (2755) so subdirectories inherit the runner group.
# This allows any user added to the runner group to access tools extracted to /var/ci-tools/.
RUN groupadd -g 121 runner && \
useradd -u 1001 -g 121 -m runner && \
mkdir -p /var/ci-tools && \
chown root:runner /var/ci-tools && \
chmod 2755 /var/ci-tools

# cosign v3.0.6
RUN case "${ARCH}" in \
amd64) CHECKSUM="c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74" ;; \
Expand Down Expand Up @@ -196,11 +205,9 @@ RUN ln -sf /usr/local/bin/helmv3 /usr/local/bin/helm_v3
# Cleanup Go caches
RUN go clean -cache -modcache

# Create a new group with GID 121 and a new user with UID 1001, add the user
# to the group, create a home directory for the user.
# Also set up CI tool family infrastructure (requires runner group to exist).
RUN groupadd -g 121 runner && useradd -u 1001 -g 121 -m runner \
&& mkdir -p /var/ci-tools/active \

# Set up CI tool family infrastructure (runner user and group created earlier).
RUN mkdir -p /var/ci-tools/active \
&& mkdir -p /usr/local/share/ci-tools/families/helm \
&& touch /usr/local/share/ci-tools/families/helm/helmv3 \
&& touch /usr/local/share/ci-tools/families/helm/helmv4 \
Expand Down
17 changes: 12 additions & 5 deletions dockerfiles/Dockerfile.go1.26
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ RUN zypper -n refresh && \
zypper -n clean -a && \
rm -rf /var/log/{lastlog,tallylog,zypper.log,zypp/history,YaST2}

# Create runner group (GID 121) and user (UID 1001) early for use in tool installations.
# /var/ci-tools/ is set up with setgid (2755) so subdirectories inherit the runner group.
# This allows any user added to the runner group to access tools extracted to /var/ci-tools/.
RUN groupadd -g 121 runner && \
useradd -u 1001 -g 121 -m runner && \
mkdir -p /var/ci-tools && \
chown root:runner /var/ci-tools && \
chmod 2755 /var/ci-tools

# cosign v3.0.6
RUN case "${ARCH}" in \
amd64) CHECKSUM="c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74" ;; \
Expand Down Expand Up @@ -196,11 +205,9 @@ RUN ln -sf /usr/local/bin/helmv3 /usr/local/bin/helm_v3
# Cleanup Go caches
RUN go clean -cache -modcache

# Create a new group with GID 121 and a new user with UID 1001, add the user
# to the group, create a home directory for the user.
# Also set up CI tool family infrastructure (requires runner group to exist).
RUN groupadd -g 121 runner && useradd -u 1001 -g 121 -m runner \
&& mkdir -p /var/ci-tools/active \

# Set up CI tool family infrastructure (runner user and group created earlier).
RUN mkdir -p /var/ci-tools/active \
&& mkdir -p /usr/local/share/ci-tools/families/helm \
&& touch /usr/local/share/ci-tools/families/helm/helmv3 \
&& touch /usr/local/share/ci-tools/families/helm/helmv4 \
Expand Down
17 changes: 12 additions & 5 deletions dockerfiles/Dockerfile.node22
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ RUN zypper -n refresh && \
zypper -n clean -a && \
rm -rf /var/log/{lastlog,tallylog,zypper.log,zypp/history,YaST2}

# Create runner group (GID 121) and user (UID 1001) early for use in tool installations.
# /var/ci-tools/ is set up with setgid (2755) so subdirectories inherit the runner group.
# This allows any user added to the runner group to access tools extracted to /var/ci-tools/.
RUN groupadd -g 121 runner && \
useradd -u 1001 -g 121 -m runner && \
mkdir -p /var/ci-tools && \
chown root:runner /var/ci-tools && \
chmod 2755 /var/ci-tools

# cosign v3.0.6
RUN case "${ARCH}" in \
amd64) CHECKSUM="c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74" ;; \
Expand Down Expand Up @@ -128,11 +137,9 @@ COPY dockerfiles/scripts/select-helm.sh /usr/local/bin/select-helm
COPY dockerfiles/scripts/ci-select.sh /usr/local/bin/ci-select
RUN chmod +x /usr/local/bin/select-helm && chmod +x /usr/local/bin/ci-select

# Create a new group with GID 121 and a new user with UID 1001, add the user
# to the group, create a home directory for the user.
# Also set up CI tool family infrastructure (requires runner group to exist).
RUN groupadd -g 121 runner && useradd -u 1001 -g 121 -m runner \
&& mkdir -p /var/ci-tools/active \

# Set up CI tool family infrastructure (runner user and group created earlier).
RUN mkdir -p /var/ci-tools/active \
&& mkdir -p /usr/local/share/ci-tools/families/helm \
&& touch /usr/local/share/ci-tools/families/helm/helmv3 \
&& touch /usr/local/share/ci-tools/families/helm/helmv4 \
Expand Down
17 changes: 12 additions & 5 deletions dockerfiles/Dockerfile.node24
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ RUN zypper -n refresh && \
zypper -n clean -a && \
rm -rf /var/log/{lastlog,tallylog,zypper.log,zypp/history,YaST2}

# Create runner group (GID 121) and user (UID 1001) early for use in tool installations.
# /var/ci-tools/ is set up with setgid (2755) so subdirectories inherit the runner group.
# This allows any user added to the runner group to access tools extracted to /var/ci-tools/.
RUN groupadd -g 121 runner && \
useradd -u 1001 -g 121 -m runner && \
mkdir -p /var/ci-tools && \
chown root:runner /var/ci-tools && \
chmod 2755 /var/ci-tools

# cosign v3.0.6
RUN case "${ARCH}" in \
amd64) CHECKSUM="c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74" ;; \
Expand Down Expand Up @@ -128,11 +137,9 @@ COPY dockerfiles/scripts/select-helm.sh /usr/local/bin/select-helm
COPY dockerfiles/scripts/ci-select.sh /usr/local/bin/ci-select
RUN chmod +x /usr/local/bin/select-helm && chmod +x /usr/local/bin/ci-select

# Create a new group with GID 121 and a new user with UID 1001, add the user
# to the group, create a home directory for the user.
# Also set up CI tool family infrastructure (requires runner group to exist).
RUN groupadd -g 121 runner && useradd -u 1001 -g 121 -m runner \
&& mkdir -p /var/ci-tools/active \

# Set up CI tool family infrastructure (runner user and group created earlier).
RUN mkdir -p /var/ci-tools/active \
&& mkdir -p /usr/local/share/ci-tools/families/helm \
&& touch /usr/local/share/ci-tools/families/helm/helmv3 \
&& touch /usr/local/share/ci-tools/families/helm/helmv4 \
Expand Down
17 changes: 12 additions & 5 deletions dockerfiles/Dockerfile.python3.11
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ RUN zypper -n refresh && \
zypper -n clean -a && \
rm -rf /var/log/{lastlog,tallylog,zypper.log,zypp/history,YaST2}

# Create runner group (GID 121) and user (UID 1001) early for use in tool installations.
# /var/ci-tools/ is set up with setgid (2755) so subdirectories inherit the runner group.
# This allows any user added to the runner group to access tools extracted to /var/ci-tools/.
RUN groupadd -g 121 runner && \
useradd -u 1001 -g 121 -m runner && \
mkdir -p /var/ci-tools && \
chown root:runner /var/ci-tools && \
chmod 2755 /var/ci-tools

# cosign v3.0.6
RUN case "${ARCH}" in \
amd64) CHECKSUM="c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74" ;; \
Expand Down Expand Up @@ -128,11 +137,9 @@ COPY dockerfiles/scripts/select-helm.sh /usr/local/bin/select-helm
COPY dockerfiles/scripts/ci-select.sh /usr/local/bin/ci-select
RUN chmod +x /usr/local/bin/select-helm && chmod +x /usr/local/bin/ci-select

# Create a new group with GID 121 and a new user with UID 1001, add the user
# to the group, create a home directory for the user.
# Also set up CI tool family infrastructure (requires runner group to exist).
RUN groupadd -g 121 runner && useradd -u 1001 -g 121 -m runner \
&& mkdir -p /var/ci-tools/active \

# Set up CI tool family infrastructure (runner user and group created earlier).
RUN mkdir -p /var/ci-tools/active \
&& mkdir -p /usr/local/share/ci-tools/families/helm \
&& touch /usr/local/share/ci-tools/families/helm/helmv3 \
&& touch /usr/local/share/ci-tools/families/helm/helmv4 \
Expand Down
17 changes: 12 additions & 5 deletions dockerfiles/Dockerfile.python3.13
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ RUN zypper -n refresh && \
zypper -n clean -a && \
rm -rf /var/log/{lastlog,tallylog,zypper.log,zypp/history,YaST2}

# Create runner group (GID 121) and user (UID 1001) early for use in tool installations.
# /var/ci-tools/ is set up with setgid (2755) so subdirectories inherit the runner group.
# This allows any user added to the runner group to access tools extracted to /var/ci-tools/.
RUN groupadd -g 121 runner && \
useradd -u 1001 -g 121 -m runner && \
mkdir -p /var/ci-tools && \
chown root:runner /var/ci-tools && \
chmod 2755 /var/ci-tools

# cosign v3.0.6
RUN case "${ARCH}" in \
amd64) CHECKSUM="c956e5dfcac53d52bcf058360d579472f0c1d2d9b69f55209e256fe7783f4c74" ;; \
Expand Down Expand Up @@ -128,11 +137,9 @@ COPY dockerfiles/scripts/select-helm.sh /usr/local/bin/select-helm
COPY dockerfiles/scripts/ci-select.sh /usr/local/bin/ci-select
RUN chmod +x /usr/local/bin/select-helm && chmod +x /usr/local/bin/ci-select

# Create a new group with GID 121 and a new user with UID 1001, add the user
# to the group, create a home directory for the user.
# Also set up CI tool family infrastructure (requires runner group to exist).
RUN groupadd -g 121 runner && useradd -u 1001 -g 121 -m runner \
&& mkdir -p /var/ci-tools/active \

# Set up CI tool family infrastructure (runner user and group created earlier).
RUN mkdir -p /var/ci-tools/active \
&& mkdir -p /usr/local/share/ci-tools/families/helm \
&& touch /usr/local/share/ci-tools/families/helm/helmv3 \
&& touch /usr/local/share/ci-tools/families/helm/helmv4 \
Expand Down
11 changes: 11 additions & 0 deletions internal/changelog/changelog.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,17 @@ func renderEntry(entry Entry) string {
for _, sc := range ic.SelectorDefaultChanged {
fmt.Fprintf(&sb, "- `%s` selector default: `%s` → `%s`\n", sc.Family, sc.From, sc.To)
}
for _, hc := range ic.ToolHooksChanged {
switch hc.ChangeType {
case "added":
fmt.Fprintf(&sb, "- `%s`: added %s-install hook (`%s`)\n", hc.Tool, hc.HookType, hc.NewChecksum[:8])
case "removed":
fmt.Fprintf(&sb, "- `%s`: removed %s-install hook\n", hc.Tool, hc.HookType)
case "modified":
fmt.Fprintf(&sb, "- `%s`: updated %s-install hook (`%s` → `%s`)\n",
hc.Tool, hc.HookType, hc.OldChecksum[:8], hc.NewChecksum[:8])
}
}
if len(entry.Changes.PackagesAdded) > 0 || len(entry.Changes.PackagesRemoved) > 0 {
sb.WriteString("- Universal package changes\n")
}
Expand Down
73 changes: 71 additions & 2 deletions internal/changelog/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func Diff(prev, next *ImagesLock) *Changes {
}
prevCfg := prev.Configs[imgName]
nextCfg := next.Configs[imgName]
ic := computeImageChanges(imgName, prev.Tools, next.Tools, prevCfg, nextCfg)
ic := computeImageChanges(imgName, prev.Tools, next.Tools, prev.Hooks, next.Hooks, prevCfg, nextCfg)
if ic.HasChanges() {
c.ImageChanges = append(c.ImageChanges, ic)
}
Expand All @@ -132,7 +132,7 @@ func Diff(prev, next *ImagesLock) *Changes {
return c
}

func computeImageChanges(imgName string, prevTools, nextTools map[string]string, prev, next ImageConfig) ImageChanges {
func computeImageChanges(imgName string, prevTools, nextTools map[string]string, prevHooks, nextHooks map[string]HookFiles, prev, next ImageConfig) ImageChanges {
ic := ImageChanges{Image: imgName}

if prev.Base != next.Base {
Expand Down Expand Up @@ -190,6 +190,75 @@ func computeImageChanges(imgName string, prevTools, nextTools map[string]string,
slices.SortFunc(ic.ToolsRemoved, func(a, b ToolChange) int { return strings.Compare(a.Tool, b.Tool) })
slices.SortFunc(ic.ToolVersionChanged, func(a, b ToolVersionChange) int { return strings.Compare(a.Tool, b.Tool) })

// Hook template changes: detect when hooks are added, removed, or modified.
// Only check hooks for tools that are actually in this image.
for _, toolName := range next.Tools {
prevHook := prevHooks[toolName]
nextHook := nextHooks[toolName]

// Check pre-hook changes
if prevHook.Pre == nil && nextHook.Pre != nil {
// Pre-hook added
ic.ToolHooksChanged = append(ic.ToolHooksChanged, ToolHookChange{
Tool: toolName,
HookType: "pre",
ChangeType: "added",
NewChecksum: nextHook.Pre.Checksum,
})
} else if prevHook.Pre != nil && nextHook.Pre == nil {
// Pre-hook removed
ic.ToolHooksChanged = append(ic.ToolHooksChanged, ToolHookChange{
Tool: toolName,
HookType: "pre",
ChangeType: "removed",
OldChecksum: prevHook.Pre.Checksum,
})
} else if prevHook.Pre != nil && nextHook.Pre != nil && prevHook.Pre.Checksum != nextHook.Pre.Checksum {
// Pre-hook modified
ic.ToolHooksChanged = append(ic.ToolHooksChanged, ToolHookChange{
Tool: toolName,
HookType: "pre",
ChangeType: "modified",
OldChecksum: prevHook.Pre.Checksum,
NewChecksum: nextHook.Pre.Checksum,
})
}

// Check post-hook changes
if prevHook.Post == nil && nextHook.Post != nil {
// Post-hook added
ic.ToolHooksChanged = append(ic.ToolHooksChanged, ToolHookChange{
Tool: toolName,
HookType: "post",
ChangeType: "added",
NewChecksum: nextHook.Post.Checksum,
})
} else if prevHook.Post != nil && nextHook.Post == nil {
// Post-hook removed
ic.ToolHooksChanged = append(ic.ToolHooksChanged, ToolHookChange{
Tool: toolName,
HookType: "post",
ChangeType: "removed",
OldChecksum: prevHook.Post.Checksum,
})
} else if prevHook.Post != nil && nextHook.Post != nil && prevHook.Post.Checksum != nextHook.Post.Checksum {
// Post-hook modified
ic.ToolHooksChanged = append(ic.ToolHooksChanged, ToolHookChange{
Tool: toolName,
HookType: "post",
ChangeType: "modified",
OldChecksum: prevHook.Post.Checksum,
NewChecksum: nextHook.Post.Checksum,
})
}
}
slices.SortFunc(ic.ToolHooksChanged, func(a, b ToolHookChange) int {
if a.Tool != b.Tool {
return strings.Compare(a.Tool, b.Tool)
}
return strings.Compare(a.HookType, b.HookType)
})

// Alias diffs: an alias is "removed" if its name disappears or its target changes.
for name, prevTarget := range prev.Aliases {
nextTarget, ok := next.Aliases[name]
Expand Down
Loading