Skip to content

Wayfinder: CodeQ deployment — seamless staging/prod updates without stale binaries/configs #16

Description

@Kenny-Heitritter

Destination

A charted route with every remediation decision locked so that, in a follow-up execution effort, a push to qBraid/opencode staging/main reliably reaches all Lab users on that environment with no stale codeq binary and no stale codeq config — and so the deployment path is correctly documented.

Planning only (destination (a)). This map decides and specs; it does not implement the Terraform/script changes. The map is done when nothing is left to decide before an implementer can execute.

Anchor artifact: CODEQ_DEPLOYMENT.md in this repo.

Notes

  • Domain: qBraid CodeQ (rebranded sst/opencode fork) delivery to JupyterLab singleuser pods on GKE staging/prod.
  • The 3-hop pipeline (see anchor doc): push → binary in GCS (auto) → Lab image rebuild (not auto) → user pod (auto for new pods only).
  • The three staleness layers: (1) binary→image decoupling, (2) image→running-pod, (3) config persistence.
  • Cross-repo source of truth for the GCP side is NOT this repo: Terraform in qbraid-infrastructure owns the Cloud Build triggers (opencode-{staging-branch,prod-main}, build-lab-base[-prod]); qbraid-Dstacks owns the Lab image + runtime codeq scripts.
  • Read before deciding: qbraid-infrastructure/docs/architecture/v2-ci-cd-strategy.md (ADR Q2/Q4), .../docs/contributing/opencode-fork-maintenance.md, and qbraid-Dstacks/CLAUDE.md §5 — the 2026-06-11 chained-trigger cascade post-mortem (a mis-scoped chain pushed a wrong-repo image to prod; any layer-1 automation must not repeat it).
  • Skills per session: /grilling + /domain-modeling for decision tickets; /research for AFK investigation.
  • Planning-by-default is IN EFFECT — tickets resolve decisions, not deliverables.

Decisions so far

  • Design & compare layer-1 auto-rebuild mechanisms (codeq binary → Lab image) — compared Pub/Sub-chain / GCS-notify→Cloud-Function / hardened-manual; recommends Pub/Sub chain for staging + manual for prod, with narrow-trigger + per-env-topic + explicit-branch guardrails against the 2026-06-11 cascade, and stamp git SHA/build-id into manifest.json + codeq --version first. Full comparison in the ticket. Feeds Decide & lock the layer-1 rebuild mechanism #19.
  • Decide running-pod refresh policy (layer 2) — layer-2 = passive convergence (idle-cull + re-login) for routine updates; documented manual break-glass drain for security-critical; no in-Lab banner, no automated drain. Only execution artifact is documentation (convergence window + break-glass runbook line → feeds Validate & complete the CodeQ deployment documentation #17).
  • Decide config-migration systematization (layer 3) — layer-3 = one uniform high-authority re-assert stays in update-codeq-token.sh (qbraid-Dstacks); rejected versioned-migration framework, .well-known defaults channel, and binary-side migration. Config is .optional() + binary-defaulted, so only explicit persisted values go stale. The opencode→Dstacks contract is scoped + registry-backed: obligation bites only on force-correct-worthy changes (rename / retire-id / forced-default / new-injected-field); a System-owned config fields registry in CODEQ_DEPLOYMENT.md is the single source of truth the Dstacks block mirrors. Execution = two doc/organization edits, no Terraform. ⚠️ overlay copy of the script has drifted to the pre-migration version — reconcile during execution (lab-base is canonical).
  • Decide & lock the layer-1 rebuild mechanism — locked mechanism A both envs, realized as a direct gcloud builds triggers run build-lab-base[-prod] step on the codeq build (no Pub/Sub topic, no chain-rebuild-* trigger — those are being retired; anchor only on qbraid-Dstacks triggers). Staging auto now; prod wired but the firing step stays off until lab-base Trivy is back to --exit-code=1 (+ smoke-test + verify prod bucket versioning). SHA/build-id stamping is Phase 0. Rollback = forward-fix (revert+push) primary, GCS-versioning restore as fast break-glass, Decide running-pod refresh policy (layer 2) #21 drain for pods. Full ordered spec + anti-cascade guardrails in the ticket. Graduated the smoke-test fog → Decide & spec the rollout smoke-test (did a codeq change reach all users?) #22.
  • Decide & spec the rollout smoke-test (did a codeq change reach all users?) — smoke-test asserts one claim: lab-base:latest carries the expected codeq SHA (manifest.json sha vs in-image codeq --version; pass-key sha, no image label). Two identical checks both envs: (A) fail-closed assert-codeq-sha step in build-lab-base[-prod] before the deferred images: push (mismatch aborts the build → :latest never poisoned; a guard on Decide & lock the layer-1 rebuild mechanism #19's auto-rebuild) + (B) operator one-liner verify-codeq-rollout.sh <env> against the live Artifact-Registry image (registry-read only, no pod shell). "Live for all users" ≙ image source correct; running-pod convergence self-corrects on restart per Decide running-pod refresh policy (layer 2) #21not measured/gated; rejected cron + stale-pod enumeration. Satisfies Decide & lock the layer-1 rebuild mechanism #19 Phase-2 go-live item 2; feeds CODEQ_DEPLOYMENT.md.

Not yet specified

  • Staging/dev codeq-gcs-upload.yml inconsistency. On non-main branches it's still the upstream-shaped workflow_dispatch build that includes linux-x64 and targets the prod gs://qbraid-codeq bucket. Whether/how to converge it is a possible cleanup decision.
  • BMA / multi-cloud (non-GKE) instances. The same three layers apply via the AMI-bake path (qbraid-arch/qbraid-BMA/IMAGES-AND-AMIS.md). Whether this map extends there or defers to that runbook.

Out of scope

  • Implementing the fixes (writing/landing Terraform, a Cloud Function, or script changes). Destination is planning-only; execution is a separate follow-up map.
  • Mac/Windows/linux-arm64 desktop & CLI codeq distribution (the codeq-gcs-upload.yml GitHub Actions path). Not the staging/prod Lab-instance path this effort targets.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    wayfinder:mapWayfinder shared map (index of an effort)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions