ci: split GitOps state into cloud-host-gitops repo, add Sealed Secrets, fix pipeline auth
Build and Deploy Platform / build-and-deploy (push) Failing after 20m1s

- Workflow now pushes image tags to the separate cloud-host-gitops repo
  (no more CI loop risk) and authenticates via CI_TOKEN secret
- Fix undefined ${REGISTRY} in Kaniko jobs, add concurrency group,
  targeted tag update, and mounted kaniko-harbor-auth docker config
- Argo CD Application is now multi-source (chart from cloud-host,
  values from cloud-host-gitops)
- Remove plaintext runner token and proxy credentials from manifests;
  secrets are now SealedSecrets in the gitops repo

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-07-02 14:10:46 +03:30
parent d4559920d1
commit 7e66d1edf3
10 changed files with 390 additions and 97 deletions
+51 -16
View File
@@ -3,15 +3,26 @@ on:
push:
branches: [main]
paths-ignore:
- "gitops/platform/values-abrban.yaml"
- "**.md"
workflow_dispatch:
# Serialize builds so parallel pushes don't race on the GitOps values update.
concurrency:
group: build-deploy-platform
cancel-in-progress: false
env:
REGISTRY: harbor-registry.cloudhost.svc.cluster.local:5000
# PULL_REGISTRY: kubelet pulls via k3s mirror → harbor-core (matches registry-pull-secret)
PULL_REGISTRY: registry.abrban.com
# PUSH_REGISTRY: kaniko pushes directly to harbor-registry (internal, no TLS)
PUSH_REGISTRY: harbor-registry.cloudhost.svc.cluster.local:5000
PROJECT: abrban
BUILD_NS: cloudhost-builds
GITEA_URL: http://gitea-http.gitea.svc.cluster.local:3000
GITEA_HOST: gitea-http.gitea.svc.cluster.local:3000
# PAT of the "ci" user, stored as repo secret CI_TOKEN (names starting with GITEA_ are reserved)
GITEA_TOKEN: ${{ secrets.CI_TOKEN }}
REPO_PATH: abrban/cloud-host.git
GITOPS_REPO_PATH: abrban/cloud-host-gitops.git
jobs:
build-and-deploy:
@@ -20,7 +31,7 @@ jobs:
- name: Checkout
shell: sh
run: |
git clone --depth=1 --branch main "${GITEA_URL}/abrban/cloud-host.git" workspace
git clone --depth=1 --branch main "http://oauth2:${GITEA_TOKEN}@${GITEA_HOST}/${REPO_PATH}" workspace
cd workspace
echo "Checked out $(git rev-parse --short HEAD)"
@@ -53,29 +64,37 @@ jobs:
- name: registry-pull-secret
initContainers:
- name: clone
image: ${REGISTRY}/${PROJECT}/alpine:3
image: ${PULL_REGISTRY}/${PROJECT}/alpine:3
command:
- sh
- -c
- apk add --no-cache git && git clone --depth=1 --branch main ${GITEA_URL}/abrban/cloud-host.git /workspace
- apk add --no-cache git && git clone --depth=1 --branch main http://oauth2:${GITEA_TOKEN}@${GITEA_HOST}/${REPO_PATH} /workspace
volumeMounts:
- name: ws
mountPath: /workspace
containers:
- name: kaniko
image: ${REGISTRY}/${PROJECT}/kaniko-executor:v1.27.6-debug
image: ${PULL_REGISTRY}/${PROJECT}/kaniko-executor:v1.27.6-debug
args:
- --dockerfile=/workspace/backend/Dockerfile
- --context=dir:///workspace/backend
- --destination=${REGISTRY}/${PROJECT}/cloudhost-backend:${IMAGE_TAG}
- --destination=${PUSH_REGISTRY}/${PROJECT}/cloudhost-backend:${IMAGE_TAG}
- --insecure
- --skip-tls-verify
volumeMounts:
- name: ws
mountPath: /workspace
- name: docker-config
mountPath: /kaniko/.docker
volumes:
- name: ws
emptyDir: {}
- name: docker-config
secret:
secretName: kaniko-harbor-auth
items:
- key: .dockerconfigjson
path: config.json
ENDJOB
echo "Waiting for backend build job: ${JOB_NAME}"
kubectl -n ${BUILD_NS} wait --for=condition=complete job/${JOB_NAME} --timeout=20m
@@ -101,43 +120,59 @@ jobs:
- name: registry-pull-secret
initContainers:
- name: clone
image: ${REGISTRY}/${PROJECT}/alpine:3
image: ${PULL_REGISTRY}/${PROJECT}/alpine:3
command:
- sh
- -c
- apk add --no-cache git && git clone --depth=1 --branch main ${GITEA_URL}/abrban/cloud-host.git /workspace
- apk add --no-cache git && git clone --depth=1 --branch main http://oauth2:${GITEA_TOKEN}@${GITEA_HOST}/${REPO_PATH} /workspace
volumeMounts:
- name: ws
mountPath: /workspace
containers:
- name: kaniko
image: ${REGISTRY}/${PROJECT}/kaniko-executor:v1.27.6-debug
image: ${PULL_REGISTRY}/${PROJECT}/kaniko-executor:v1.27.6-debug
args:
- --dockerfile=/workspace/frontend/Dockerfile
- --context=dir:///workspace/frontend
- --build-arg=NEXT_PUBLIC_API_URL=https://api.abrban.com
- --destination=${REGISTRY}/${PROJECT}/cloudhost-frontend:${IMAGE_TAG}
- --destination=${PUSH_REGISTRY}/${PROJECT}/cloudhost-frontend:${IMAGE_TAG}
- --insecure
- --skip-tls-verify
volumeMounts:
- name: ws
mountPath: /workspace
- name: docker-config
mountPath: /kaniko/.docker
volumes:
- name: ws
emptyDir: {}
- name: docker-config
secret:
secretName: kaniko-harbor-auth
items:
- key: .dockerconfigjson
path: config.json
ENDJOB
echo "Waiting for frontend build job: ${JOB_NAME}"
kubectl -n ${BUILD_NS} wait --for=condition=complete job/${JOB_NAME} --timeout=20m
echo "Frontend build done"
- name: Update GitOps values and push
- name: Update GitOps repo and push
shell: sh
run: |
cd workspace
sed -i "s|tag: \"[^\"]*\"|tag: \"${IMAGE_TAG}\"|g" gitops/platform/values-abrban.yaml
git clone --depth=1 --branch main "http://oauth2:${GITEA_TOKEN}@${GITEA_HOST}/${GITOPS_REPO_PATH}" gitops-repo
cd gitops-repo
VALUES=platform/values-abrban.yaml
if command -v yq >/dev/null 2>&1; then
IMAGE_TAG="${IMAGE_TAG}" yq -i '.images.backend.tag = strenv(IMAGE_TAG) | .images.frontend.tag = strenv(IMAGE_TAG)' "${VALUES}"
else
# Only touch the tag line directly below each cloudhost-* repository line.
sed -i "/repository: .*cloudhost-backend/{n;s|tag: \".*\"|tag: \"${IMAGE_TAG}\"|;}" "${VALUES}"
sed -i "/repository: .*cloudhost-frontend/{n;s|tag: \".*\"|tag: \"${IMAGE_TAG}\"|;}" "${VALUES}"
fi
git config user.email "ci@abrban.com"
git config user.name "Gitea Actions"
git add gitops/platform/values-abrban.yaml
git add "${VALUES}"
if ! git diff --cached --quiet; then
git commit -m "ci: deploy platform ${IMAGE_TAG}"
git push origin HEAD:main