Bake git/yq/bash/python3/curl into a custom docker-cli image
Replaces per-build on-demand installs (apk add bash/python3/curl,
curl-downloading yq to /tmp) in runHooks.groovy, syncArgoApp.groovy,
and updateHelmTag.groovy with a single custom image
(build-tools.Dockerfile) that has all of it baked in once, at
image-build time — not repeated on every single pipeline run.
updateHelmTag.groovy also now runs inside container('docker-cli')
(previously unwrapped, defaulting to the auto-injected jnlp agent
container, which is why it needed the curl-downloaded yq fallback in
the first place — that container has git but not yq).
dind-pod.yaml's docker-cli container now points at
harbor.192.168.1.7.nip.io/homelab/build-tools:1 instead of the stock
docker:27-cli — this image needs building and pushing once before any
build using this pod template will work; see build-tools.Dockerfile's
header comment.
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
# Custom docker-cli image for dind-pod.yaml's docker-cli container —
|
||||||
|
# bakes in everything the pipeline stages need at runtime (git, yq,
|
||||||
|
# bash, python3 + pip/venv for runHooks' python hooks, curl) so nothing
|
||||||
|
# gets apk-installed or curl-downloaded on every single build. Rebuild
|
||||||
|
# and push this (see the one-off build commands in the commit that
|
||||||
|
# added this file) whenever this list changes; dind-pod.yaml pins the
|
||||||
|
# resulting image tag explicitly, so a rebuild doesn't silently roll
|
||||||
|
# out until that pin is also bumped.
|
||||||
|
FROM docker:27-cli
|
||||||
|
|
||||||
|
RUN apk add --no-cache git bash python3 py3-pip py3-virtualenv curl \
|
||||||
|
&& curl -sL -o /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 \
|
||||||
|
&& chmod +x /usr/local/bin/yq
|
||||||
@@ -33,7 +33,14 @@ spec:
|
|||||||
- name: docker-graph-storage
|
- name: docker-graph-storage
|
||||||
mountPath: /var/lib/docker
|
mountPath: /var/lib/docker
|
||||||
- name: docker-cli
|
- name: docker-cli
|
||||||
image: docker:27-cli
|
# Custom image (see build-tools.Dockerfile in this same directory)
|
||||||
|
# — bakes in git/yq/bash/python3+pip/venv/curl so nothing needs
|
||||||
|
# apk-installing or curl-downloading on every single build (was
|
||||||
|
# slow and, per its own point, defeats the purpose of a
|
||||||
|
# reproducible pipeline to be quietly downloading a tool binary
|
||||||
|
# fresh on every run). Versioned tag, not :latest — a rebuild of
|
||||||
|
# the tools image doesn't roll out until this pin is bumped too.
|
||||||
|
image: harbor.192.168.1.7.nip.io/homelab/build-tools:1
|
||||||
command: ["cat"]
|
command: ["cat"]
|
||||||
tty: true
|
tty: true
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -93,21 +93,15 @@ def buildRunCommand(String script, String interpreter, String requirements) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean isPython = (interp == 'python3' || interp == 'python' || script.endsWith('.py'))
|
boolean isPython = (interp == 'python3' || interp == 'python' || script.endsWith('.py'))
|
||||||
// docker:27-cli is minimal Alpine — only `sh` is guaranteed present.
|
// bash/python3+pip/venv are baked into the docker-cli image (see
|
||||||
// bash/python3 need installing on demand, unlike the real system's
|
// build-tools.Dockerfile) — used to apk-install these on demand on
|
||||||
// pod images which already bundle a full toolchain.
|
// every single hook invocation, unlike the real system's pod images
|
||||||
String installLine = ''
|
// which already bundle a full toolchain.
|
||||||
if (isPython) {
|
|
||||||
installLine = 'apk add --no-cache python3 py3-pip py3-virtualenv >/dev/null'
|
|
||||||
} else if (interp == 'bash') {
|
|
||||||
installLine = 'apk add --no-cache bash >/dev/null'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requirements && isPython) {
|
if (requirements && isPython) {
|
||||||
String py = interp ?: 'python3'
|
String py = interp ?: 'python3'
|
||||||
return """
|
return """
|
||||||
set -e
|
set -e
|
||||||
${installLine}
|
|
||||||
${py} -m venv .hook_venv
|
${py} -m venv .hook_venv
|
||||||
. .hook_venv/bin/activate
|
. .hook_venv/bin/activate
|
||||||
pip install --quiet --disable-pip-version-check -r ${requirements}
|
pip install --quiet --disable-pip-version-check -r ${requirements}
|
||||||
@@ -116,7 +110,7 @@ def buildRunCommand(String script, String interpreter, String requirements) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (interp) {
|
if (interp) {
|
||||||
return "set -e\n${installLine}\n${interp} ${script}"
|
return "set -e\n${interp} ${script}"
|
||||||
}
|
}
|
||||||
// No interpreter resolved — rely on the script's shebang.
|
// No interpreter resolved — rely on the script's shebang.
|
||||||
return "set -e\nchmod +x ${script}\n./${script}"
|
return "set -e\nchmod +x ${script}\n./${script}"
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ def run(Map config) {
|
|||||||
echo "ARGOCD_TOKEN is empty — the jenkins-ci account token has not been generated yet. See secretstores/argocd-jenkins-ci-token.yaml for the one-time bootstrap steps." >&2
|
echo "ARGOCD_TOKEN is empty — the jenkins-ci account token has not been generated yet. See secretstores/argocd-jenkins-ci-token.yaml for the one-time bootstrap steps." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
apk add --no-cache curl >/dev/null
|
|
||||||
curl -sf -X POST \\
|
curl -sf -X POST \\
|
||||||
-H "Authorization: Bearer \$ARGOCD_TOKEN" \\
|
-H "Authorization: Bearer \$ARGOCD_TOKEN" \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ package com.homelab.stages
|
|||||||
def run(Map config) {
|
def run(Map config) {
|
||||||
def valuesFile = "values/${config.repo_name}/${config.service_name}/values.yaml"
|
def valuesFile = "values/${config.repo_name}/${config.service_name}/values.yaml"
|
||||||
stage(stageName('Update Helm chart image tag')) {
|
stage(stageName('Update Helm chart image tag')) {
|
||||||
|
// git and yq are both baked into the docker-cli image now (see
|
||||||
|
// build-tools.Dockerfile) — this used to run unwrapped, defaulting
|
||||||
|
// to the auto-injected jnlp agent container (which has git but no
|
||||||
|
// yq, confirmed by `apk: not found` when trying to install yq
|
||||||
|
// on demand there), needing a curl-downloaded yq fallback to
|
||||||
|
// /tmp every single build. Wrapping in container('docker-cli')
|
||||||
|
// means both tools are simply already there.
|
||||||
|
container('docker-cli') {
|
||||||
withCredentials([usernamePassword(credentialsId: config.gitea_cred ?: 'gitea-ci-credentials', usernameVariable: 'GIT_USER', passwordVariable: 'GIT_PASS')]) {
|
withCredentials([usernamePassword(credentialsId: config.gitea_cred ?: 'gitea-ci-credentials', usernameVariable: 'GIT_USER', passwordVariable: 'GIT_PASS')]) {
|
||||||
dir('helm-chart-repo') {
|
dir('helm-chart-repo') {
|
||||||
deleteDir()
|
deleteDir()
|
||||||
@@ -43,23 +51,7 @@ def run(Map config) {
|
|||||||
def authedUrl = "${urlParts[0]}://\${GIT_USER}:\${GIT_PASS}@${urlParts[1]}"
|
def authedUrl = "${urlParts[0]}://\${GIT_USER}:\${GIT_PASS}@${urlParts[1]}"
|
||||||
sh """
|
sh """
|
||||||
git clone ${authedUrl} .
|
git clone ${authedUrl} .
|
||||||
# This sh step isn't wrapped in container('docker-cli')
|
yq -i '${config.image_tag_yq_path} = "${env.TAG}"' ${valuesFile}
|
||||||
# (unlike runHooks/buildDocker), so it runs in the
|
|
||||||
# auto-injected jnlp agent container by default — a
|
|
||||||
# Debian-based jenkins/inbound-agent image, not Alpine,
|
|
||||||
# confirmed by `apk: not found` right after git clone
|
|
||||||
# worked fine in the same step. No package manager
|
|
||||||
# assumption is safe here since the underlying
|
|
||||||
# container/distro isn't pinned — fetch the static
|
|
||||||
# mikefarah/yq binary directly instead, to /tmp (always
|
|
||||||
# writable, unlike /usr/local/bin under a non-root
|
|
||||||
# agent user).
|
|
||||||
if ! command -v yq >/dev/null 2>&1; then
|
|
||||||
curl -sL -o /tmp/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
|
|
||||||
chmod +x /tmp/yq
|
|
||||||
fi
|
|
||||||
YQ=\$(command -v yq || echo /tmp/yq)
|
|
||||||
\$YQ -i '${config.image_tag_yq_path} = "${env.TAG}"' ${valuesFile}
|
|
||||||
git config user.email 'jenkins-ci@homelab.local'
|
git config user.email 'jenkins-ci@homelab.local'
|
||||||
git config user.name 'jenkins-ci'
|
git config user.name 'jenkins-ci'
|
||||||
git commit -am 'ci: bump ${config.repo_name}/${config.service_name} image tag to ${env.TAG}'
|
git commit -am 'ci: bump ${config.repo_name}/${config.service_name} image tag to ${env.TAG}'
|
||||||
@@ -69,3 +61,4 @@ def run(Map config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user