5555 runs-on : ubuntu-latest
5656 environment : dev
5757 env :
58- ARGOCD_VERSION : " v2.13.0"
5958 BAO_VERSION : " 2.5.5"
60- REPO_URL : https://github.com/${{ github.repository }}
61- BRANCH : ${{ github.head_ref || github.ref_name }}
6259
6360 steps :
6461 - uses : actions/checkout@v4
6865 with :
6966 version : " latest"
7067
68+ - name : Install yq
69+ run : |
70+ sudo wget -qO /usr/local/bin/yq \
71+ https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
72+ sudo chmod +x /usr/local/bin/yq
73+ yq --version
74+
7175 - name : Install bao CLI
7276 run : |
7377 curl -sSfL \
@@ -76,205 +80,16 @@ jobs:
7680 sudo dpkg -i openbao.deb
7781 bao version
7882
79- - name : Install ArgoCD CLI
80- run : |
81- curl -sSfL \
82- "https://github.com/argoproj/argo-cd/releases/download/${ARGOCD_VERSION}/argocd-linux-amd64" \
83- -o argocd
84- sudo install -m 755 argocd /usr/local/bin/argocd
85- argocd version --client
86-
8783 - name : Start minikube
8884 uses : medyagh/setup-minikube@latest
8985
90- - name : Install ArgoCD
91- run : |
92- kubectl create namespace argocd
93- kubectl apply --server-side -n argocd \
94- -f "https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml"
95- kubectl rollout status deployment/argocd-server -n argocd --timeout=180s
96-
97- - name : Expose ArgoCD + login
98- id : argocd-login
99- run : |
100- kubectl port-forward svc/argocd-server -n argocd 8080:443 &
101- sleep 8
102- PASS=$(kubectl -n argocd get secret argocd-initial-admin-secret \
103- -o jsonpath="{.data.password}" | base64 -d)
104- argocd login localhost:8080 --username admin --password "${PASS}" --insecure
105- # Allow ArgoCD to pull from this (possibly private) repo via GITHUB_TOKEN
106- argocd repo add "${REPO_URL}" \
107- --username x-access-token \
108- --password "${{ secrets.GITHUB_TOKEN }}" \
109- --insecure-skip-server-verification || true
110-
111- - name : Inject S3 credentials Secret (pre-sync)
112- run : |
113- kubectl create namespace openbao --dry-run=client -o yaml | kubectl apply -f -
114- kubectl create secret generic scaleway-s3-credentials \
115- --namespace openbao \
116- --from-literal=access_key="${{ secrets.SCW_ACCESS_KEY }}" \
117- --from-literal=secret_key="${{ secrets.SCW_SECRET_KEY }}" \
118- --from-literal=bucket="${{ vars.SCW_S3_BUCKET }}"
119-
120- - name : Apply bootstrap Application
121- run : |
122- argocd app create bootstrap \
123- --repo "${REPO_URL}" \
124- --path bootstrap \
125- --dest-server https://kubernetes.default.svc \
126- --dest-namespace argocd \
127- --helm-set env=local \
128- --helm-set "revision=${BRANCH}" \
129- --helm-set "repoURL=${REPO_URL}" \
130- --sync-policy automated \
131- --upsert
132-
133- - name : Wait for OpenBao to unseal
134- id : wait-unseal
135- run : |
136- # Poll health endpoint until initialized + unsealed (HTTP 200)
137- BAO_ADDR="http://$(kubectl get svc openbao -n openbao \
138- -o jsonpath='{.spec.clusterIP}' 2>/dev/null || echo 'pending'):8200"
139- echo "BAO_ADDR=${BAO_ADDR}" >> "${GITHUB_ENV}"
140-
141- for i in $(seq 1 72); do
142- # Refresh ClusterIP in case the svc wasn't ready yet
143- CIP=$(kubectl get svc openbao -n openbao -o jsonpath='{.spec.clusterIP}' 2>/dev/null || true)
144- if [ -n "${CIP}" ]; then
145- BAO_ADDR="http://${CIP}:8200"
146- echo "BAO_ADDR=${BAO_ADDR}" >> "${GITHUB_ENV}"
147- fi
148-
149- STATUS=$(curl -sf -o /dev/null -w "%{http_code}" \
150- "${BAO_ADDR}/v1/sys/health" 2>/dev/null || echo "000")
151- echo "Attempt ${i}/72 — OpenBao status: ${STATUS}"
152-
153- if [ "${STATUS}" = "200" ] || [ "${STATUS}" = "429" ]; then
154- echo "OpenBao is unsealed."
155- break
156- fi
157- sleep 5
158- done
159-
160- if [ "${STATUS}" != "200" ] && [ "${STATUS}" != "429" ]; then
161- echo "ERROR: OpenBao did not unseal within 6 minutes"
162- kubectl get events -n openbao --sort-by='.lastTimestamp' | tail -20 || true
163- kubectl logs -l 'app.kubernetes.io/name=openbao' -n openbao --tail=50 || true
164- exit 1
165- fi
166-
167- - name : Write canary secret
168- run : |
169- CANARY_VALUE="survive-${{ github.run_id }}"
170- echo "CANARY_VALUE=${CANARY_VALUE}" >> "${GITHUB_ENV}"
171-
172- # Authenticate via Kubernetes auth using the external-secrets SA token
173- SA_JWT=$(kubectl create token external-secrets -n external-secrets --duration=5m)
174- BAO_TOKEN=$(curl -sf "${BAO_ADDR}/v1/auth/kubernetes/login" \
175- -d "{\"role\":\"external-secrets\",\"jwt\":\"${SA_JWT}\"}" \
176- | jq -r '.auth.client_token')
177-
178- curl -sf "${BAO_ADDR}/v1/kv/data/apps/test/canary" \
179- -H "X-Vault-Token: ${BAO_TOKEN}" \
180- -d "{\"data\":{\"value\":\"${CANARY_VALUE}\"}}"
181-
182- echo "Canary written: ${CANARY_VALUE}"
183-
184- # ── Cluster destroy & recreate ─────────────────────────────────────────
185-
186- - name : Destroy minikube
187- run : minikube delete
188-
189- - name : Recreate minikube
190- uses : medyagh/setup-minikube@latest
191-
192- - name : Re-install ArgoCD
193- run : |
194- kubectl create namespace argocd
195- kubectl apply --server-side -n argocd \
196- -f "https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml"
197- kubectl rollout status deployment/argocd-server -n argocd --timeout=180s
198-
199- - name : Re-expose ArgoCD + login
200- run : |
201- kubectl port-forward svc/argocd-server -n argocd 8080:443 &
202- sleep 8
203- PASS=$(kubectl -n argocd get secret argocd-initial-admin-secret \
204- -o jsonpath="{.data.password}" | base64 -d)
205- argocd login localhost:8080 --username admin --password "${PASS}" --insecure
206- argocd repo add "${REPO_URL}" \
207- --username x-access-token \
208- --password "${{ secrets.GITHUB_TOKEN }}" \
209- --insecure-skip-server-verification || true
210-
211- - name : Re-inject S3 credentials Secret
212- run : |
213- kubectl create namespace openbao --dry-run=client -o yaml | kubectl apply -f -
214- kubectl create secret generic scaleway-s3-credentials \
215- --namespace openbao \
216- --from-literal=access_key="${{ secrets.SCW_ACCESS_KEY }}" \
217- --from-literal=secret_key="${{ secrets.SCW_SECRET_KEY }}" \
218- --from-literal=bucket="${{ vars.SCW_S3_BUCKET }}"
219-
220- - name : Re-apply bootstrap Application
221- run : |
222- argocd app create bootstrap \
223- --repo "${REPO_URL}" \
224- --path bootstrap \
225- --dest-server https://kubernetes.default.svc \
226- --dest-namespace argocd \
227- --helm-set env=local \
228- --helm-set "revision=${BRANCH}" \
229- --helm-set "repoURL=${REPO_URL}" \
230- --sync-policy automated \
231- --upsert
232-
233- - name : Wait for OpenBao to unseal after recreate
234- id : wait-unseal-2
235- run : |
236- for i in $(seq 1 72); do
237- CIP=$(kubectl get svc openbao -n openbao -o jsonpath='{.spec.clusterIP}' 2>/dev/null || true)
238- if [ -n "${CIP}" ]; then BAO_ADDR="http://${CIP}:8200"; fi
239-
240- STATUS=$(curl -sf -o /dev/null -w "%{http_code}" \
241- "${BAO_ADDR}/v1/sys/health" 2>/dev/null || echo "000")
242- echo "Attempt ${i}/72 — OpenBao status: ${STATUS}"
243-
244- if [ "${STATUS}" = "200" ] || [ "${STATUS}" = "429" ]; then
245- echo "OpenBao is unsealed after recreate."
246- break
247- fi
248- sleep 5
249- done
250-
251- if [ "${STATUS}" != "200" ] && [ "${STATUS}" != "429" ]; then
252- echo "ERROR: OpenBao did not unseal after cluster recreate"
253- kubectl get events -n openbao --sort-by='.lastTimestamp' | tail -20 || true
254- exit 1
255- fi
256-
257- echo "BAO_ADDR=${BAO_ADDR}" >> "${GITHUB_ENV}"
258-
259- - name : Assert canary secret restored (SC-001)
260- run : |
261- SA_JWT=$(kubectl create token external-secrets -n external-secrets --duration=5m)
262- BAO_TOKEN=$(curl -sf "${BAO_ADDR}/v1/auth/kubernetes/login" \
263- -d "{\"role\":\"external-secrets\",\"jwt\":\"${SA_JWT}\"}" \
264- | jq -r '.auth.client_token')
265-
266- RESTORED=$(curl -sf "${BAO_ADDR}/v1/kv/data/apps/test/canary" \
267- -H "X-Vault-Token: ${BAO_TOKEN}" \
268- | jq -r '.data.data.value')
269-
270- echo "Expected : ${CANARY_VALUE}"
271- echo "Restored : ${RESTORED}"
272-
273- if [ "${RESTORED}" != "${CANARY_VALUE}" ]; then
274- echo "ERROR: Canary mismatch — secret not restored after destroy/recreate"
275- exit 1
276- fi
277- echo "OK: SC-001 verified — secrets survive cluster destroy/recreate"
86+ - name : Run smoke test (SC-001)
87+ env :
88+ SCW_ACCESS_KEY : ${{ secrets.SCW_ACCESS_KEY }}
89+ SCW_SECRET_KEY : ${{ secrets.SCW_SECRET_KEY }}
90+ SCW_S3_BUCKET : ${{ vars.SCW_S3_BUCKET }}
91+ CANARY_VALUE : survive-${{ github.run_id }}
92+ run : bash scripts/smoke-test.sh
27893
27994 - name : Assert no Infisical pods (SC-003)
28095 run : |
0 commit comments