Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 43 additions & 31 deletions .github/workflows/docs-e2e.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
name: Docs E2E Tests

# "Docs E2E" is a required status check on master, so this workflow must
# produce a check run on every PR — a `paths` trigger filter would leave
# non-docs PRs waiting on a check that never reports. Path scoping happens
# in the "Detect changed paths" step instead; when nothing docs-related
# changed, the remaining steps are skipped and the check reports green.
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
branches: ['master']
paths:
- 'apps/docs/content/guides/**/*.mdx'
- 'apps/docs/content/troubleshooting/**/*.mdx'
- 'apps/docs/content/_partials/**'
- 'e2e/docs/features/**'
- 'e2e/docs/utils/**'
- 'e2e/docs/scripts/**'
- 'e2e/docs/playwright.config.ts'
- 'e2e/docs/package.json'
- 'e2e/docs/tsconfig.json'
- 'pnpm-lock.yaml'
- '.github/workflows/docs-e2e.yml'
workflow_dispatch:
inputs:
base_url:
Expand Down Expand Up @@ -49,7 +42,32 @@ jobs:
runs-on: blacksmith-4vcpu-ubuntu-2404

steps:
# Runs before checkout — reads the PR file list from the API. `docs`
# mirrors the path scope this workflow used to have as a trigger filter;
# `docs_app` decides whether a Vercel docs preview exists to test against.
- name: Detect changed paths
id: changes
if: github.event_name == 'pull_request'
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with:
filters: |
docs:
- 'apps/docs/content/guides/**/*.mdx'
- 'apps/docs/content/troubleshooting/**/*.mdx'
- 'apps/docs/content/_partials/**'
- 'e2e/docs/features/**'
- 'e2e/docs/utils/**'
- 'e2e/docs/scripts/**'
- 'e2e/docs/playwright.config.ts'
- 'e2e/docs/package.json'
- 'e2e/docs/tsconfig.json'
- 'pnpm-lock.yaml'
- '.github/workflows/docs-e2e.yml'
docs_app:
- 'apps/docs/**'

- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
if: github.event_name == 'workflow_dispatch' || steps.changes.outputs.docs == 'true'
with:
persist-credentials: false
# Need full history on PRs so we can diff against the base branch.
Expand All @@ -65,6 +83,7 @@ jobs:
apps/docs/scripts/federated-content/sources

- name: Use Node.js
if: github.event_name == 'workflow_dispatch' || steps.changes.outputs.docs == 'true'
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
Expand All @@ -73,6 +92,7 @@ jobs:
# URLs. Harness-only PRs resolve to skip=true and exit before Playwright.
- name: Resolve docs E2E scope
id: scope
if: github.event_name == 'workflow_dispatch' || steps.changes.outputs.docs == 'true'
env:
EVENT_NAME: ${{ github.event_name }}
BASE_REF: ${{ github.base_ref }}
Expand All @@ -98,37 +118,29 @@ jobs:
run: echo "No in-scope docs pages changed; skipping Playwright suite."

- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
if: steps.scope.outputs.skip != 'true'
if: steps.scope.outputs.skip == 'false'
name: Install pnpm
with:
run_install: false

- name: Enable pnpm store cache
if: steps.scope.outputs.skip != 'true'
if: steps.scope.outputs.skip == 'false'
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'

# Vercel skips the docs preview when a PR only changes the harness
# (e2e/docs, workflow). Wait for a preview only when apps/docs changed.
- name: Detect docs app changes
if: steps.scope.outputs.skip != 'true' && github.event_name == 'pull_request'
id: filter
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with:
filters: |
docs_app:
- 'apps/docs/**'

# (e2e/docs, workflow), so wait for a preview only when apps/docs changed.
#
# Vercel's GitHub App stopped writing GitHub Deployment objects on
# 2026-02-17 (broken app auth), so vercel/wait-for-deployment-action
# times out polling that API even though the preview builds fine.
# Poll the "Vercel – docs" commit status instead — Vercel keeps posting
# those — then resolve the deployment it points to via Vercel's own API
# to get the actual preview URL. See scripts/waitForVercelDocsPreview.js.
- name: Wait for Vercel docs preview
if: steps.scope.outputs.skip != 'true' && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && steps.filter.outputs.docs_app == 'true'
if: steps.scope.outputs.skip == 'false' && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && steps.changes.outputs.docs_app == 'true'
id: deployment
run: node scripts/waitForVercelDocsPreview.js
env:
Expand All @@ -138,13 +150,13 @@ jobs:
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}

