ce7cb702218693d08ea6d83464d2457c9250027c

This commit is contained in:
ms2k 2026-11-12 20:46:28 +09:00
commit 34c5f8963c
11 changed files with 145336 additions and 0 deletions

View file

@ -0,0 +1,29 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- network-policy.yaml
- qualification
- workflowtemplate.yaml
configMapGenerator:
- name: nuthatch-runtime
namespace: project-delivery
files:
- nuthatch.apko.yaml=nuthatch.apko.yaml
- nuthatch-runner.apko.yaml=nuthatch-runner.apko.yaml
options:
labels:
app.kubernetes.io/instance: nuthatch
- name: nuthatch-runtime-lock
namespace: project-delivery
files:
- nuthatch-runtime-x86_64.sha256=nuthatch-runtime-x86_64.sha256
- nuthatch-test-shell-x86_64.sha256=nuthatch-test-shell-x86_64.sha256
- nuthatch-runtime-x86_64.index.sha256=nuthatch-runtime-x86_64.index.sha256
- nuthatch-test-x86_64.index.sha256=nuthatch-test-x86_64.index.sha256
options:
labels:
app.kubernetes.io/instance: nuthatch
generatorOptions:
disableNameSuffixHash: true
labels:
app.kubernetes.io/name: project-delivery

View file

@ -0,0 +1,132 @@
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: nuthatch-source
namespace: project-delivery
spec:
endpointSelector:
matchLabels:
delivery.quorate.dev/stage: nuthatch-source
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- {port: "53", protocol: UDP}
- {port: "53", protocol: TCP}
rules:
dns:
- matchName: forge-git-http.forgejo-public.svc.cluster.local
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: forgejo-public
app.kubernetes.io/name: forgejo
app.kubernetes.io/instance: forge-git
toPorts:
- ports:
- {port: "3000", protocol: TCP}
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: nuthatch-toolchain
namespace: project-delivery
spec:
endpointSelector:
matchLabels:
delivery.quorate.dev/stage: nuthatch-toolchain
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- {port: "53", protocol: UDP}
- {port: "53", protocol: TCP}
rules:
dns:
- matchName: downloads.haskell.org
- matchName: github.com
- matchName: hackage.haskell.org
- matchName: packages.wolfi.dev
- matchName: registry.npmjs.org
- matchName: release-assets.githubusercontent.com
- toFQDNs:
- {matchName: downloads.haskell.org}
- {matchName: github.com}
- {matchName: hackage.haskell.org}
- {matchName: packages.wolfi.dev}
- {matchName: registry.npmjs.org}
- {matchName: release-assets.githubusercontent.com}
toPorts:
- ports:
- {port: "443", protocol: TCP}
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: nuthatch-cache
namespace: project-delivery
spec:
endpointSelector:
matchExpressions:
- key: delivery.quorate.dev/stage
operator: In
values: [nuthatch-cache-pull, nuthatch-cache-export]
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- {port: "53", protocol: UDP}
- {port: "53", protocol: TCP}
rules:
dns:
- matchName: s3.quorate.internal
- toCIDR: [10.66.127.81/32]
toPorts:
- ports:
- {port: "443", protocol: TCP}
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: versitygw
app.kubernetes.io/name: versitygw
app.kubernetes.io/instance: versitygw
toPorts:
- ports:
- {port: "7070", protocol: TCP}
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: nuthatch-publication
namespace: project-delivery
spec:
endpointSelector:
matchLabels:
delivery.quorate.dev/stage: publish-internal
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- {port: "53", protocol: UDP}
- {port: "53", protocol: TCP}
- toCIDR: [10.108.252.250/32, 10.66.127.81/32]
toPorts:
- ports:
- {port: "443", protocol: TCP}
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: quay
app: quay
toPorts:
- ports:
- {port: "8443", protocol: TCP}

View file

@ -0,0 +1,33 @@
contents:
repositories:
- /workspace/repository
packages:
- bash=5.3-r12
- busybox=1.37.0-r61
- ca-certificates-bundle=20260413-r1
- curl=8.21.0-r1
- gmp=6.3.0-r8
- libffi=3.8.0-r0
- libpq-18=18.6-r0
- ncurses=6.6.20260808-r0
- nodejs-24=24.18.1-r1
- openjdk-25-default-jdk=25.0.4-r0
- quorate-nuthatch-runner
- openssl=3.6.3-r3
- ripgrep=15.2.0-r1
- zlib=1.3.2-r4
accounts:
groups:
- groupname: test
gid: 65532
users:
- username: test
uid: 65532
gid: 65532
run-as: 65532
entrypoint:
command: /bin/sh
environment:
HOME: /workspace
PATH: /usr/local/bin:/usr/bin:/bin
work-dir: /workspace

View file

@ -0,0 +1 @@
647e167b27bce2975973df454abf2132c90663a070206614c47c57461a091191

View file

