Skip to content

frontend: linked changes panel on the deployment page and "ships in" on the query page #1035

Description

@babltiga

Part of #1029 (linked deployment changes epic — read it first for the big picture). Needs #1032.

Goal

Make the link visible from both ends. The deployment detail page gets a Linked changes panel
(sequence, query type, live status chip, link to /queries/:id, "ready" summary that explains a
held gate); the query detail page gets a Ships in deployment callout listing the deployment
requests that carry it. No new route, no new store.

Today pages/deployments/DeploymentDetailPage.tsx loads the request and gate with TanStack
(:75-92, keys in api/deploymentRequests.ts:11-18) and renders DetailCards at :386-468;
pages/queries/QueryDetailPage.tsx loads queryKeys.detail (:90) and stacks Alert banners
(:392-542) above its cards. types/api.ts:4368 DeploymentRequest has linked_queries
since #1030; DeploymentRequestListFilters (:4410) has no query filter.

Design constraints agreed on the epic:

  • "Ships in" is served by GET /deployment-requests?query_request_id= — the list's own
    visibility rule applies, so a viewer only sees deployments they could open. QueryDetail gains
    no field; core cannot depend on deploygov. The backend filter (DeploymentRequestListFilter
    • DeploymentRequestSpecifications.forFilter, :25) ships in this issue's PR together with its
      docs/04-api-spec.md row (:7701), DefaultDeploymentRequestServiceTest and
      DeploymentRequestControllerTest cases — document the endpoint change before the code.
  • Status chips through StatusPill / utils/statusColors.ts:153; QueryTypePill for the type;
    no hex colours.

Steps

  1. src/types/api.ts — DeploymentLinkedQuery { query_request_id; sequence_order; status: QueryStatus | null; query_type: QueryType | null; datasource_id: string | null; datasource_name: string | null }; linked_queries_ready: boolean and linked_queries on
    DeploymentGateStatus; query_request_id?: string on DeploymentRequestListFilters.
  2. src/api/deploymentRequests.ts — pass query_request_id through listDeploymentRequests;
    add deploymentKeys.forQuery(queryId) so the query page can invalidate independently.
    api/deploymentRequests.test.ts covers the new param.
  3. components/deployments/LinkedChangesPanel.tsx (new) — an antd Table inside a
    DetailCard: # (sequence_order), type (QueryTypePill), datasource, status (StatusPill,
    a muted "no longer exists" chip when null), and a Link to /queries/:id. Header shows
    "N of M ready" from the gate payload and, when not ready, the pending ids in the same tone as
    the frozen banner (deploygov.detail.bannerFrozen). Render nothing when there are no links —
    the panel must not add an empty card to every deployment.
  4. DeploymentDetailPage.tsx — mount the panel between the approvals card (:409) and the
    metadata card (:441); the releasability banner (bannerReleasable / bannerFrozen) gains a
    third state, bannerLinkedPending, when releasable is false only because of links.
  5. components/queries/ShipsInDeploymentCallout.tsx (new) — useQuery on
    deploymentKeys.forQuery(id) → listDeploymentRequests({ query_request_id: id, size: 20 }),
    enabled only when the user's org has the deployments governance domain enabled (the same
    hasPermission / domain gate the sidebar uses for /deployments), rendering an Alert with
    one line per deployment: pipeline, environment, version, StatusPill, link to
    /deployments/:id. Hidden when the list is empty; a 404/403 from a caller without
    deployment visibility is rendered as nothing, never as showApiError.
  6. QueryDetailPage.tsx — mount the callout with the other banners (:392-542), after the
    SQL-review findings so the reviewer reads "what is it" before "where does it ship".
  7. i18n — every string through t() under deploygov.linked.* and queries.detail.ships_in_*
    (snake_case, matching the queries.detail.* convention at en.json), in all seven
    src/locales/*.json; locales/__tests__/locales.parity.test.ts enforces it. Backend enum
    values through src/utils/enumLabels.ts (queryStatusLabel, :81).
  8. e2e — extend e2e/tests/deployment-review.spec.ts (serial block at :38, pipeline and
    environment created in beforeAll) with one spec: createPostgresDatasource →
    submitQueryViaApi (e2e/helpers/datasources.ts:334) with a DDL statement →
    approveQueryViaApi (:465) → triggerDeploymentViaApi (e2e/helpers/deployments.ts:119,
    extended with queryRequestIds?: string[]) → the deployment page shows the panel row with the
    query's status chip and the link opens the query page, whose callout names the deployment's
    version. Extend getDeploymentGateViaApi (:182) to expose linked_queries_ready and
    confirmDeploymentExecutionViaApi (:215) with an executeLinkedQueries option. Note: this
    requires deploygov: bind deployment environments to datasources and make sort_order meaningful #877's environment datasource_id in createDeploymentEnvironmentViaApi (:48).

Acceptance criteria

  • Component tests: LinkedChangesPanel (ordered rows, null-status chip, hidden when empty,
    "N of M ready"), ShipsInDeploymentCallout (renders per deployment, hidden on empty, hidden on
    a visibility error, disabled without the domain), and the new banner state on
    DeploymentDetailPage.test.tsx; QueryDetailPage.test.tsx mounts the callout.
  • The e2e spec passes in the main e2e variant (.claude/patterns/e2e-spec.md); selectors use
    roles and t()-driven text, no ant-* class names.
  • Backend: filter unit + controller tests, docs/04 row, MessagesParityTest untouched (no new
    backend strings).
  • npm run lint, npm run typecheck, npm run test:coverage (≥ 90 % lines / ≥ 80 % branches)
    and npm run build pass — build is stricter than typecheck (noUncheckedIndexedAccess on
    tests too), and one TS error fails all three e2e variants.
  • help-corpus/ regenerated (node .github/scripts/build-help-corpus.mjs) because en.json
    changed; the help-corpus CI job fails on drift.

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

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions