feat: update auto-deploy workflow to use Komodo API and remove webhook dependency
Some checks failed
Auto-Deploy Changed Stacks / deploy (push) Failing after 4s
Some checks failed
Auto-Deploy Changed Stacks / deploy (push) Failing after 4s
This commit is contained in:
parent
2ecc602963
commit
92b7ffce74
@ -14,56 +14,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
|
|
||||||
- name: Detect changed stacks and trigger Komodo webhooks
|
- name: Detect changed stacks and deploy via Komodo API
|
||||||
|
env:
|
||||||
|
KOMODO_URL: ${{ secrets.KOMODO_URL }}
|
||||||
|
KOMODO_API_KEY: ${{ secrets.KOMODO_API_KEY }}
|
||||||
|
KOMODO_API_SECRET: ${{ secrets.KOMODO_API_SECRET }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
# Webhook map: stack-name → Komodo webhook URL
|
|
||||||
# Komodo webhook URLs are self-authenticating (token is embedded
|
|
||||||
# in the URL path). Fill in URLs from:
|
|
||||||
# Komodo UI → Stack → Webhooks tab → copy the full URL
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
declare -A WEBHOOK_MAP
|
|
||||||
|
|
||||||
# heimdall stacks
|
|
||||||
WEBHOOK_MAP["5etools"]="TODO"
|
|
||||||
WEBHOOK_MAP["authentik"]="TODO"
|
|
||||||
WEBHOOK_MAP["bentopdf"]="TODO"
|
|
||||||
WEBHOOK_MAP["byparr"]="TODO"
|
|
||||||
WEBHOOK_MAP["convertx"]="TODO"
|
|
||||||
WEBHOOK_MAP["core"]="TODO"
|
|
||||||
WEBHOOK_MAP["docker_registry"]="TODO"
|
|
||||||
WEBHOOK_MAP["gitea"]="TODO"
|
|
||||||
WEBHOOK_MAP["guardian"]="TODO"
|
|
||||||
WEBHOOK_MAP["homelab-registry-mcp"]="TODO"
|
|
||||||
WEBHOOK_MAP["karakeep"]="TODO"
|
|
||||||
WEBHOOK_MAP["kitchenowl"]="TODO"
|
|
||||||
WEBHOOK_MAP["ntfy"]="TODO"
|
|
||||||
WEBHOOK_MAP["overseerr"]="TODO"
|
|
||||||
WEBHOOK_MAP["profilarr"]="TODO"
|
|
||||||
WEBHOOK_MAP["prowlarr"]="TODO"
|
|
||||||
WEBHOOK_MAP["radarr"]="TODO"
|
|
||||||
WEBHOOK_MAP["sabnzbd"]="TODO"
|
|
||||||
WEBHOOK_MAP["snapotter"]="TODO"
|
|
||||||
WEBHOOK_MAP["sonarr"]="TODO"
|
|
||||||
WEBHOOK_MAP["sparkyfitness"]="TODO"
|
|
||||||
WEBHOOK_MAP["tautulli"]="TODO"
|
|
||||||
WEBHOOK_MAP["tracearr"]="TODO"
|
|
||||||
WEBHOOK_MAP["trek"]="TODO"
|
|
||||||
WEBHOOK_MAP["vaultwarden"]="TODO"
|
|
||||||
WEBHOOK_MAP["vscode"]="TODO"
|
|
||||||
WEBHOOK_MAP["weatherchannel"]="TODO"
|
|
||||||
WEBHOOK_MAP["wizarr"]="TODO"
|
|
||||||
WEBHOOK_MAP["zipline"]="TODO"
|
|
||||||
|
|
||||||
# waldorf stacks
|
|
||||||
WEBHOOK_MAP["immich"]="TODO"
|
|
||||||
WEBHOOK_MAP["openwebui"]="TODO"
|
|
||||||
WEBHOOK_MAP["pinchflat"]="TODO"
|
|
||||||
WEBHOOK_MAP["plex"]="TODO"
|
|
||||||
WEBHOOK_MAP["tunarr"]="TODO"
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# Detect changed paths vs the previous commit
|
# Detect changed paths vs the previous commit
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
@ -83,7 +41,6 @@ jobs:
|
|||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
declare -A SEEN_STACKS
|
declare -A SEEN_STACKS
|
||||||
declare -a STACKS_TO_DEPLOY
|
declare -a STACKS_TO_DEPLOY
|
||||||
declare -a UNMATCHED_PATHS
|
|
||||||
|
|
||||||
while IFS= read -r filepath; do
|
while IFS= read -r filepath; do
|
||||||
[[ -z "$filepath" ]] && continue
|
[[ -z "$filepath" ]] && continue
|
||||||
@ -104,60 +61,38 @@ jobs:
|
|||||||
[[ -n "${SEEN_STACKS[$stack]+_}" ]] && continue
|
[[ -n "${SEEN_STACKS[$stack]+_}" ]] && continue
|
||||||
SEEN_STACKS["$stack"]=1
|
SEEN_STACKS["$stack"]=1
|
||||||
|
|
||||||
if [[ -n "${WEBHOOK_MAP[$stack]+_}" ]]; then
|
|
||||||
STACKS_TO_DEPLOY+=("$stack")
|
STACKS_TO_DEPLOY+=("$stack")
|
||||||
echo " Queued for deploy: $stack (node: $node)"
|
echo " Queued for deploy: $stack (node: $node)"
|
||||||
else
|
|
||||||
UNMATCHED_PATHS+=("$filepath (stack: $stack)")
|
|
||||||
fi
|
|
||||||
done <<< "$CHANGED_FILES"
|
done <<< "$CHANGED_FILES"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
# Warn about paths that have no webhook entry — not silent
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
if [[ "${#UNMATCHED_PATHS[@]}" -gt 0 ]]; then
|
|
||||||
echo "=== WARNING: paths with no matching webhook entry ==="
|
|
||||||
for p in "${UNMATCHED_PATHS[@]}"; do
|
|
||||||
echo " - $p"
|
|
||||||
done
|
|
||||||
echo " Add these stack names to WEBHOOK_MAP in this workflow."
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
# Nothing under nodes/ changed
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
if [[ "${#STACKS_TO_DEPLOY[@]}" -eq 0 ]]; then
|
if [[ "${#STACKS_TO_DEPLOY[@]}" -eq 0 ]]; then
|
||||||
echo "No stack changes detected — nothing to deploy."
|
echo "No stack changes detected — nothing to deploy."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# POST to each Komodo webhook
|
# Call Komodo DeployStack API for each changed stack
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
echo "=== Triggering Komodo webhooks ==="
|
echo "=== Triggering Komodo deployments ==="
|
||||||
FAILED=0
|
FAILED=0
|
||||||
|
|
||||||
for stack in "${STACKS_TO_DEPLOY[@]}"; do
|
for stack in "${STACKS_TO_DEPLOY[@]}"; do
|
||||||
url="${WEBHOOK_MAP[$stack]}"
|
|
||||||
|
|
||||||
if [[ "$url" == "TODO" ]]; then
|
|
||||||
echo " SKIP: $stack — webhook URL not configured yet (fill in WEBHOOK_MAP)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -n " → $stack ... "
|
echo -n " → $stack ... "
|
||||||
HTTP_STATUS=$(curl --silent --show-error --output /dev/null \
|
HTTP_STATUS=$(curl --silent --show-error --output /dev/null \
|
||||||
--write-out "%{http_code}" \
|
--write-out "%{http_code}" \
|
||||||
--max-time 30 \
|
--max-time 30 \
|
||||||
--request POST "$url" \
|
--request POST "${KOMODO_URL}/execute/DeployStack" \
|
||||||
--header "Content-Type: application/json" \
|
--header "Content-Type: application/json" \
|
||||||
--data '{"trigger":"gitea-push"}')
|
--header "X-Api-Key: ${KOMODO_API_KEY}" \
|
||||||
|
--header "X-Api-Secret: ${KOMODO_API_SECRET}" \
|
||||||
|
--data "{\"stack\": \"${stack}\"}")
|
||||||
|
|
||||||
if [[ "$HTTP_STATUS" =~ ^2 ]]; then
|
if [[ "$HTTP_STATUS" =~ ^2 ]]; then
|
||||||
echo "HTTP $HTTP_STATUS OK"
|
echo "HTTP $HTTP_STATUS OK"
|
||||||
|
elif [[ "$HTTP_STATUS" == "404" ]]; then
|
||||||
|
echo "HTTP 404 WARNING — stack not found in Komodo (not yet registered?)"
|
||||||
else
|
else
|
||||||
echo "HTTP $HTTP_STATUS FAILED"
|
echo "HTTP $HTTP_STATUS FAILED"
|
||||||
FAILED=1
|
FAILED=1
|
||||||
@ -166,8 +101,8 @@ jobs:
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
if [[ "$FAILED" -ne 0 ]]; then
|
if [[ "$FAILED" -ne 0 ]]; then
|
||||||
echo "ERROR: One or more Komodo webhook POSTs returned a non-2xx status."
|
echo "ERROR: One or more Komodo API calls returned a non-2xx status."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "All webhooks triggered successfully."
|
echo "All deployments triggered successfully."
|
||||||
|
|||||||
@ -47,8 +47,9 @@ Merging a PR to `main` automatically deploys every stack whose folder changed.
|
|||||||
|
|
||||||
**Before it goes live you need:**
|
**Before it goes live you need:**
|
||||||
- A Gitea Actions runner installed on Heimdall (see [SOP-003](documentation/SOPs/SOP-003-Gitea-Actions-Runner-Setup.md))
|
- A Gitea Actions runner installed on Heimdall (see [SOP-003](documentation/SOPs/SOP-003-Gitea-Actions-Runner-Setup.md))
|
||||||
- All `TODO` webhook URLs in `WEBHOOK_MAP` replaced with the actual Komodo webhook URLs
|
- A Komodo service user (`gitea-ci`) with Stack → Execute permissions and an API key generated
|
||||||
(Komodo UI → Stack → Webhooks tab → copy the full self-authenticating URL)
|
- Three Gitea repo secrets configured: `KOMODO_URL`, `KOMODO_API_KEY`, `KOMODO_API_SECRET`
|
||||||
|
- Stack folder names in this repo must match stack names in Komodo UI
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
Install and register a Gitea Actions runner on Heimdall so that the
|
Install and register a Gitea Actions runner on Heimdall so that the
|
||||||
`.gitea/workflows/auto-deploy.yml` workflow can execute when PRs are merged
|
`.gitea/workflows/auto-deploy.yml` workflow can execute when PRs are merged
|
||||||
to `main`. The runner triggers Komodo webhooks for any stack whose folder
|
to `main`. The runner calls the Komodo REST API to redeploy any stack whose
|
||||||
changed in the push.
|
folder changed in the push — no per-stack webhook URLs required.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -23,7 +23,8 @@ changed in the push.
|
|||||||
- [ ] Docker and Docker Compose running on Heimdall
|
- [ ] Docker and Docker Compose running on Heimdall
|
||||||
- [ ] Gitea instance accessible at `https://git.castaldifamily.com`
|
- [ ] Gitea instance accessible at `https://git.castaldifamily.com`
|
||||||
- [ ] Admin or repo-owner access to the `nathan/homelab` Gitea repository
|
- [ ] Admin or repo-owner access to the `nathan/homelab` Gitea repository
|
||||||
- [ ] Komodo webhook URLs retrieved from Komodo UI (see [Step 4](#step-4--add-required-secrets-in-gitea))
|
- [ ] Komodo service user created with Stack → Execute permissions (see [Step 4](#step-4--create-komodo-service-user-and-api-key))
|
||||||
|
- [ ] API key + secret copied and ready to add as Gitea secrets
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -108,38 +109,43 @@ Verify the runner appears in Gitea:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Step 4 — Add Required Secrets in Gitea
|
## Step 4 — Create Komodo Service User and API Key
|
||||||
|
|
||||||
The auto-deploy workflow does not use a shared secret (Komodo webhook URLs
|
The workflow authenticates to Komodo using a dedicated service user with
|
||||||
are self-authenticating). No repository secrets are required for the
|
minimal permissions. Do not use your personal admin account.
|
||||||
workflow itself.
|
|
||||||
|
|
||||||
If you later need to store additional credentials (e.g., a Komodo API key
|
### 4a — Create the service user
|
||||||
for a future workflow), add them at:
|
|
||||||
|
|
||||||
> **Repository** → **Settings** → **Secrets and Variables** → **Actions** → **New secret**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 5 — Fill In Webhook URLs
|
|
||||||
|
|
||||||
Open `.gitea/workflows/auto-deploy.yml` in the repo and replace each `TODO`
|
|
||||||
value in `WEBHOOK_MAP` with the actual URL from Komodo:
|
|
||||||
|
|
||||||
1. Log into Komodo UI (`https://komodo.castaldifamily.com`)
|
1. Log into Komodo UI (`https://komodo.castaldifamily.com`)
|
||||||
2. Navigate to **Stacks** → select the stack
|
2. Go to **Settings** → **Users** → **New User**
|
||||||
3. Open the **Webhooks** tab
|
3. Set type to **Service**
|
||||||
4. Copy the full webhook URL (token is embedded in the path)
|
4. Name it something like `gitea-ci`
|
||||||
5. Paste it as the map value for that stack name
|
5. Grant **Execute** permission on **Stacks** only — no write or delete access
|
||||||
|
6. Save the user
|
||||||
|
|
||||||
Commit the updated workflow file to `main` (or merge a PR that includes it).
|
### 4b — Generate an API key
|
||||||
|
|
||||||
> **Never paste webhook URLs into public forks or issue comments.** They are
|
1. Open the `gitea-ci` user → **Api Keys** → **New Api Key**
|
||||||
> equivalent to credentials.
|
2. Copy both the **key** and the **secret** immediately — the secret is not shown again
|
||||||
|
|
||||||
|
### 4c — Add secrets to Gitea
|
||||||
|
|
||||||
|
In Gitea: **Repository** → **Settings** → **Secrets and Variables** → **Actions** → **New secret**
|
||||||
|
|
||||||
|
Add all three:
|
||||||
|
|
||||||
|
| Secret name | Value |
|
||||||
|
|---|---|
|
||||||
|
| `KOMODO_URL` | `https://komodo.castaldifamily.com` |
|
||||||
|
| `KOMODO_API_KEY` | API key from step 4b |
|
||||||
|
| `KOMODO_API_SECRET` | API secret from step 4b |
|
||||||
|
|
||||||
|
> **Security:** Never commit these values to the repo. The workflow reads them
|
||||||
|
> from Gitea secrets at runtime.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Step 6 — Verify End-to-End
|
## Step 5 — Verify End-to-End
|
||||||
|
|
||||||
1. Make a trivial change to any stack folder (e.g., add a blank line to
|
1. Make a trivial change to any stack folder (e.g., add a blank line to
|
||||||
`nodes/heimdall/sonarr/compose.yaml`)
|
`nodes/heimdall/sonarr/compose.yaml`)
|
||||||
@ -154,10 +160,10 @@ Commit the updated workflow file to `main` (or merge a PR that includes it).
|
|||||||
|
|
||||||
Queued for deploy: sonarr (node: heimdall)
|
Queued for deploy: sonarr (node: heimdall)
|
||||||
|
|
||||||
=== Triggering Komodo webhooks ===
|
=== Triggering Komodo deployments ===
|
||||||
→ sonarr ... HTTP 200 OK
|
→ sonarr ... HTTP 200 OK
|
||||||
|
|
||||||
All webhooks triggered successfully.
|
All deployments triggered successfully.
|
||||||
```
|
```
|
||||||
|
|
||||||
6. In Komodo UI, verify the `sonarr` stack shows a recent deployment event
|
6. In Komodo UI, verify the `sonarr` stack shows a recent deployment event
|
||||||
@ -170,10 +176,10 @@ Commit the updated workflow file to `main` (or merge a PR that includes it).
|
|||||||
|---|---|
|
|---|---|
|
||||||
| Runner shows **Offline** in Gitea | `docker compose logs runner` on Heimdall; check `GITEA_INSTANCE_URL` reachability |
|
| Runner shows **Offline** in Gitea | `docker compose logs runner` on Heimdall; check `GITEA_INSTANCE_URL` reachability |
|
||||||
| Job never picks up | Runner label must match `runs-on` in the workflow (`ubuntu-latest`) |
|
| Job never picks up | Runner label must match `runs-on` in the workflow (`ubuntu-latest`) |
|
||||||
| `HTTP 404` on webhook POST | URL in `WEBHOOK_MAP` is wrong; re-copy from Komodo UI |
|
| `HTTP 401` / `403` on DeployStack call | Check `KOMODO_API_KEY` / `KOMODO_API_SECRET` secrets are set correctly in Gitea |
|
||||||
| `HTTP 401` / `403` on webhook POST | URL token is stale; regenerate webhook in Komodo UI |
|
| `HTTP 404` on DeployStack call | Stack name in repo folder does not match the name registered in Komodo UI |
|
||||||
|
| `HTTP 404` logged as WARNING, not failure | Expected — stack exists in repo but isn't registered in Komodo yet |
|
||||||
| Job shows `HEAD~1` diff error | Ensure `fetch-depth: 2` is set in the checkout step |
|
| Job shows `HEAD~1` diff error | Ensure `fetch-depth: 2` is set in the checkout step |
|
||||||
| Stack not in `WEBHOOK_MAP` | Logged as a warning in job output; add the stack name to the map |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user