@ -0,0 +1,30 @@
2ca7f5ffc611dcd8130462443713abc907e64fe3e5006bd3c53960673566f5f8 busybox-1.37.0-r61.apk
355058d6dd75143315159800147cc778e1305bd7202b36dca57b2c9c12766bfe ca-certificates-bundle-20260413-r1.apk
d023e22a81f22d47737784520e6e403cbbb6ad46284893f9c1e6a1d204aad99c cyrus-sasl-heimdal-libs-2.1.28-r54.apk
0f349182ec9d27fb409642da2171ac9b709075f2086e9a8b34ac32d02f87eedb gdbm-1.26-r5.apk
495a506a1630939614ac7aa98cc63af8b76762ee981864310b800374ef1652cd glibc-2.43-r13.apk
5b28c532c3d2af5e8086da69ece4277ef2e0958f4576805aebd25474240a60c2 glibc-locale-posix-2.43-r13.apk
aa380bccf588737bc788370f08ad911131dbb3b04f4a3746e5a64ef65dc0a552 gmp-6.3.0-r8.apk
4f77aff1f00fc6e44c874baf2fb156a32433dd0c0e5b60c07d8d8299d58562bb heimdal-libs-7.8.0-r51.apk
a24f381476c14c21b69d4ce9d2604a88c539d89d9a797406a8c029a9f51aa9b9 keyutils-libs-1.6.3-r39.apk
fbf18eeac1fc863fe4ef55a0ab24463abdd1f56f9e380aba6ba1cfa69b3e6f61 krb5-conf-1.0-r9.apk
aca1e742c46bb25b18a729183be16f09a95aeb5bc64a863354b6ba362e13171f krb5-libs-1.22.2-r2.apk
f49b25afb455a17c0a6335bc97ade76be8b7b0674354a21b12d95a3a4e63e219 ld-linux-2.43-r13.apk
b2b7020631a41f6ce01c34d0ea9b839d860c42356e23b026c9fb84f8332a478c libcom_err-1.47.4-r1.apk
6a4a6fbabfa05b60f2f76a2fb468b7b30dff048cd4b32cbba8a9d284e0f91764 libcrypt1-2.43-r13.apk
0a6db82a1064ff780f1609b5dc94a64d397924df8e6a339c0de7e210d6ae5474 libcrypto3-3.6.3-r3.apk
22bb0de1650e6923ce453b4ddc55c9fcc9900208fab5a59bbf7d475bbc8d6bdb libffi-3.8.0-r0.apk
ad923214add20d7a410ee391718df91116ed29c12902c1170cf23a7c91adc602 libgcc-16.1.0-r4.apk
140df3743ee774109bec62bf0531321d2fbb501327cfbd855ab5a535ce3c4c90 libldap-2.6.10-r5.apk
fadf9e1eb3d8342fc2bca2353516db8068593141b603126374684609489c7314 libpq-18-18.6-r0.apk
698c9f853a6afddff19a7e3005f3b68c78d254be6c256ed1b1a2c53826e023d4 libssl3-3.6.3-r3.apk
9ac930b743608314f1a4bb0ed87518e0c5d26fbbe098f17f13dacd6bce6ab025 libstdc++-16.1.0-r4.apk
7761dbf3d9520eb5d5acf5c88a2f2a625f4566e3ee7ae46ada397023af6cb555 libverto-0.3.2-r7.apk
08fcbcec72ef514e48d6bffc1348e02d9a4763f2a26be59da4b4e2a6ec973b5d libxcrypt-4.5.2-r4.apk
a1c2ff0b69c7d421c971f1f9a4b69657870d2984a5e7ae614cbf6e353d4a2baa ncurses-6.6.20260808-r0.apk
7a7ffa08b6a7be9676fd7f1e901318772f5864a61faab376b1532bc42fba47d7 ncurses-terminfo-base-6.6.20260808-r0.apk
86f8a3d7a7525009bc703640dd8fa8d69ca6712348865309e68054a8be419d67 openssl-3.6.3-r3.apk
268933ea5e61bbfd00af609be984e753eb4b902a26257e42303836fddea3836a readline-8.3-r2.apk
09010a1a174b03b3f73ee13d22a1b5399796a9aaa9be53a18d8a045bebd4e499 sqlite-libs-3.53.4-r0.apk
c7aef94f6c8e3060cac5a6b1dfa6257ad0d2d4d0a6ff93d02bba26e0ea518457 wolfi-baselayout-20230201-r29.apk
421dfb6b878c9b8453fdf5e73a830eba29a8fb06260c69e39592759326212166 zlib-1.3.2-r4.apk

View file

