Skip to main content

demo-web-ng-fastpath

Refresh the Kubernetes `demo` namespace with a web-ng-only change using the ServiceRadar fast path. Use when the diff only touches `elixir/web-ng/**` and the user wants a faster local demo rollout without rebuilding the full image graph. Covers scope verification, copying unchanged images forward, rebuilding the production `serviceradar-web-ng` release locally, pushing with `crane`, signing with the OpenBao release key, patching Argo, and verifying the rollout. Do not use when non-web-ng services changed or when cutting a release.

Jump to install

Source facts

Repository
carverauto/serviceradar
Last source activity
August 22, 2026 at 19:40
Detected SKILL.md language
English
Stars
919
Forks
2

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
demo-web-ng-fastpath
description
Refresh the Kubernetes `demo` namespace with a web-ng-only change using the ServiceRadar fast path. Use when the diff only touches `elixir/web-ng/**` and the user wants a faster local demo rollout without rebuilding the full image graph. Covers scope verification, copying unchanged images forward, rebuilding the production `serviceradar-web-ng` release locally, pushing with `crane`, signing with the OpenBao release key, patching Argo, and verifying the rollout. Do not use when non-web-ng services changed or when cutting a release.
# Demo Web-NG Fast Path ## Overview Use this skill when a change is isolated to `elixir/web-ng/**` and the goal is to test it in `demo` quickly. Rebuild only `serviceradar-web-ng`, copy the other `demo` images forward to the new immutable tag, sign the new web-ng image, patch Argo, and verify the rollout. Formal releases use semver tags, such as `v1.2.41`, and ArgoCD Image Updater. This skill is only for temporary unpublished `sha-...` demo testing. ## Workflow 1. Work from the repo root. 2. Determine the new immutable tag from `git rev-parse HEAD`. 3. Verify the diff only touches `elixir/web-ng/**`. 4. Identify the currently deployed `demo` tag. 5. Copy every unchanged `demo` image from the old tag to the new tag. 6. Build a local production `web-ng` release. 7. Package and push the new `serviceradar-web-ng` image with `crane`. 8. Sign the new web-ng digest with the OpenBao-backed release key. 9. Patch `serviceradar-demo-prod` to the new tag. 10. Watch Argo and the key workloads until the rollout completes. ## Guardrails - Use this only when the diff is actually `web-ng`-only. If anything outside `elixir/web-ng/**` changed, fall back to `$demo-local-rollout`. - Do not use this for release cuts or any namespace other than `demo` unless the user explicitly redirects you. - Do not leave a formal release rollout on a `sha-...` tag. After testing is complete, use `$release-cut-and-demo-roll` to return `demo` to the published semver/Image Updater path. - Do not skip signing. `demo` admission is Kyverno-enforced. - Sign by digest, not by tag, whenever possible. - Keep the other demo images identical by copying them forward from the currently deployed tag. ## Verify The Scope First Run: ```bash git diff --name-only <currently-deployed-sha>..HEAD ``` Proceed only if every changed file is under `elixir/web-ng/`. ## Copy Unchanged Images Forward Copy the unchanged images from the current demo tag to the new tag with `crane`: ```bash /tmp/gobin/crane copy \ registry.carverauto.dev/serviceradar/<image>:sha-<old> \ registry.carverauto.dev/serviceradar/<image>:sha-<new> ``` Repeat for: - `arancini` - `serviceradar-agent` - `serviceradar-agent-gateway` - `serviceradar-core-elx` - `serviceradar-datasvc` - `serviceradar-db-event-writer` - `serviceradar-faker` - `serviceradar-flow-collector` - `serviceradar-log-collector` - `serviceradar-rperf-client` - `serviceradar-tools` - `serviceradar-trapd` - `serviceradar-zen` Leave `serviceradar-log-collector-tcp` alone unless the user explicitly changed that path too. ## Build The Production Web-NG Release From `elixir/web-ng`: ```bash MIX_ENV=prod HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.compile MIX_ENV=prod HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix compile MIX_ENV=prod HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix assets.deploy MIX_ENV=prod HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix release --path /tmp/serviceradar_web_ng_release_<shortsha> ``` ## Package And Push The Web-NG Image Create the image layer tarball: ```bash tar --owner=10001 --group=10001 --transform='s,^,app/,' \ -cf /tmp/serviceradar_web_ng_layer_<shortsha>.tar \ -C /tmp/serviceradar_web_ng_release_<shortsha> . ``` Append the release onto the pinned Elixir base image and then mutate the runtime config: ```bash /tmp/gobin/crane append \ --platform linux/amd64 \ -b index.docker.io/hexpm/elixir:1.19.4-erlang-28.3-debian-bookworm-20251208-slim \ -f /tmp/serviceradar_web_ng_layer_<shortsha>.tar \ -t registry.carverauto.dev/serviceradar/serviceradar-web-ng:sha-<new> /tmp/gobin/crane mutate \ --platform linux/amd64 \ --tag registry.carverauto.dev/serviceradar/serviceradar-web-ng:sha-<new> \ --entrypoint /app/bin/serviceradar_web_ng \ --cmd start \ --env HOME=/app \ --env PATH=/app/bin:/usr/local/bin:/usr/bin:/bin \ --env PHX_SERVER=true \ --env MIX_ENV=prod \ --exposed-ports 4000/tcp \ --user 10001:10001 \ --workdir /app \ registry.carverauto.dev/serviceradar/serviceradar-web-ng:sha-<new> ``` Capture the pushed digest with: ```bash /tmp/gobin/crane digest registry.carverauto.dev/serviceradar/serviceradar-web-ng:sha-<new> ``` ## Verified Facts (2026-08-22, live run) These were each confirmed against the live `carverauto` cluster during a real web-ng roll. Do not re-derive them. - **OpenBao is HTTPS.** Through the port-forward, `https://127.0.0.1:18200` works and `http://` returns `400 Client sent an HTTP request to an HTTPS server`. - **The role is `forgejo-signing-runner` (namespace `forgejo-actions`), NOT `forgejo-runner`.** The plain `forgejo-runner` role does not exist. A successful login returns policies `["cosign-runner","default","plugin-upload-signing"]`. - **`.argocd-source-serviceradar-demo-prod.yaml` REPLACES `helm.parameters` at render time.** This is stronger than a race: a `kubectl patch` of `spec.source.helm.parameters` on `serviceradar-demo-prod` persists in the Application spec, syncs `Synced|Healthy|Succeeded`, and is still **completely ignored** — only the parameters listed in that file on `demo/prod-release` reach Helm. Any parameter you need (`global.imageTag`, `image.digests.*`) must be committed to that file on `demo/prod-release`. - **`image.digests.<service>` is a real per-service escape hatch** (`_helpers.tpl` `serviceradar.imageRefSuffix`): it short-circuits ahead of the tag, so you can move ONE service and leave every other image on the already-signed release tag — one signature instead of fifteen. Service key for web-ng is `webNg`. It still has to go in the `.argocd-source-...` file to take effect. - **`make push_all` also moves `latest`** on every image (`oci_push` carries `static_tags = ["latest"]`), despite advice elsewhere to "tag only sha-<commit>". It does NOT move `v<VERSION>`: `scripts/workspace_status.sh` emits `STABLE_VERSION dev` unless a matching `v<VERSION>` git tag points at HEAD, and `container_tags.bzl` filters `vdev`. Verify with `git tag --points-at HEAD` before pushing. - **Claude Code auto mode blocks the signing flow** unless these allow rules exist in `.claude/settings.local.json`, and the commands are run discretely (a `bash -c '...'` wrapper defeats prefix matching): `Bash(kubectl create token:*)`, `Bash(curl -sS -k -X POST https://127.0.0.1:18200/v1/auth/kubernetes/login:*)`, `Bash(cosign sign:*)`, `Bash(cosign verify:*)`. Keep the JWT and Vault token in files; never put them on a command line. ## Prepare OpenBao Signing Env Port-forward the signer if needed: ```bash kubectl port-forward -n openbao-system svc/openbao-active 18200:8200 ``` Mint a Forgejo runner service-account token and exchange it for a Vault token: ```bash OPENBAO_ADDR=https://127.0.0.1:18200 OPENBAO_K8S_ROLE=forgejo-signing-runner # NOT forgejo-runner (that role does not exist -> 403) sa_jwt="$(kubectl create token -n forgejo-actions forgejo-signing-runner)" vault_token="$({ curl -sS -k \ -H 'Content-Type: application/json' \ -d "{\"role\":\"${OPENBAO_K8S_ROLE}\",\"jwt\":\"${sa_jwt}\"}" \ "${OPENBAO_ADDR}/v1/auth/kubernetes/login" # HTTPS + -k: the listener is TLS, http:// returns 400 } | jq -er '.auth.client_token')" ``` Export: ```bash export VAULT_ADDR="$OPENBAO_ADDR" export VAULT_TOKEN="$vault_token" export COSIGN_KEY_REF=hashivault://cosign-release export COSIGN_YES=true export COSIGN_DOCKER_MEDIA_TYPES=1 export COSIGN_REFERRERS_MODE=legacy export COSIGN_TLOG_UPLOAD=true ``` If signing fails with `403 permission denied`, mint a fresh Vault token and retry. ## Sign The Web-NG Digest ```bash cosign sign --key "$COSIGN_KEY_REF" \ registry.carverauto.dev/serviceradar/serviceradar-web-ng@sha256:<digest> ``` ## Patch Demo Argo App ```bash kubectl patch application -n argocd serviceradar-demo-prod \ --type merge \ -p '{"spec":{"source":{"helm":{"parameters":[{"name":"global.imageTag","value":"sha-<new>"}]}}}}' ``` ## Verify Rollout Wait for: ```text Synced|Healthy|Succeeded ``` Use: ```bash kubectl get application -n argocd serviceradar-demo-prod \ -o jsonpath='{.status.sync.status}{"|"}{.status.health.status}{"|"}{.status.operationState.phase}{"\n"}' ``` Check the key deployments: ```bash kubectl get deploy -n demo \ serviceradar-web-ng serviceradar-core serviceradar-agent serviceradar-tools \ -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range .spec.template.spec.containers[*]}{.image}{" "}{end}{"\n"}{end}' ``` Inspect pods and jobs if Argo is still `Progressing`: ```bash kubectl get pods -n demo -o wide kubectl get jobs -n demo ``` Do not report success until the new `serviceradar-web-ng` pod is running on the new tag and Argo reaches `Succeeded`. ## Report Back Close with: - target immutable tag - old tag that was copied forward - web-ng digest that was signed - final Argo status - any lingering rollout risk
View on GitHub