- name: Resolve base URL
if: steps.scope.outputs.skip != 'true'
if: steps.scope.outputs.skip == 'false'
id: base-url
env:
EVENT_NAME: ${{ github.event_name }}
BASE_URL_INPUT: ${{ inputs.base_url }}
DEPLOYMENT_URL: ${{ steps.deployment.outputs.deployment-url }}
DOCS_APP_CHANGED: ${{ steps.filter.outputs.docs_app }}
DOCS_APP_CHANGED: ${{ steps.changes.outputs.docs_app }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
printf 'url=%s\n' "$BASE_URL_INPUT" >> "$GITHUB_OUTPUT"
Expand All @@ -159,15 +171,15 @@ jobs:
fi

- name: Install dependencies
if: steps.scope.outputs.skip != 'true'
if: steps.scope.outputs.skip == 'false'
run: pnpm install --frozen-lockfile --filter=e2e-docs...

- name: Install Playwright Chromium
if: steps.scope.outputs.skip != 'true'
if: steps.scope.outputs.skip == 'false'
run: pnpm -C e2e/docs exec playwright install chromium --with-deps --only-shell

- name: Run docs E2E
if: steps.scope.outputs.skip != 'true'
if: steps.scope.outputs.skip == 'false'
working-directory: e2e/docs
run: pnpm run e2e:docs
env:
Expand All @@ -176,7 +188,7 @@ jobs:
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ steps.base-url.outputs.use_bypass == 'true' && secrets.VERCEL_AUTOMATION_BYPASS_DOCS || '' }}

- name: Upload Playwright report
if: failure() && steps.scope.outputs.skip != 'true'
if: failure() && steps.scope.outputs.skip == 'false'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: docs-playwright-report
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ import { Input } from 'ui-patterns/DataInputs/Input'
import { EmptyStatePresentational } from 'ui-patterns/EmptyStatePresentational'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'

import { REPLICA_STATUS } from '../../Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants'
import { DestinationPanel } from './DestinationPanel/DestinationPanel'
import { DestinationType } from './DestinationPanel/DestinationPanel.types'
import { DestinationRow } from './DestinationRow'
import { DisablePipelinesDialog } from './DisablePipelinesDialog'
import { EnablePipelinesModal } from './EnablePipelinesCallout'
import { ReadReplicaRow } from './ReadReplicas/ReadReplicaRow'
import { REPLICA_STATUS } from './Replication.constants'
import {
useIsETLBigQueryPrivateAlpha,
useIsETLClickHousePrivateAlpha,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useQueryClient } from '@tanstack/react-query'
import { useParams } from 'common'
import { toast } from 'sonner'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { ConfirmationModal } from 'ui-patterns/Dialogs/ConfirmationModal'

