You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #1029 (linked deployment changes epic — read it first for the big picture). Needs #1032.
Goal
Let every CI wrapper pass the linked query ids and ask the deployment to run them, and document
the recipe a pipeline follows to get its migrations governed first. Same four beats as today —
submit idempotently by run id → poll the gate → confirm → report the outcome
(docs/18-deployment-governance.md:362-368) — with one more field on the submit body and one on
the confirm body. .github/actions/deployment-outcome is unchanged.
Today .github/actions/deployment-gate/deployment-gate.sh:58-64 assembles the submit body with jq -n and add_str (:66) appends optional scalars; the GitLab hidden job builds the same body
at ci-templates/gitlab/accessflow-deployment.gitlab-ci.yml:64-70, the Azure template at ci-templates/azure/accessflow-deployment.yml:85-95 from parameters mapped at :133-145, and ci-templates/examples/generic-curl-deployment.md §1 (:15) shows the raw curl. The offline
harness .github/actions/tests/deployment-gate-test.sh scripts responses through .github/actions/tests/fake-curl.sh and asserts body fields with assert_body_field (:84,
used at :105-114). The run-query action executes a query the moment it is approved
(.github/actions/run-query/run-query.sh:66-75).
Design constraints agreed on the epic:
Wire names are snake_case: query_request_ids (array), execute_linked_queries (boolean).
Fail closed everywhere: a 409 DEPLOYMENT_LINKED_QUERY_FAILED on confirm fails the job with the
problem detail printed, exactly like every other >= 400 (deployment-gate.sh:92-95).
.github/actions/deployment-gate/action.yml — inputs query-request-ids (comma-separated
UUIDs, optional; whitespace tolerated) and execute-linked-queries ("false" default), wired
as AF_QUERY_REQUEST_IDS / AF_EXECUTE_LINKED_QUERIES next to AF_METADATA_FILE (:85).
Output linked-queries-ready from the last gate poll, beside ai-risk-level (:71).
deployment-gate.sh — after add_str (:66-73): split AF_QUERY_REQUEST_IDS on commas,
trim, drop empties, and jq --argjson the array in as query_request_ids only when non-empty.
On the confirm call, send {"execute_linked_queries": true} as the body when the flag is true, otherwise keep the bodiless POST. While polling, echo linked_queries_ready=false with
the pending ids so the job log explains a held gate.
.github/actions/tests/deployment-gate-test.sh — scenarios: linked-ids-are-sent
(assert_body_field 1 '.query_request_ids | length' 2, order preserved, spaces trimmed), no-linked-ids-omits-field ('.query_request_ids // "absent"'), execute-linked-sent-on-confirm
(body of the confirm call carries execute_linked_queries: true), and linked-query-failed-409-fails-job (confirm answers 409 DEPLOYMENT_LINKED_QUERY_FAILED → exit
1, problem detail in the log, no outcome call). Wire nothing new into CI — ci.yml:665 already
runs this file.
ci-templates/gitlab/accessflow-deployment.gitlab-ci.yml — variables AF_QUERY_REQUEST_IDS
and AF_EXECUTE_LINKED_QUERIES, same jq assembly as the action; document them in the header
comment block (:15-37). ci-templates/azure/accessflow-deployment.yml — parameters queryRequestIds and executeLinkedQueries mapped to the same env names (:133-145); Azure
renders booleans as True, so match both spellings as :90 does for break-glass.
ci-templates/examples/generic-curl-deployment.md — query_request_ids in the §1 body and
the confirm body in §3; ci-templates/README.md — the two new rows in both input tables
(:45, :82, :96).
run-query learns to stop at approval. New input execute ("true" default) on .github/actions/run-query/action.yml; when "false", run-query.sh exits 0 on APPROVED
without calling /execute and reports status=APPROVED, so the deployment can run the query.
Add the equivalent variable to the GitLab run-query hidden job in ci-templates/gitlab/accessflow.gitlab-ci.yml.
Recipe — a new ci-templates/examples/github-migrations-workflow.yml: a matrix over db/migrations/*.sql that calls run-query with execute: "false", collects each query-id
output into a comma-separated string, then calls deployment-gate with query-request-ids
and execute-linked-queries: "true". Reference it from docs/16-iac.md (:191) and docs/18 §8; deploygov: linked-changes documentation sweep #1036 carries the same recipe to the website.
Acceptance criteria
bash .github/actions/tests/deployment-gate-test.sh passes with every existing scenario intact
and the four new ones green; the harness runs offline (fake curl, no network).
A run-query harness scenario (add one beside the gate scenarios if none exists) proves execute: "false" exits 0 at APPROVED and never POSTs /execute.
The GitLab and Azure templates stay valid YAML (yamllint / the actions CI job), and the
Azure boolean handling is exercised in the README example.
ci-templates/README.md, generic-curl-deployment.md and the new example are consistent with docs/04-api-spec.md field names — grep query_request_ids across ci-templates/ and .github/actions/ and every hit spells it identically.
Part of #1029 (linked deployment changes epic — read it first for the big picture). Needs #1032.
Goal
Let every CI wrapper pass the linked query ids and ask the deployment to run them, and document
the recipe a pipeline follows to get its migrations governed first. Same four beats as today —
submit idempotently by run id → poll the gate → confirm → report the outcome
(
docs/18-deployment-governance.md:362-368) — with one more field on the submit body and one onthe confirm body.
.github/actions/deployment-outcomeis unchanged.Today
.github/actions/deployment-gate/deployment-gate.sh:58-64assembles the submit body withjq -nandadd_str(:66) appends optional scalars; the GitLab hidden job builds the same bodyat
ci-templates/gitlab/accessflow-deployment.gitlab-ci.yml:64-70, the Azure template atci-templates/azure/accessflow-deployment.yml:85-95from parameters mapped at:133-145, andci-templates/examples/generic-curl-deployment.md§1 (:15) shows the raw curl. The offlineharness
.github/actions/tests/deployment-gate-test.shscripts responses through.github/actions/tests/fake-curl.shand asserts body fields withassert_body_field(:84,used at
:105-114). Therun-queryaction executes a query the moment it is approved(
.github/actions/run-query/run-query.sh:66-75).Design constraints agreed on the epic:
snake_case:query_request_ids(array),execute_linked_queries(boolean).409 DEPLOYMENT_LINKED_QUERY_FAILEDon confirm fails the job with theproblem detail printed, exactly like every other
>= 400(deployment-gate.sh:92-95).:209, and the templates forverification — rebase on it rather than renumbering scenarios.
Steps
.github/actions/deployment-gate/action.yml— inputsquery-request-ids(comma-separatedUUIDs, optional; whitespace tolerated) and
execute-linked-queries("false"default), wiredas
AF_QUERY_REQUEST_IDS/AF_EXECUTE_LINKED_QUERIESnext toAF_METADATA_FILE(:85).Output
linked-queries-readyfrom the last gate poll, besideai-risk-level(:71).deployment-gate.sh— afteradd_str(:66-73): splitAF_QUERY_REQUEST_IDSon commas,trim, drop empties, and
jq --argjsonthe array in asquery_request_idsonly when non-empty.On the confirm call, send
{"execute_linked_queries": true}as the body when the flag istrue, otherwise keep the bodiless POST. While polling, echolinked_queries_ready=falsewiththe pending ids so the job log explains a held gate.
.github/actions/tests/deployment-gate-test.sh— scenarios:linked-ids-are-sent(
assert_body_field 1 '.query_request_ids | length' 2, order preserved, spaces trimmed),no-linked-ids-omits-field('.query_request_ids // "absent"'),execute-linked-sent-on-confirm(body of the confirm call carries
execute_linked_queries: true), andlinked-query-failed-409-fails-job(confirm answers409 DEPLOYMENT_LINKED_QUERY_FAILED→ exit1, problem detail in the log, no outcome call). Wire nothing new into CI —
ci.yml:665alreadyruns this file.
ci-templates/gitlab/accessflow-deployment.gitlab-ci.yml— variablesAF_QUERY_REQUEST_IDSand
AF_EXECUTE_LINKED_QUERIES, same jq assembly as the action; document them in the headercomment block (
:15-37).ci-templates/azure/accessflow-deployment.yml— parametersqueryRequestIdsandexecuteLinkedQueriesmapped to the same env names (:133-145); Azurerenders booleans as
True, so match both spellings as:90does for break-glass.ci-templates/examples/generic-curl-deployment.md—query_request_idsin the §1 body andthe confirm body in §3;
ci-templates/README.md— the two new rows in both input tables(
:45,:82,:96).run-querylearns to stop at approval. New inputexecute("true"default) on.github/actions/run-query/action.yml; when"false",run-query.shexits 0 onAPPROVEDwithout calling
/executeand reportsstatus=APPROVED, so the deployment can run the query.Add the equivalent variable to the GitLab
run-queryhidden job inci-templates/gitlab/accessflow.gitlab-ci.yml.ci-templates/examples/github-migrations-workflow.yml: a matrix overdb/migrations/*.sqlthat callsrun-querywithexecute: "false", collects eachquery-idoutput into a comma-separated string, then calls
deployment-gatewithquery-request-idsand
execute-linked-queries: "true". Reference it fromdocs/16-iac.md(:191) anddocs/18§8; deploygov: linked-changes documentation sweep #1036 carries the same recipe to the website.Acceptance criteria
bash .github/actions/tests/deployment-gate-test.shpasses with every existing scenario intactand the four new ones green; the harness runs offline (fake curl, no network).
run-queryharness scenario (add one beside the gate scenarios if none exists) provesexecute: "false"exits 0 atAPPROVEDand never POSTs/execute.yamllint/ theactionsCI job), and theAzure boolean handling is exercised in the README example.
ci-templates/README.md,generic-curl-deployment.mdand the new example are consistent withdocs/04-api-spec.mdfield names — grepquery_request_idsacrossci-templates/and.github/actions/and every hit spells it identically.