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
122 changes: 122 additions & 0 deletions .github/workflows/docs-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Docs E2E Tests

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
branches: ['master']
paths:
- 'apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx'
- 'apps/docs/content/_partials/quickstart_db_setup.mdx'
- 'apps/docs/content/_partials/api_settings.mdx'
- 'e2e/docs/**'
- 'pnpm-lock.yaml'
- '.github/workflows/docs-e2e.yml'
workflow_dispatch:
inputs:
base_url:
description: 'Base URL to test against'
required: false
default: 'https://supabase.com'
type: string

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read
deployments: read
statuses: read
pull-requests: read

env:
CI: true

jobs:
e2e:
name: Docs E2E
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.draft == false
timeout-minutes: 30
runs-on: blacksmith-4vcpu-ubuntu-2404

steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
sparse-checkout: |
e2e/docs
patches

# 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: github.event_name == 'pull_request'
id: filter
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with:
filters: |
docs_app:
- 'apps/docs/**'

- name: Wait for Vercel docs preview
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && steps.filter.outputs.docs_app == 'true'
id: deployment
uses: vercel/wait-for-deployment-action@0e2b0c5c5cce31f1648108aeec56467187aca037
with:
project-slug: docs
environment: preview
timeout: '900'

- name: Resolve base URL
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 }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
printf 'url=%s\n' "$BASE_URL_INPUT" >> "$GITHUB_OUTPUT"
echo "use_bypass=false" >> "$GITHUB_OUTPUT"
elif [ "$DOCS_APP_CHANGED" = "true" ] && [ -n "$DEPLOYMENT_URL" ]; then
printf 'url=%s\n' "$DEPLOYMENT_URL" >> "$GITHUB_OUTPUT"
echo "use_bypass=true" >> "$GITHUB_OUTPUT"
else
# Harness-only PRs have no docs preview; test against production.
echo "url=https://supabase.com" >> "$GITHUB_OUTPUT"
echo "use_bypass=false" >> "$GITHUB_OUTPUT"
fi

- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
name: Install pnpm
with:
run_install: false

- name: Use Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile --filter=e2e-docs...

- name: Install Playwright Chromium
run: pnpm -C e2e/docs exec playwright install chromium --with-deps --only-shell

- name: Run docs E2E
working-directory: e2e/docs
run: pnpm run e2e:docs
env:
PLAYWRIGHT_BASE_URL: ${{ steps.base-url.outputs.url }}
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ steps.base-url.outputs.use_bypass == 'true' && secrets.VERCEL_AUTOMATION_BYPASS_DOCS || '' }}

- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: docs-playwright-report
path: |
e2e/docs/playwright-report/
e2e/docs/test-results/
retention-days: 7
8 changes: 8 additions & 0 deletions apps/docs/content/guides/realtime/authorization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ Realtime uses the `messages` table in your database's `realtime` schema to gener

By creating RLS policies on the `realtime.messages` table you can control the access users have to a Channel topic, and features within a Channel topic.

<Admonition type="caution">

Realtime locks down the `realtime` schema to protect it against unexpected changes to guarantee the healthy operation of the Realtime service and avoid conflicts that could be caused by future migrations. Creating a table or function in `realtime` is expected to fail with `permission denied for schema realtime`, whether you run the SQL yourself or through the dashboard. Managing RLS policies on `realtime.messages` is allowed.

Row level security (RLS) is enabled by default on table `realtime.messages`, you don't need to execute `ALTER TABLE realtime.messages ENABLE ROW LEVEL SECURITY`.

</Admonition>

The validation is done when the user connects. When their WebSocket connection is established and a Channel topic is joined, their permissions are calculated based on:

- The RLS policies on the `realtime.messages` table
Expand Down
3 changes: 2 additions & 1 deletion apps/docs/content/guides/realtime/concepts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ Realtime has a cleanup process that will delete tables older than 3 days.

### Functions

Realtime creates two functions on your database:
Realtime creates some functions on your database:

- `realtime.send` - Inserts an entry into `realtime.messages` table that will trigger the replication slot to broadcast the changes to the clients. It also captures errors to prevent the trigger from breaking.
- `realtime.send_binary` - Similar to `realtime.send` but allows you to broadcast binaries.
- `realtime.broadcast_changes` - uses `realtime.send` to broadcast the changes with a format that is compatible with Postgres Changes
8 changes: 1 addition & 7 deletions apps/docs/internals/markdown-schema/AiSkillsIndex.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { existsSync, readFileSync } from 'node:fs'
import { readFileSync } from 'node:fs'
import path from 'node:path'

const SKILLS_PATH = path.join(process.cwd(), 'features/docs/generated/ai-skills.json')
Expand All @@ -10,12 +10,6 @@ interface SkillSummary {
}

export const AiSkillsIndex = (): string => {
// `build:guides-markdown` can run standalone (e.g. apps/www's prebuild) without
// `build:federated-content`, so this generated artifact may not exist yet.
if (!existsSync(SKILLS_PATH)) {
return ''
}

const skills: SkillSummary[] = JSON.parse(readFileSync(SKILLS_PATH, 'utf-8'))

return skills
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { existsSync, readFileSync } from 'node:fs'
import { readFileSync } from 'node:fs'
import path from 'node:path'

const SCHEMA_PATH = path.join(process.cwd(), 'features/docs/generated/terraform.schema.json')
Expand All @@ -15,12 +15,6 @@ function attributesTable(attributes: Record<string, any>, extraColumns: string[]
}

export const TerraformProviderSchema = (): string => {
// `build:guides-markdown` can run standalone (e.g. apps/www's prebuild) without
// `build:federated-content`, so this generated artifact may not exist yet.
if (!existsSync(SCHEMA_PATH)) {
return ''
}

const schema = JSON.parse(readFileSync(SCHEMA_PATH, 'utf-8'))
const provider = schema.provider_schemas['registry.terraform.io/supabase/supabase']

Expand Down
2 changes: 2 additions & 0 deletions apps/docs/public/humans.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Ana Mogul
Andrew Valleteau
Andrey A
Angelico de los Reyes
Anna Baker
Ant Evans
Ant Wilson
Ariuna K
Expand Down Expand Up @@ -267,6 +268,7 @@ Sergio Cioban Filho
Shaii O
Shane Adams
Shane E
Shaun Newman
Shreekar Shetty
Sreyas Udayavarman
Stephanie Jackson (stejacks)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ export const ProjectCreationForm = ({
loading={!isOrganizationsSuccess}
noMargin={isVercelIntegrationFlow}
className={cn(
!isVercelIntegrationFlow && 'border-0 shadow-none rounded-none bg-transparent'
isVercelIntegrationFlow && 'border-0 shadow-none rounded-none bg-transparent'
)}
title={
!isVercelIntegrationFlow && (
Expand Down
29 changes: 29 additions & 0 deletions apps/studio/components/interfaces/SQLEditor/SQLEditor.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { DiffOnMount, OnMount } from '@monaco-editor/react'
import type { UntrustedSqlFragment } from '@supabase/pg-meta'
import { Dispatch, SetStateAction } from 'react'

export interface SQLTemplate {
Expand All @@ -17,6 +18,34 @@ export type ContentDiff = {
modified: string
}

/**
* Semantic, Monaco-agnostic port onto the main editor. Hooks/controllers call
* this instead of touching `editorRef.current` directly, so the editor is
* swappable for a real in-memory adapter in tests without mocking.
*/
export type EditorController = {
isReady: () => boolean
getValue: () => string | undefined
getSelectionStartLine: () => number | undefined
getSql: (snippetContent?: UntrustedSqlFragment) => UntrustedSqlFragment | undefined
replaceAll: (text: string, source: string) => void
focus: () => void
revealLineInCenter: (line: number) => void
highlightErrorLine: (
error: { position?: unknown; formattedError?: string },
hasSelection: boolean
) => void
clearHighlights: () => void
}

/** Semantic, Monaco-agnostic port onto the diff editor. */
export type DiffController = {
isMounted: () => boolean
getModifiedValue: () => string | undefined
setDiff: (diff: ContentDiff, revealLine: number) => void
attach: (editor: IStandaloneDiffEditor) => void
}

export type SQLEditorContextValues = {
aiInput: string
setAiInput: Dispatch<SetStateAction<string>>
Expand Down
Loading
Loading