-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Continuously Deploy Main
Goal
On every push to main, build a container image and deploy it to the Kubernetes cluster.
Architecture
The workflow has two jobs:
- Build - Reuse the existing
container.yamlworkflow to build, push, and sign the container image toghcr.io/holos-run/holos-console. - Deploy - Use
kubectlwith Kustomize to patch the Deployment image tag and apply it to the cluster.
Phases
Phase 1: Wire container.yaml as a reusable workflow
Add workflow_call trigger to container.yaml so the CD workflow can call it and receive the image tag as an output. This avoids duplicating the build logic.
Add inputs and outputs for workflow_call matching the existing workflow_dispatch interface.
Phase 2: Create the Kustomize overlay
Create deploy/cd/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
images:
- name: ghcr.io/holos-run/holos-console
newTag: PLACEHOLDERCreate deploy/cd/deployment.yaml containing the base Deployment resource stripped of status and server-managed fields. The workflow will use kustomize edit set image to replace the tag at deploy time.
Phase 3: Create the CD workflow
Create .github/workflows/cd.yaml triggered on pushes to main.
Job 1: build
- Call the existing
container.yamlas a reusable workflow viauses: ./.github/workflows/container.yaml. - Receives the image tag as an output.
Job 2: deploy
- Depends on
build. - Checks out the repo, sets up kubectl, writes kubeconfig from secret, runs
kustomize edit set imagethenkubectl apply -k .. - Verifies rollout completes.
Phase 4: Secrets the platform operator must provide
The deploy job needs kubectl access to the Kubernetes cluster over the public internet. One GitHub repository secret is required:
| Secret Name | Description |
|---|---|
KUBECONFIG_DATA |
Base64-encoded kubeconfig file scoped to the holos-console namespace |
Steps for the platform operator:
-
Create a ServiceAccount for CD on the cluster:
kubectl -n holos-console create serviceaccount github-cd
-
Create an RBAC Role and RoleBinding scoped to the
holos-consolenamespace:kubectl -n holos-console create role github-cd \ --verb=get,list,watch,patch,update \ --resource=deployments,replicasets,pods kubectl -n holos-console create rolebinding github-cd \ --role=github-cd \ --serviceaccount=holos-console:github-cd
-
Create a long-lived token for the ServiceAccount:
kubectl -n holos-console apply -f - <<'EOF' apiVersion: v1 kind: Secret metadata: name: github-cd-token annotations: kubernetes.io/service-account.name: github-cd type: kubernetes.io/service-account-token EOF
-
Build a kubeconfig using the token and cluster CA:
TOKEN=$(kubectl -n holos-console get secret github-cd-token -o jsonpath='{.data.token}' | base64 -d) CA=$(kubectl -n holos-console get secret github-cd-token -o jsonpath='{.data.ca\.crt}') SERVER="https://<cluster-api-endpoint>:6443" cat > /tmp/cd-kubeconfig.yaml <<EOF apiVersion: v1 kind: Config clusters: - cluster: certificate-authority-data: ${CA} server: ${SERVER} name: odin contexts: - context: cluster: odin namespace: holos-console user: github-cd name: github-cd@odin current-context: github-cd@odin users: - name: github-cd user: token: ${TOKEN} EOF
-
Add the GitHub secret:
gh secret set KUBECONFIG_DATA < <(base64 -w0 /tmp/cd-kubeconfig.yaml) rm /tmp/cd-kubeconfig.yaml
Phase 5: Final cleanup
Scan for dead code, stale docs, or outdated references introduced by the plan.
Workflow sketch
name: CD
on:
push:
branches: [main]
jobs:
build:
uses: ./.github/workflows/container.yaml
with:
git_ref: refs/heads/main
permissions:
contents: read
packages: write
attestations: write
id-token: write
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- name: Configure kubeconfig
run: echo "$KUBECONFIG_DATA" | base64 -d > "$RUNNER_TEMP/kubeconfig"
env:
KUBECONFIG_DATA: ${{ secrets.KUBECONFIG_DATA }}
- name: Deploy
env:
KUBECONFIG: ${{ runner.temp }}/kubeconfig
run: |
cd deploy/cd
kustomize edit set image "ghcr.io/holos-run/holos-console=${{ needs.build.outputs.tag }}"
kubectl apply -k .
- name: Verify rollout
env:
KUBECONFIG: ${{ runner.temp }}/kubeconfig
run: kubectl -n holos-console rollout status deployment/holos-console --timeout=120sTest plan
- Push a commit to
mainand verify the workflow builds the image and deploys it. - Verify the deployed image tag matches the build output.
- Verify the rollout completes successfully.