ci: update hello-world app files

This commit is contained in:
Ansible
2026-10-06 22:29:42 +02:00
commit a12d48a934
7 changed files with 222 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
ENTRYPOINT ["nginx", "-g", "daemon off;"]
Vendored
+129
View File
@@ -0,0 +1,129 @@
// Build -> registry -> deploy, with nothing written back into this repository: Jenkins builds the image with
// rootless BuildKit (no privileged docker-in-docker) and pushes it to Harbor as :<commit> and :latest, using the
// project's push-only robot account. Argo CD Image Updater (ImageUpdater hello-world in namespace argocd) sees the
// new :<commit> tag in Harbor and points the Argo CD application at it. No commit back means no webhook loop, so
// no [skip ci] commits and no extra builds.
pipeline {
agent {
kubernetes {
label 'buildkit-agent'
yaml """
apiVersion: v1
kind: Pod
spec:
serviceAccountName: jenkins
containers:
- name: buildkit
image: moby/buildkit:v0.33.1-rootless
command: ['sleep']
args: ['99d']
env:
# Rootless BuildKit inside an unprivileged pod: no process sandbox of its own (the pod is the sandbox).
- name: BUILDKITD_FLAGS
value: --oci-worker-no-process-sandbox
# buildctl and buildkitd are Go: SSL_CERT_DIR adds the internal CA (/certs) to both trust stores, beside the
# image's own bundle -- the push talks TLS to Harbor's registry and to its token endpoint.
- name: SSL_CERT_DIR
value: /etc/ssl/certs:/certs
- name: HTTP_PROXY
value: http://10.0.10.10:3128
- name: HTTPS_PROXY
value: http://10.0.10.10:3128
- name: NO_PROXY
value: localhost,127.0.0.1,10.0.0.0/8,.cluster.local,.svc,.demo-06-10-2026.app.ariki.ai
- name: http_proxy
value: http://10.0.10.10:3128
- name: https_proxy
value: http://10.0.10.10:3128
- name: no_proxy
value: localhost,127.0.0.1,10.0.0.0/8,.cluster.local,.svc,.demo-06-10-2026.app.ariki.ai
securityContext:
runAsUser: 1000
runAsGroup: 1000
seccompProfile:
type: Unconfined
appArmorProfile:
type: Unconfined
volumeMounts:
# buildkitd.toml: trust the internal CA for harbor.demo-06-10-2026.app.ariki.ai (ConfigMap hello-world-buildkitd)
- name: buildkitd-config
mountPath: /home/user/.config/buildkit
- name: internal-root-ca
mountPath: /certs
readOnly: true
# Harbor push credentials: the push-only robot (ExternalSecret hello-world-harbor-push)
- name: harbor-push
mountPath: /home/user/.docker
readOnly: true
- name: buildkit-state
mountPath: /home/user/.local/share/buildkit
volumes:
- name: buildkitd-config
configMap:
name: hello-world-buildkitd
- name: internal-root-ca
secret:
secretName: internal-root-ca
- name: harbor-push
secret:
secretName: hello-world-harbor-push
items:
- key: .dockerconfigjson
path: config.json
- name: buildkit-state
emptyDir: {}
"""
}
}
triggers {
GenericTrigger(
genericVariables: [
[key: 'ref', value: '$.ref'],
[key: 'commit_message', value: '$.head_commit.message']
],
token: 'gitea-webhook'
)
}
environment {
HARBOR_HOST = "harbor.demo-06-10-2026.app.ariki.ai"
HARBOR_PROJECT = "demo-06-10-2026"
IMAGE_NAME = "${HARBOR_HOST}/${HARBOR_PROJECT}/hello-world"
}
stages {
stage('Build and push image') {
steps {
script {
// The commit, not BUILD_NUMBER: unique even if the job is recreated, and it names the source
// the image was built from. The ImageUpdater only accepts tags of this shape.
env.IMAGE_TAG = env.GIT_COMMIT.take(12)
currentBuild.description = env.IMAGE_TAG
}
container('buildkit') {
// buildkitd.toml gives the daemon (blob push) the internal CA; the registry token is fetched by
// buildctl itself, which needs it too (--registry-auth-tlscontext), or the push fails with
// "failed to fetch oauth token ... x509: certificate signed by unknown authority".
sh '''
buildctl-daemonless.sh build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--registry-auth-tlscontext "host=${HARBOR_HOST},ca=/certs/ca.crt" \
--output "type=image,\\"name=${IMAGE_NAME}:${IMAGE_TAG},${IMAGE_NAME}:latest\\",push=true"
'''
}
}
}
}
post {
success {
echo "Pushed ${IMAGE_NAME}:${IMAGE_TAG}; Argo CD Image Updater deploys it to https://hello-world.demo-06-10-2026.app.ariki.ai"
}
failure {
echo "Pipeline failed at: ${env.STAGE_NAME}"
}
}
}
+9
View File
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello from K3s cluster!</h1>
</body>
</html>
+35
View File
@@ -0,0 +1,35 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
namespace: hello-world
spec:
replicas: 2
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
imagePullSecrets:
- name: harbor-pull-secret
containers:
- name: hello-world
image: harbor.demo-06-10-2026.app.ariki.ai/demo-06-10-2026/hello-world:latest
ports:
- containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
+23
View File
@@ -0,0 +1,23 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world
namespace: hello-world
spec:
ingressClassName: nginx
tls:
- hosts:
- hello-world.demo-06-10-2026.app.ariki.ai
secretName: hello-world-tls
rules:
- host: hello-world.demo-06-10-2026.app.ariki.ai
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-world
port:
number: 80
+8
View File
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# A Kustomize application, so Argo CD Image Updater can set the image tag as an Application override
# (spec.source.kustomize.images) instead of anyone committing it into deployment.yml.
resources:
- deployment.yml
- service.yml
- ingress.yml
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: hello-world
namespace: hello-world
spec:
selector:
app: hello-world
ports:
- port: 80
targetPort: 80