import { REPLICA_STATUS } from './InstanceConfiguration.constants'
import { REPLICA_STATUS } from '../Replication.constants'
import { InlineLink } from '@/components/ui/InlineLink'
import { replicaKeys } from '@/data/read-replicas/keys'
import { useReadReplicaRemoveMutation } from '@/data/read-replicas/replica-remove-mutation'
import type { Database } from '@/data/read-replicas/replicas-query'
Expand All @@ -23,6 +24,26 @@ export const DropReplicaConfirmationModal = ({
const { ref: projectRef } = useParams()
const queryClient = useQueryClient()
const formattedId = formatDatabaseID(selectedReplica?.identifier ?? '')

const getRemoveReplicaErrorMessage = (message: string) => {
const isPrivateLinkAssociationError =
/private\s*link/i.test(message) && /association/i.test(message)

if (isPrivateLinkAssociationError) {
return (
<span>
Remove the replica{' '}
<InlineLink href={`/project/${projectRef}/settings/integrations`}>
PrivateLink association
</InlineLink>{' '}
before dropping this read replica
</span>
)
}

return `Failed to remove read replica: ${message}`
}

const { mutate: removeReadReplica, isPending: isRemoving } = useReadReplicaRemoveMutation({
onSuccess: () => {
toast.success(`Tearing down read replica (ID: ${formattedId})`)
Expand All @@ -44,6 +65,9 @@ export const DropReplicaConfirmationModal = ({
onSuccess()
onCancel()
},
onError: (error) => {
toast.error(getRemoveReplicaErrorMessage(error.message))
},
})

const onConfirmRemove = async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import { Input } from 'ui-patterns/DataInputs/Input'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'

import { REPLICA_STATUS } from '../Replication.constants'
import { REPORT_DATERANGE_HELPER_LABELS } from '@/components/interfaces/Reports/Reports.constants'
import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants'
import { ScaffoldContainer, ScaffoldSection } from '@/components/layouts/Scaffold'
import { useInfraMonitoringAttributesQuery } from '@/data/analytics/infra-monitoring-query'
import { useLoadBalancersQuery } from '@/data/read-replicas/load-balancers-query'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import {
} from 'ui'
import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'

import { REPLICA_STATUS } from '../Replication.constants'
import { DropReplicaConfirmationModal } from './DropReplicaConfirmationModal'
import { getIsInTransition, getStatusLabel } from './ReadReplicas.utils'
import { DropReplicaConfirmationModal } from '@/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DropReplicaConfirmationModal'
import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants'
import { RestartReplicaConfirmationModal } from '@/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/RestartReplicaConfirmationModal'
import { RestartReplicaConfirmationModal } from './RestartReplicaConfirmationModal'
import { useReplicationLagQuery } from '@/data/read-replicas/replica-lag-query'
import { type Database } from '@/data/read-replicas/replicas-query'
import { formatDatabaseID } from '@/data/read-replicas/replicas.utils'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants'
import { REPLICA_STATUS } from '../Replication.constants'
import { ReplicaInitializationStatus } from '@/data/read-replicas/replicas-status-query'

export const getIsInTransition = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useParams } from 'common'
import { toast } from 'sonner'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'

import { REPLICA_STATUS } from './InstanceConfiguration.constants'
import { REPLICA_STATUS } from '../Replication.constants'
import { useProjectRestartMutation } from '@/data/projects/project-restart-mutation'
import { replicaKeys } from '@/data/read-replicas/keys'
import { Database } from '@/data/read-replicas/replicas-query'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { components } from 'api-types'

import { PROJECT_STATUS } from '@/lib/constants'

export const STATUS_REFRESH_FREQUENCY_MS: number = 10000 // 10 seconds

export enum PipelineStatusName {
Expand All @@ -8,3 +12,11 @@ export enum PipelineStatusName {
STOPPING = 'stopping',
UNKNOWN = 'unknown',
}

export const REPLICA_STATUS: {
[key: string]: components['schemas']['DatabaseStatusResponse']['status']
} = {
...PROJECT_STATUS,
INIT_READ_REPLICA: 'INIT_READ_REPLICA',
INIT_READ_REPLICA_FAILED: 'INIT_READ_REPLICA_FAILED',
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { useMemo } from 'react'
import { cn } from 'ui'

import { getStatusName } from '../Pipeline.utils'
import { STATUS_REFRESH_FREQUENCY_MS } from '../Replication.constants'
import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants'
import { REPLICA_STATUS, STATUS_REFRESH_FREQUENCY_MS } from '../Replication.constants'
import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
import { useReplicationPipelineStatusQuery } from '@/data/replication/pipeline-status-query'
import { useReplicationPipelinesQuery } from '@/data/replication/pipelines-query'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const TopSection = () => {
)}
>
<ReactFlowProvider>
<InstanceConfiguration diagramOnly />
<InstanceConfiguration />
</ReactFlowProvider>
</div>
</div>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { useParams } from 'common'
import { Loader2 } from 'lucide-react'
import { Tooltip, TooltipContent, TooltipTrigger } from 'ui'

import { EdgeData, REPLICA_STATUS } from './InstanceConfiguration.constants'
import { EdgeData } from './InstanceConfiguration.constants'
import { REPLICA_STATUS } from '@/components/interfaces/Database/Replication/Replication.constants'
import { useReplicationLagQuery } from '@/data/read-replicas/replica-lag-query'
import { formatDatabaseID } from '@/data/read-replicas/replicas.utils'

Expand Down
Loading
Loading