@ -0,0 +1,56 @@
7980f08672e731801f8f411f1a0fa6fb11581354ac4d5fdd9eff5cf057959c3c alsa-lib-1.2.16.1-r1.apk
04db98c81192d3a52ece091fac002d5abd1bae97b43ef042c80196b7a9f8cc36 bash-5.3-r12.apk
579d994e3849078b9d0b9e38a5da7d8b1d5a2a569b626f12a9e74710784095c4 c-ares-1.34.8-r0.apk
e73e69ae827d0ebddef4bf0f2471f6c6cd9c5af124a2740f9601872ff1d72044 ca-certificates-20260413-r1.apk
355058d6dd75143315159800147cc778e1305bd7202b36dca57b2c9c12766bfe ca-certificates-bundle-20260413-r1.apk
95e856bb6f55f8d69cddcb987191ab2466e503dc0f5de93a149c9aacff1d9114 curl-8.21.0-r1.apk
e7f7d32b494518dcd8ed1448dd61f9337570fd2054a505637ed86b4897988e67 freetype-2.14.3-r4.apk
83eb9c2796b8898daa640f09355d01128965ea3b220eba3e1bbf2129a9b7ef48 giflib-6.1.3-r0.apk
495a506a1630939614ac7aa98cc63af8b76762ee981864310b800374ef1652cd glibc-2.43-r13.apk
5b28c532c3d2af5e8086da69ece4277ef2e0958f4576805aebd25474240a60c2 glibc-locale-posix-2.43-r13.apk
b02a6cb15cc21dd5c9af2b7563d7a4063acf3a0b9fd3b79fa112c75104914a48 icu78-data-full-78.3-r1.apk
aa7cd87b31aa503e6a159ac94f2b3cbf868b392025bf1822176f35b7c22fb068 java-cacerts-20260413-r1.apk
312ef24e5d86b9c0204246b0808d4ca844e0195e358caf0f8c19fd701b227d50 java-common-0.2-r3.apk
e8d816eecadd0edaf78f0499d3ae75a9c633fe4b8e64efdbdfcd439562fad463 java-common-jre-0.2-r3.apk
91bd8c0cb4ee0b2312e74dc7828a269edd7be5abaa0a3fedc0ef20ea1781acb3 lcms2-2.19.1-r1.apk
f49b25afb455a17c0a6335bc97ade76be8b7b0674354a21b12d95a3a4e63e219 ld-linux-2.43-r13.apk
49dbcc31d5126eece677200ef3c777be224c493ea4cd7a03cf3d36e27e9715f8 libbrotlicommon1-1.2.0-r3.apk
1031104cad23db551bd510baf7fa0f9b419dfef9f7947eba2d6ec3f23528cddc libbrotlidec1-1.2.0-r3.apk
d28217d62ea9d22c1c315a53e2e6e62bde75fd24dd859a43600c502ebca7d6d1 libbrotlienc1-1.2.0-r3.apk
796efdde62e76824bb22c55534ed6ed4acb9dcc08de35aaa9ed63900600a5ecb libbz2-1-1.0.8-r23.apk
1741db306c6afa4bdbf85d5b7824b48534447e8b6cfa9261f183970720fac6cd libcrypto3-3.6.3-r4.apk
242db949bcdb424a81edb0fcdd4c312da14b3b232ce3740697864b5156a0b6c1 libcurl-openssl4-8.21.0-r1.apk
22bb0de1650e6923ce453b4ddc55c9fcc9900208fab5a59bbf7d475bbc8d6bdb libffi-3.8.0-r0.apk
ad923214add20d7a410ee391718df91116ed29c12902c1170cf23a7c91adc602 libgcc-16.1.0-r4.apk
c6d47a025599fd9154e2b337eeba9dd9cc3db2e7393a8e58ccc2b2886599272a libicu78-78.3-r1.apk
8570420f03521d3ed026f3ef988bab340f91ffe406826c1a638478207058a515 libidn2-2.3.8-r8.apk
a13d8b969ff6aa2dc9083ceb29c7ad770729df52bb16e66ffa60768fb8d2d3fd libjpeg-turbo-3.2.0-r1.apk
6218d0c490d7310694c161d78b4f9ab2d4a2d743408a8e6b26cad9cc02ff21bd libnghttp2-14-1.70.0-r2.apk
be08692857710f2ae7c2b113b447b035b2f31478fd7cdc28a7c8d91378e5edbb libpng-1.6.58-r1.apk
c4b2e86ebcfc22ced4f6b9dae44c0a0a6d623384e53f673b34443ac41fcfb6e3 libpsl-0.23.2-r0.apk
121ddd5051f2a82b015865462439962418849fcc4964e0b85f51b09f30493b9b libssl3-3.6.3-r4.apk
9ac930b743608314f1a4bb0ed87518e0c5d26fbbe098f17f13dacd6bce6ab025 libstdc++-16.1.0-r4.apk
91cfc876e8dc9806a6fefc9a383d948eff884f65d6fe1e60c6cc06cd67012236 libtasn1-4.21.0-r5.apk
7923969e5333292e479263b39f3fa9b2f40eea3b759fb1f5b58db78eb0735fc0 libunistring-1.4.2-r2.apk
020c6d18c47547ff2875b57109f445066e717cd68c440dff57fb71cfee813fb2 libuv-1.52.1-r1.apk
a4408e335afd6fe53f7f236935aae8516543d0485ebea072fda102071b1319a4 libx11-1.8.13-r5.apk
748dbf40f5e0b8fba7404b67d55cc7d4e494bb5a170f0b71845f63775cc1a959 libxau-1.0.12-r7.apk
cc343174e9d0160b113fe2bce5199960f834038a5a6c1df67f60270a1028e3c5 libxcb-1.17.0-r15.apk
b05a3455c5c8c904f4d2ad48a11f7f2c473175d581afc6a9618e6c55ba99d49b libxdmcp-1.1.5-r9.apk
cfea1481d83b03f48d7e7e38be995bc522aae08cfb7582544c0fc8a3d47d35fe libxext-1.3.7-r0.apk
1743ed1eb73e92bbbeb6fcfbbe95cacbc48e9ebec4c0b544a599cc2811e0a03e libxi-1.8.3-r0.apk
b26ab6e01c2b940aba2aadd009712235c45a2744f729e542391d0332fb68abcd libxrender-0.9.12-r8.apk
d10647c6cf059c6ae0a40062b0c2b075723ce00d22a125c9136fb02a8c173812 libxtst-1.2.5-r7.apk
a1c2ff0b69c7d421c971f1f9a4b69657870d2984a5e7ae614cbf6e353d4a2baa ncurses-6.6.20260808-r0.apk
7a7ffa08b6a7be9676fd7f1e901318772f5864a61faab376b1532bc42fba47d7 ncurses-terminfo-base-6.6.20260808-r0.apk
bc0dbc34ae1e52ba3cd43b93f3b4b7d369f4b0317589299dae1bd0c3b0977310 nghttp3-1.18.0-r0.apk
8d4af514ca52379fac1f754b25bd2c9f60a1c76910ab7037a1f8e8f55e1748be ngtcp2-1.25.0-r1.apk
5af31d2691ad5ace3e081ed0dc756bb01804afb75bea458d56b5d8a2c7bf32c6 nodejs-24-24.18.1-r1.apk
ed6a1cc2a07f0e779e19e26bf196a831bbfe189ef60c789c0e90a8fe2c7bf9a2 openjdk-25-25.0.4-r0.apk
bcc27aa88163ebdb010dafbb4fab38f414996ba77c173cd4783ef309389e3d8b openjdk-25-default-jdk-25.0.4-r0.apk
efae428afe598cabcf0d7240f7b271c819e8f919d3a656a5268104127a0baf12 p11-kit-0.26.5-r0.apk
baa8599fcd645eac39003511b1b06edffe0b69907bf6a6e6a88144706c04a2ba p11-kit-trust-0.26.5-r0.apk
3991bac9608f5a1a3ed122d0196cbf5a3cf0df9c08fae1869f9743020c8b2213 ripgrep-15.2.0-r1.apk
088ad286ce4fd1d3e5583117632dae7119f28bd9d003e6960dfb52dd1071df34 ttf-dejavu-2.37-r8.apk
c7aef94f6c8e3060cac5a6b1dfa6257ad0d2d4d0a6ff93d02bba26e0ea518457 wolfi-baselayout-20230201-r29.apk
421dfb6b878c9b8453fdf5e73a830eba29a8fb06260c69e39592759326212166 zlib-1.3.2-r4.apk

View file

@ -0,0 +1 @@
6b6f1017029d6fa4632ba48b5c3447d7a0cf23f7c8329fd893cbd077fcf6be4a

View file

@ -0,0 +1,27 @@
contents:
repositories:
- /workspace/repository
packages:
- busybox=1.37.0-r61
- ca-certificates-bundle=20260413-r1
- gmp=6.3.0-r8
- libffi=3.8.0-r0
- libpq-18=18.6-r0
- ncurses=6.6.20260808-r0
- quorate-nuthatch
- openssl=3.6.3-r3
- zlib=1.3.2-r4
accounts:
groups:
- groupname: nuthatch
gid: 10001
users:
- username: nuthatch
uid: 10001
gid: 10001
run-as: 10001
entrypoint:
command: /usr/local/bin/nuthatch
environment:
PATH: /usr/local/bin:/usr/bin:/bin
work-dir: /app

View file

@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- workflowtemplate.yaml

View file

@ -0,0 +1,343 @@
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: nuthatch-qualification
namespace: project-delivery
labels:
app.kubernetes.io/name: project-delivery
app.kubernetes.io/instance: nuthatch-qualification
spec:
entrypoint: qualify
serviceAccountName: qualification-executor
automountServiceAccountToken: false
executor:
serviceAccountName: qualification-executor
activeDeadlineSeconds: 10800
parallelism: 2
podGC:
strategy: OnWorkflowCompletion
nodeSelector:
kubernetes.io/hostname: "{{workflow.parameters.workflow-node}}"
podMetadata:
labels:
app.kubernetes.io/name: project-delivery
app.kubernetes.io/instance: nuthatch-qualification
podSpecPatch: |
imagePullSecrets:
- name: quay-reader
containers:
- name: wait
volumeMounts:
- name: exec-sa-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
volumes:
- name: exec-sa-token
secret: null
projected:
defaultMode: 0440
sources:
- serviceAccountToken:
expirationSeconds: 3600
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
fieldPath: metadata.namespace
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
arguments:
parameters:
- name: test-image
- name: workflow-node
- name: gate
value: all
templates:
- name: qualify
dag:
tasks:
- name: gate
template: bootstrap
when: "{{=workflow.parameters['gate'] == 'all' || workflow.parameters['gate'] == item.gate}}"
arguments:
parameters:
- {name: gate, value: "{{item.gate}}"}
- {name: coordination, value: "{{item.coordination}}"}
- {name: oidc, value: "{{item.oidc}}"}
- {name: target, value: "{{item.target}}"}
withItems:
- {gate: unit, coordination: none, oidc: none, target: none}
- {gate: dependency, coordination: all, oidc: all, target: all}
- {gate: fixture, coordination: all, oidc: all, target: all}
- {gate: storage, coordination: none, oidc: none, target: all}
- {gate: auth, coordination: all, oidc: all, target: all}
- {gate: browser, coordination: redis, oidc: keycloak, target: garage}
- {gate: idempotency, coordination: all, oidc: all, target: all}
- {gate: product, coordination: all, oidc: all, target: all}
- {gate: protocol, coordination: redis, oidc: none, target: all}
- {gate: recovery, coordination: redis, oidc: none, target: all}
- {gate: runtime, coordination: redis, oidc: keycloak, target: garage}
- {gate: streaming, coordination: all, oidc: all, target: all}
- name: bootstrap
inputs:
parameters:
- name: gate
- name: coordination
- name: oidc
- name: target
metadata:
labels:
qualification.quorate.dev/stage: bootstrap
podSpecPatch: |
containers:
- name: main
volumeMounts:
- name: exec-sa-token
mountPath: /kubernetes
readOnly: true
container:
image: &fsi registry.quorate.internal/quorate/fsharp-runner@sha256:e4cbf2cfcbd903ff4600590b84a08c0e09d95fa1e2edda4daf8d32a6aeda35f7
imagePullPolicy: IfNotPresent
command: &fsi-command [/usr/share/dotnet/dotnet, /opt/fsi/fsi.dll, --exec]
args: [/orchestration/qualification.fsx]
env:
- {name: QUALIFICATION_ACTION, value: bootstrap}
- {name: QUALIFICATION_RUN, value: "{{workflow.uid}}"}
- {name: QUALIFICATION_GATE, value: "{{inputs.parameters.gate}}"}
- {name: QUALIFICATION_COORDINATION, value: "{{inputs.parameters.coordination}}"}
- {name: QUALIFICATION_OIDC, value: "{{inputs.parameters.oidc}}"}
- {name: QUALIFICATION_TARGET, value: "{{inputs.parameters.target}}"}
- {name: TEST_IMAGE, value: "{{workflow.parameters.test-image}}"}
- {name: WORKFLOW_NODE, value: "{{workflow.parameters.workflow-node}}"}
resources:
requests: {cpu: 50m, memory: 128Mi}
limits: {cpu: 500m, memory: 512Mi}
securityContext: &restricted
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}
readOnlyRootFilesystem: true
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: temporary, mountPath: /tmp}
volumes:
- name: orchestration
configMap: {name: nuthatch-qualification-orch, defaultMode: 0444}
- {name: temporary, emptyDir: {}}
---
apiVersion: argoproj.io/v1alpha1
kind: ClusterWorkflowTemplate
metadata:
name: nuthatch-qualification-lane
labels:
app.kubernetes.io/name: project-delivery
app.kubernetes.io/instance: nuthatch-qualification
spec:
entrypoint: qualify
serviceAccountName: qualification-lane
automountServiceAccountToken: false
executor:
serviceAccountName: qualification-lane
activeDeadlineSeconds: 7200
podGC:
strategy: OnWorkflowCompletion
nodeSelector:
kubernetes.io/hostname: "{{workflow.parameters.workflow-node}}"
podMetadata:
labels:
app.kubernetes.io/name: nuthatch-qualification
app.kubernetes.io/instance: nuthatch
podSpecPatch: |
imagePullSecrets:
- name: quay-reader
containers:
- name: wait
volumeMounts:
- name: exec-sa-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
volumes:
- name: exec-sa-token
secret: null
projected:
defaultMode: 0440
sources:
- serviceAccountToken:
expirationSeconds: 3600
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
fieldPath: metadata.namespace
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
arguments:
parameters:
- name: gate
- name: coordination
- name: oidc
- name: target
- name: test-image
- name: workflow-node
volumes:
- name: orchestration
configMap: {name: nuthatch-qualification-orch, defaultMode: 0444}
- {name: temporary, emptyDir: {}}
templates:
- name: qualify
metadata:
labels:
qualification.quorate.dev/stage: qualification
podSpecPatch: |
containers:
- name: main
volumeMounts: &token-mount
- name: exec-sa-token
mountPath: /kubernetes
readOnly: true
- name: redis
volumeMounts: *token-mount
- name: dragonfly
volumeMounts: *token-mount
- name: keycloak
volumeMounts: *token-mount
- name: zitadel
volumeMounts: *token-mount
- name: garage
volumeMounts: *token-mount
- name: versitygw
volumeMounts: *token-mount
- name: test
volumeMounts: *token-mount
volumes:
- name: exec-sa-token
secret: null
projected:
defaultMode: 0440
sources:
- serviceAccountToken:
expirationSeconds: 3600
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
fieldPath: metadata.namespace
containerSet:
volumeMounts: &fixture-mounts
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: temporary, mountPath: /tmp}
containers:
- name: main
image: &lane-fsi registry.quorate.internal/quorate/fsharp-runner@sha256:e4cbf2cfcbd903ff4600590b84a08c0e09d95fa1e2edda4daf8d32a6aeda35f7
imagePullPolicy: IfNotPresent
command: &lane-fsi-command [/usr/share/dotnet/dotnet, /opt/fsi/fsi.dll, --exec]
args: [/orchestration/postgres.fsx]
env: &fixture-env
- {name: QUALIFICATION_NAMESPACE, value: "{{workflow.namespace}}"}
- {name: QUALIFICATION_GATE, value: "{{workflow.parameters.gate}}"}
- {name: QUALIFICATION_COORDINATION, value: "{{workflow.parameters.coordination}}"}
- {name: QUALIFICATION_OIDC, value: "{{workflow.parameters.oidc}}"}
- {name: QUALIFICATION_TARGET, value: "{{workflow.parameters.target}}"}
- {name: TEST_IMAGE, value: "{{workflow.parameters.test-image}}"}
- {name: WORKFLOW_NODE, value: "{{workflow.parameters.workflow-node}}"}
- {name: FSI_IMAGE, value: *lane-fsi}
resources: &fixture-resources
requests: {cpu: 25m, memory: 64Mi}
limits: {cpu: 500m, memory: 512Mi}
securityContext: &lane-restricted
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}
readOnlyRootFilesystem: true
- name: redis
dependencies: [main]
image: *lane-fsi
imagePullPolicy: IfNotPresent
command: *lane-fsi-command
args: [/orchestration/redis.fsx]
env: *fixture-env
resources: *fixture-resources
securityContext: *lane-restricted
- name: dragonfly
dependencies: [main]
image: *lane-fsi
imagePullPolicy: IfNotPresent
command: *lane-fsi-command
args: [/orchestration/dragonfly.fsx]
env: *fixture-env
resources: *fixture-resources
securityContext: *lane-restricted
- name: keycloak
dependencies: [main]
image: *lane-fsi
imagePullPolicy: IfNotPresent
command: *lane-fsi-command
args: [/orchestration/keycloak.fsx]
env: *fixture-env
resources: *fixture-resources
securityContext: *lane-restricted
- name: zitadel
dependencies: [main]
image: *lane-fsi
imagePullPolicy: IfNotPresent
command: *lane-fsi-command
args: [/orchestration/zitadel.fsx]
env: *fixture-env
resources: *fixture-resources
securityContext: *lane-restricted
- name: garage
dependencies: [main]
image: *lane-fsi
imagePullPolicy: IfNotPresent
command: *lane-fsi-command
args: [/orchestration/garage.fsx]
env: *fixture-env
resources: *fixture-resources
securityContext: *lane-restricted
- name: versitygw
dependencies: [main]
image: *lane-fsi
imagePullPolicy: IfNotPresent
command: *lane-fsi-command
args: [/orchestration/versitygw.fsx]
env: *fixture-env
resources: *fixture-resources
securityContext: *lane-restricted
- name: test
dependencies: [redis, dragonfly, keycloak, zitadel, garage, versitygw]
image: *lane-fsi
imagePullPolicy: IfNotPresent
command: *lane-fsi-command
args: [/orchestration/test.fsx]
env: *fixture-env
resources:
requests: {cpu: 50m, memory: 128Mi}
limits: {cpu: 500m, memory: 512Mi}
securityContext: *lane-restricted

View file

@ -0,0 +1,398 @@
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: nuthatch-delivery
namespace: project-delivery
labels:
app.kubernetes.io/name: project-delivery
app.kubernetes.io/instance: nuthatch
spec:
entrypoint: workflow
serviceAccountName: project-delivery-executor
automountServiceAccountToken: false
executor:
serviceAccountName: project-delivery-executor
parallelism: 4
podGC:
strategy: OnWorkflowCompletion
podMetadata:
labels:
app.kubernetes.io/name: project-delivery
delivery.quorate.dev/project: nuthatch
podSpecPatch: |
dnsConfig:
options:
- name: ndots
value: "1"
containers:
- name: wait
volumeMounts:
- name: exec-sa-token
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
readOnly: true
volumes:
- name: exec-sa-token
secret: null
projected:
defaultMode: 0440
sources:
- serviceAccountToken:
expirationSeconds: 3600
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
arguments:
parameters:
- name: source-repository
- name: source-ref
- name: source-revision
- name: targets
- name: build-kind
value: release
templates:
- name: workflow
steps:
- - name: initialize-workspace
template: initialize-workspace
- - name: delivery
template: delivery
arguments:
parameters:
- name: working-pvc
value: "{{steps.initialize-workspace.outputs.parameters.working-pvc}}"
outputs:
parameters:
- name: delivery-result
valueFrom:
parameter: "{{steps.delivery.outputs.parameters.delivery-result}}"
- name: initialize-workspace
metadata:
labels:
delivery.quorate.dev/stage: nuthatch-workspace-init
container:
image: &runner registry.quorate.internal/quorate/fsharp-runner@sha256:e4cbf2cfcbd903ff4600590b84a08c0e09d95fa1e2edda4daf8d32a6aeda35f7
command: &fsi [/usr/share/dotnet/dotnet, /opt/fsi/fsi.dll, --exec]
args: [/orchestration/initialize.fsx]
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
resources:
requests: {cpu: 250m, memory: 128Mi}
limits: {cpu: "1", memory: 512Mi}
securityContext: &restricted
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}
readOnlyRootFilesystem: true
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: workflow-workspace, mountPath: /workspace}
- {name: temporary, mountPath: /tmp}
volumes:
- {name: orchestration, configMap: {name: nuthatch-delivery-orch, defaultMode: 0444}}
- {name: temporary, emptyDir: {}}
- name: workflow-workspace
ephemeral:
volumeClaimTemplate:
spec:
accessModes: [ReadWriteOnce]
storageClassName: openebs-hostpath-ssd
resources:
requests:
storage: 100Gi
outputs:
parameters:
- name: working-pvc
valueFrom: {path: /workspace/.claim-name}
- name: delivery
inputs:
parameters:
- name: working-pvc
dag:
tasks:
- name: tools
template: tools
arguments:
parameters:
- {name: working-pvc, value: "{{inputs.parameters.working-pvc}}"}
- name: source
dependencies: [tools]
template: source
arguments:
parameters:
- {name: working-pvc, value: "{{inputs.parameters.working-pvc}}"}
- name: toolchain
template: toolchain
arguments:
parameters:
- {name: working-pvc, value: "{{inputs.parameters.working-pvc}}"}
- name: cache-pull
template: cache-pull
arguments:
parameters:
- {name: working-pvc, value: "{{inputs.parameters.working-pvc}}"}
- name: build
dependencies: [source, toolchain, cache-pull]
template: build
arguments:
parameters:
- {name: working-pvc, value: "{{inputs.parameters.working-pvc}}"}
- name: publish
dependencies: [build]
template: publish
arguments:
parameters:
- {name: working-pvc, value: "{{inputs.parameters.working-pvc}}"}
- name: cache-export
dependencies: [build]
template: cache-export
continueOn:
failed: true
error: true
arguments:
parameters:
- {name: working-pvc, value: "{{inputs.parameters.working-pvc}}"}
outputs:
parameters:
- name: delivery-result
valueFrom:
parameter: "{{tasks.publish.outputs.parameters.delivery-result}}"
- name: source
inputs: &working-pvc-input
parameters:
- name: working-pvc
metadata:
labels:
delivery.quorate.dev/stage: nuthatch-source
container:
image: *runner
command: *fsi
args: [/orchestration/source.fsx]
env:
- {name: SOURCE_REPOSITORY, value: "{{workflow.parameters.source-repository}}"}
- {name: SOURCE_REVISION, value: "{{workflow.parameters.source-revision}}"}
resources:
requests: {cpu: 50m, memory: 64Mi}
limits: {cpu: 500m, memory: 256Mi}
securityContext: *restricted
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: workflow-workspace, mountPath: /tools, subPath: tools, readOnly: true}
- {name: workflow-workspace, mountPath: /source, subPath: source}
- {name: workflow-workspace, mountPath: /tmp, subPath: source-tmp}
volumes:
- {name: orchestration, configMap: {name: nuthatch-delivery-orch, defaultMode: 0444}}
- &workflow-workspace
name: workflow-workspace
persistentVolumeClaim:
claimName: "{{inputs.parameters.working-pvc}}"
- name: tools
inputs: *working-pvc-input
metadata:
labels:
delivery.quorate.dev/stage: nuthatch-toolchain
container:
image: *runner
command: *fsi
args: [/orchestration/tools.fsx]
resources:
requests: {cpu: 100m, memory: 128Mi}
limits: {cpu: "1", memory: 1Gi}
securityContext: *restricted
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: workflow-workspace, mountPath: /workspace, subPath: tools}
- {name: temporary, mountPath: /tmp}
volumes:
- {name: orchestration, configMap: {name: nuthatch-delivery-orch, defaultMode: 0444}}
- *workflow-workspace
- {name: temporary, emptyDir: {}}
- name: toolchain
inputs: *working-pvc-input
podSpecPatch: |
runtimeClassName: gvisor
metadata:
labels:
delivery.quorate.dev/stage: nuthatch-toolchain
container:
image: *runner
command: *fsi
args: [/orchestration/dependencies.fsx]
env:
- {name: BUILD_KIND, value: "{{workflow.parameters.build-kind}}"}
resources:
requests: {cpu: 500m, memory: 1Gi}
limits: {cpu: "3", memory: 8Gi}
securityContext: *restricted
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: runtime-lock, mountPath: /runtime-lock, readOnly: true}
- {name: workflow-workspace, mountPath: /source, subPath: source, readOnly: true}
- {name: workflow-workspace, mountPath: /plan, subPath: state, readOnly: true}
- {name: workflow-workspace, mountPath: /workspace, subPath: toolchain}
- {name: workflow-workspace, mountPath: /tmp, subPath: toolchain/tmp}
volumes:
- {name: orchestration, configMap: {name: nuthatch-delivery-orch, defaultMode: 0444}}
- *workflow-workspace
- {name: runtime-lock, configMap: {name: nuthatch-runtime-lock, defaultMode: 0444}}
- name: cache-pull
inputs: *working-pvc-input
metadata:
labels:
delivery.quorate.dev/stage: nuthatch-cache-pull
container:
image: *runner
command: *fsi
args: [/orchestration/cache.fsx]
env:
- {name: BUILD_KIND, value: "{{workflow.parameters.build-kind}}"}
- {name: CACHE_ACTION, value: pull}
- {name: SOURCE_REVISION, value: "{{workflow.parameters.source-revision}}"}
resources:
requests: {cpu: "2", memory: 1Gi}
limits: {cpu: "6", memory: 4Gi}
securityContext: *restricted
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: runtime-lock, mountPath: /runtime-lock, readOnly: true}
- {name: cache-auth, mountPath: /cache-auth, readOnly: true}
- {name: cache-ca, mountPath: /cache-ca, readOnly: true}
- {name: workflow-workspace, mountPath: /source, subPath: source}
- {name: workflow-workspace, mountPath: /toolchain, subPath: toolchain}
- {name: workflow-workspace, mountPath: /state, subPath: state}
- {name: workflow-workspace, mountPath: /plan, subPath: state}
- {name: workflow-workspace, mountPath: /state/restored-build-state/dist-newstyle, subPath: output/dist-newstyle}
- {name: workflow-workspace, mountPath: /tmp, subPath: state/cache-tmp}
volumes:
- {name: orchestration, configMap: {name: nuthatch-delivery-orch, defaultMode: 0444}}
- {name: cache-auth, secret: {secretName: project-delivery-cache-reader, defaultMode: 0440}}
- {name: cache-ca, secret: {secretName: quay-internal-ca, defaultMode: 0440}}
- *workflow-workspace
- {name: runtime-lock, configMap: {name: nuthatch-runtime-lock, defaultMode: 0444}}
- name: build
inputs: *working-pvc-input
podSpecPatch: |
runtimeClassName: gvisor
metadata:
labels:
delivery.quorate.dev/stage: nuthatch-build
container:
image: *runner
command: *fsi
args: [/orchestration/build.fsx]
env:
- {name: BUILD_KIND, value: "{{workflow.parameters.build-kind}}"}
- {name: SOURCE_REVISION, value: "{{workflow.parameters.source-revision}}"}
- {name: XDG_CACHE_HOME, value: /state}
resources:
requests: {cpu: "6", memory: 8Gi}
limits: {cpu: "12", memory: 24Gi}
securityContext: *restricted
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: apk-signing, mountPath: /apk-signing, readOnly: true}
- {name: runtime-config, mountPath: /configuration, readOnly: true}
- {name: workflow-workspace, mountPath: /workspace, subPath: output}
- {name: workflow-workspace, mountPath: /workspace/source, subPath: source/source, readOnly: true}
- {name: workflow-workspace, mountPath: /workspace/dependencies, subPath: toolchain, readOnly: true}
- {name: workflow-workspace, mountPath: /workspace/toolchain, subPath: toolchain/toolchain, readOnly: true}
- {name: workflow-workspace, mountPath: /workspace/cabal-home, subPath: toolchain/cabal-home}
- {name: workflow-workspace, mountPath: /workspace/state-input, subPath: state}
- {name: workflow-workspace, mountPath: /plan, subPath: state, readOnly: true}
- {name: workflow-workspace, mountPath: /state, subPath: output/state}
- {name: workflow-workspace, mountPath: /tmp, subPath: output/tmp}
volumes:
- {name: orchestration, configMap: {name: nuthatch-delivery-orch, defaultMode: 0444}}
- {name: apk-signing, secret: {secretName: apk-signing, defaultMode: 0440}}
- *workflow-workspace
- name: runtime-config
configMap: {name: nuthatch-runtime, defaultMode: 0444}
- name: publish
inputs: *working-pvc-input
metadata:
labels:
delivery.quorate.dev/stage: publish-internal
container:
image: *runner
command: *fsi
args: [/orchestration/push.fsx]
env:
- {name: BUILD_KIND, value: "{{workflow.parameters.build-kind}}"}
- {name: SOURCE_REVISION, value: "{{workflow.parameters.source-revision}}"}
- {name: TARGETS, value: "{{workflow.parameters.targets}}"}
resources:
requests: {cpu: 250m, memory: 512Mi}
limits: {cpu: "2", memory: 2Gi}
securityContext: *restricted
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: registry-auth, mountPath: /auth, readOnly: true}
- {name: registry-ca, mountPath: /registry-ca, readOnly: true}
- {name: workflow-workspace, mountPath: /handoff, subPath: output, readOnly: true}
- {name: workflow-workspace, mountPath: /result, subPath: output/result}
- {name: workflow-workspace, mountPath: /tmp, subPath: output/publish-tmp}
volumes:
- {name: orchestration, configMap: {name: nuthatch-delivery-orch, defaultMode: 0444}}
- {name: registry-auth, secret: {secretName: quay-writer, defaultMode: 0440}}
- {name: registry-ca, secret: {secretName: quay-internal-ca, defaultMode: 0440}}
- *workflow-workspace
outputs:
parameters:
- name: delivery-result
valueFrom: {path: /result/delivery-result}
- name: cache-export
inputs: *working-pvc-input
metadata:
labels:
delivery.quorate.dev/stage: nuthatch-cache-export
container:
image: *runner
command: *fsi
args: [/orchestration/cache.fsx]
env:
- {name: CACHE_ACTION, value: export}
resources:
requests: {cpu: "6", memory: 2Gi}
limits: {cpu: "12", memory: 8Gi}
securityContext: *restricted
volumeMounts:
- {name: orchestration, mountPath: /orchestration, readOnly: true}
- {name: cache-auth, mountPath: /cache-auth, readOnly: true}
- {name: cache-ca, mountPath: /cache-ca, readOnly: true}
- {name: workflow-workspace, mountPath: /plan, subPath: state, readOnly: true}
- {name: workflow-workspace, mountPath: /toolchain, subPath: toolchain, readOnly: true}
- {name: workflow-workspace, mountPath: /build-output, subPath: output, readOnly: true}
- {name: workflow-workspace, mountPath: /tmp, subPath: output/cache-tmp}
volumes:
- {name: orchestration, configMap: {name: nuthatch-delivery-orch, defaultMode: 0444}}
- {name: cache-auth, secret: {secretName: project-delivery-cache-writer, defaultMode: 0440}}
- {name: cache-ca, secret: {secretName: quay-internal-ca, defaultMode: 0440}}
- *workflow-workspace