Skip to content

Commit

Permalink
chore (examples): Add authentication to the examples (#2248)
Browse files Browse the repository at this point in the history
Updated GH Actions all SST scripts to use the necessary tokens to reach the admin-api

---------

Co-authored-by: Valter Balegas <[email protected]>
  • Loading branch information
kevin-dp and balegas authored Jan 29, 2025
1 parent 11e34ea commit 2cd85ec
Show file tree
Hide file tree
Showing 25 changed files with 455 additions and 223 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/deploy_all_examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ jobs:
working-directory: ./examples/linearlite-read-only
run: pnpm sst deploy --stage production

- name: Deploy Linearlite
working-directory: ./examples/linearlite
run: pnpm sst deploy --stage production
# - name: Deploy Linearlite
# working-directory: ./examples/linearlite
# run: pnpm sst deploy --stage production

- name: Deploy NextJs example
working-directory: ./examples/nextjs
run: pnpm sst deploy --stage production

- name: Deploy Yjs example
working-directory: ./examples/yjs
run: pnpm sst deploy --stage production
59 changes: 59 additions & 0 deletions .github/workflows/deploy_examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ jobs:
ELECTRIC_API: ${{ secrets.ELECTRIC_API }}
ELECTRIC_ADMIN_API: ${{ secrets.ELECTRIC_ADMIN_API }}
ELECTRIC_TEAM_ID: ${{ secrets.ELECTRIC_TEAM_ID }}
ELECTRIC_ADMIN_API_TOKEN_ID: ${{ secrets.ELECTRIC_ADMIN_API_TOKEN_ID }}
ELECTRIC_ADMIN_API_TOKEN_SECRET: ${{ secrets.ELECTRIC_ADMIN_API_TOKEN_SECRET }}
# HONEYCOMB_API_KEY: ${{ secrets.HONEYCOMB_API_KEY }} TODO

steps:
Expand All @@ -47,6 +49,18 @@ jobs:
restore-keys: |
sst-cache-main-${{ runner.os }}
- name: Deploy Yjs example
working-directory: ./examples/yjs
run: |
pnpm sst deploy --stage ${{ env.DEPLOY_ENV }}
if [ -f ".sst/outputs.json" ]; then
yjs=$(jq -r '.website' .sst/outputs.json)
echo "yjs=$yjs" >> $GITHUB_ENV
else
echo "sst outputs file not found. Exiting."
exit 123
fi
- name: Deploy Linearlite Read Only
working-directory: ./examples/linearlite-read-only
run: |
Expand All @@ -59,6 +73,19 @@ jobs:
exit 123
fi
- name: Deploy Write Patterns example
working-directory: ./examples/write-patterns
run: |
pnpm --filter @electric-sql/client --filter @electric-sql/experimental --filter @electric-sql/react run build
pnpm sst deploy --stage ${{ env.DEPLOY_ENV }}
if [ -f ".sst/outputs.json" ]; then
writes=$(jq -r '.website' .sst/outputs.json)
echo "writes=$writes" >> $GITHUB_ENV
else
echo "sst outputs file not found. Exiting."
exit 123
fi
- name: Deploy NextJs example
working-directory: ./examples/nextjs
run: |
Expand All @@ -71,6 +98,30 @@ jobs:
exit 123
fi
- name: Deploy TODO App example
working-directory: ./examples/todo-app
run: |
pnpm sst deploy --stage ${{ env.DEPLOY_ENV }}
if [ -f ".sst/outputs.json" ]; then
todoapp=$(jq -r '.website' .sst/outputs.json)
echo "todoapp=$todoapp" >> $GITHUB_ENV
else
echo "sst outputs file not found. Exiting."
exit 123
fi
- name: Deploy proxy-auth example
working-directory: ./examples/proxy-auth
run: |
pnpm sst deploy --stage ${{ env.DEPLOY_ENV }}
if [ -f ".sst/outputs.json" ]; then
auth=$(jq -r '.website' .sst/outputs.json)
echo "auth=$auth" >> $GITHUB_ENV
else
echo "sst outputs file not found. Exiting."
exit 123
fi
- name: Add comment to PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
Expand All @@ -79,11 +130,19 @@ jobs:
script: |
const linearlite_read_only = process.env.linearlite_read_only;
const nextjs = process.env.nextjs;
const todoapp = process.env.todoapp;
const yjs = process.env.yjs;
const writes = process.env.writes;
const auth = process.env.auth;
const prNumber = context.issue.number;
const commentBody = `## Examples
- linearlite-read-only: ${linearlite_read_only}
- nextjs: ${nextjs}
- todoapp: ${todoapp}
- yjs: ${yjs}
- writes: ${writes}
- auth: ${auth}
`;
const { data: comments } = await github.rest.issues.listComments({
Expand Down
4 changes: 2 additions & 2 deletions examples/linearlite-read-only/src/electric.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const baseUrl = import.meta.env.VITE_ELECTRIC_URL
? new URL(import.meta.env.VITE_ELECTRIC_URL).origin
: `http://localhost:3000`
export const token = import.meta.env.VITE_ELECTRIC_TOKEN ?? ``
export const databaseId = import.meta.env.VITE_DATABASE_ID ?? ``
export const source_secret = import.meta.env.VITE_ELECTRIC_SOURCE_SECRET ?? ``
export const source_id = import.meta.env.VITE_ELECTRIC_SOURCE_ID ?? ``
6 changes: 3 additions & 3 deletions examples/linearlite-read-only/src/pages/Issue/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { formatDate } from '../../utils/date'
import { showWarning } from '../../utils/notification'
import { Comment, Issue } from '../../types/types'
import { useShape } from '@electric-sql/react'
import { baseUrl, databaseId, token } from '../../electric'
import { baseUrl, source_id, source_secret } from '../../electric'

export interface CommentsProps {
issue: Issue
Expand All @@ -19,8 +19,8 @@ function Comments(commentProps: CommentsProps) {
const allComments = useShape({
url: `${baseUrl}/v1/shape`,
params: {
token,
source_id: databaseId,
source_secret,
source_id,
table: `comment`,
},
})! as Comment[]
Expand Down
6 changes: 3 additions & 3 deletions examples/linearlite-read-only/src/shapes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ShapeStreamOptions } from '@electric-sql/client'
import { baseUrl, databaseId, token } from './electric'
import { baseUrl, source_id, source_secret } from './electric'

export const issueShape: ShapeStreamOptions = {
url: `${baseUrl}/v1/shape/`,
params: {
table: `issue`,
token,
source_id: databaseId,
source_secret,
source_id,
},
}
4 changes: 2 additions & 2 deletions examples/linearlite-read-only/src/sst-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_ELECTRIC_URL: string
readonly VITE_ELECTRIC_TOKEN: string
readonly VITE_DATABASE_ID: string
readonly VITE_ELECTRIC_SOURCE_SECRET: string
readonly VITE_ELECTRIC_SOURCE_ID: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
Expand Down
31 changes: 23 additions & 8 deletions examples/linearlite-read-only/sst.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

import { execSync } from 'child_process'

const adminApiTokenId = process.env.ELECTRIC_ADMIN_API_TOKEN_ID
const adminApiTokenSecret = process.env.ELECTRIC_ADMIN_API_TOKEN_SECRET

export default $config({
app(input) {
return {
Expand All @@ -12,7 +15,7 @@ export default $config({
providers: {
cloudflare: `5.42.0`,
aws: {
version: `6.57.0`,
version: `6.66.2`,
profile: process.env.CI ? undefined : `marketing`,
},
neon: `0.6.3`,
Expand All @@ -21,6 +24,14 @@ export default $config({
}
},
async run() {
if (!$dev && !process.env.ELECTRIC_ADMIN_API_TOKEN_ID) {
throw new Error(`ELECTRIC_ADMIN_API_TOKEN_ID is not set`)
}

if (!$dev && !process.env.ELECTRIC_ADMIN_API_TOKEN_SECRET) {
throw new Error(`ELECTRIC_ADMIN_API_TOKEN_ID is not set`)
}

const project = neon.getProjectOutput({ id: process.env.NEON_PROJECT_ID! })

const dbName = `linearlite-read-only-${$app.stage}`
Expand Down Expand Up @@ -53,8 +64,8 @@ export default $config({
const website = deployLinearLite(electricInfo)
return {
databaseUri,
database_id: electricInfo.id,
electric_token: electricInfo.token,
// source_id: electricInfo.id,
// source_secret: electricInfo.source_secret,
website: website.url,
}
} catch (e) {
Expand Down Expand Up @@ -82,13 +93,13 @@ function loadData(uri: string) {
}

function deployLinearLite(
electricInfo: $util.Output<{ id: string; token: string }>
electricInfo: $util.Output<{ id: string; source_secret: string }>
) {
return new sst.aws.StaticSite(`linearlite-read-only`, {
environment: {
VITE_ELECTRIC_URL: process.env.ELECTRIC_API!,
VITE_ELECTRIC_TOKEN: electricInfo.token,
VITE_DATABASE_ID: electricInfo.id,
VITE_ELECTRIC_SOURCE_SECRET: electricInfo.source_secret,
VITE_ELECTRIC_SOURCE_ID: electricInfo.id,
},
build: {
command: `pnpm run --filter @electric-sql/client --filter @electric-sql/react --filter @electric-examples/linearlite-read-only build`,
Expand All @@ -103,13 +114,17 @@ function deployLinearLite(

async function addDatabaseToElectric(
uri: string
): Promise<{ id: string; token: string }> {
): Promise<{ id: string; source_secret: string }> {
const adminApi = process.env.ELECTRIC_ADMIN_API
const teamId = process.env.ELECTRIC_TEAM_ID

const result = await fetch(`${adminApi}/v1/sources`, {
method: `PUT`,
headers: { 'Content-Type': `application/json` },
headers: {
'Content-Type': `application/json`,
'CF-Access-Client-Id': adminApiTokenId ?? ``,
'CF-Access-Client-Secret': adminApiTokenSecret ?? ``,
},
body: JSON.stringify({
database_url: uri,
region: `us-east-1`,
Expand Down
16 changes: 8 additions & 8 deletions examples/linearlite/src/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const WRITE_SERVER_URL = import.meta.env.VITE_WRITE_SERVER_URL
const ELECTRIC_URL = import.meta.env.VITE_ELECTRIC_URL
? new URL(import.meta.env.VITE_ELECTRIC_URL).origin
: `http://localhost:3000`
const ELECTRIC_DATABASE_ID = import.meta.env.VITE_ELECTRIC_DATABASE_ID
const ELECTRIC_TOKEN = import.meta.env.VITE_ELECTRIC_TOKEN
const ELECTRIC_SOURCE_ID = import.meta.env.VITE_ELECTRIC_SOURCE_ID
const ELECTRIC_SOURCE_SECRET = import.meta.env.VITE_ELECTRIC_SOURCE_SECRET
const APPLY_CHANGES_URL = `${WRITE_SERVER_URL}/apply-changes`

type SyncStatus = 'initial-sync' | 'done'
Expand Down Expand Up @@ -57,8 +57,8 @@ async function startSyncToDatabase(pg: PGliteWithExtensions) {
}

const issueUrl = new URL(`${ELECTRIC_URL}/v1/shape`)
if (ELECTRIC_TOKEN) {
issueUrl.searchParams.set('token', ELECTRIC_TOKEN)
if (ELECTRIC_SOURCE_SECRET) {
issueUrl.searchParams.set('source_secret', ELECTRIC_SOURCE_SECRET)
}

// Issues Sync
Expand All @@ -67,7 +67,7 @@ async function startSyncToDatabase(pg: PGliteWithExtensions) {
url: issueUrl.toString(),
params: {
table: 'issue',
source_id: ELECTRIC_DATABASE_ID,
source_id: ELECTRIC_SOURCE_ID,
},
},
table: 'issue',
Expand All @@ -93,8 +93,8 @@ async function startSyncToDatabase(pg: PGliteWithExtensions) {
)

const commentUrl = new URL(`${ELECTRIC_URL}/v1/shape`)
if (ELECTRIC_TOKEN) {
commentUrl.searchParams.set('token', ELECTRIC_TOKEN)
if (ELECTRIC_SOURCE_SECRET) {
commentUrl.searchParams.set('source_secret', ELECTRIC_SOURCE_SECRET)
}

// Comments Sync
Expand All @@ -103,7 +103,7 @@ async function startSyncToDatabase(pg: PGliteWithExtensions) {
url: commentUrl.toString(),
params: {
table: 'comment',
source_id: ELECTRIC_DATABASE_ID,
source_id: ELECTRIC_SOURCE_ID,
},
},
table: 'comment',
Expand Down
29 changes: 22 additions & 7 deletions examples/linearlite/sst.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { execSync } from 'child_process'
const isProduction = (stage: string) =>
stage.toLocaleLowerCase() === `production`

const adminApiTokenId = process.env.ELECTRIC_ADMIN_API_TOKEN_ID
const adminApiTokenSecret = process.env.ELECTRIC_ADMIN_API_TOKEN_SECRET

export default $config({
app(input) {
return {
Expand All @@ -15,13 +18,21 @@ export default $config({
providers: {
cloudflare: `5.42.0`,
aws: {
version: `6.57.0`,
version: `6.66.2`,
profile: process.env.CI ? undefined : `marketing`,
},
},
}
},
async run() {
if (!$dev && !process.env.ELECTRIC_ADMIN_API_TOKEN_ID) {
throw new Error(`ELECTRIC_ADMIN_API_TOKEN_ID is not set`)
}

if (!$dev && !process.env.ELECTRIC_ADMIN_API_TOKEN_SECRET) {
throw new Error(`ELECTRIC_ADMIN_API_TOKEN_ID is not set`)
}

try {
const databaseUri = $interpolate`postgresql://postgres:${process.env.LINEARLITE_SUPABASE_PROJECT_PASSWORD}@db.${process.env.LINEARLITE_SUPABASE_PROJECT_ID}.supabase.co:5432/postgres`

Expand All @@ -42,8 +53,8 @@ export default $config({
},
environment: {
VITE_ELECTRIC_URL: process.env.ELECTRIC_API,
VITE_ELECTRIC_TOKEN: electricInfo.token,
VITE_ELECTRIC_DATABASE_ID: electricInfo.id,
VITE_ELECTRIC_SOURCE_SECRET: electricInfo.source_secret,
VITE_ELECTRIC_SOURCE_ID: electricInfo.id,
},
domain: {
name: `linearlite${isProduction($app.stage) ? `` : `-stage-${$app.stage}`}.examples.electric-sql.com`,
Expand All @@ -56,8 +67,8 @@ export default $config({

return {
databaseUri,
database_id: electricInfo.id,
electric_token: electricInfo.token,
// source_id: electricInfo.id,
// source_secret: electricInfo.source_secret,
website: website.url,
}
} catch (e) {
Expand All @@ -77,13 +88,17 @@ function applyMigrations(uri: string) {

async function addDatabaseToElectric(
uri: string
): Promise<{ id: string; token: string }> {
): Promise<{ id: string; source_secret: string }> {
const adminApi = process.env.ELECTRIC_ADMIN_API
const teamId = process.env.ELECTRIC_TEAM_ID

const result = await fetch(`${adminApi}/v1/sources`, {
method: `PUT`,
headers: { 'Content-Type': `application/json` },
headers: {
'Content-Type': 'application/json',
'CF-Access-Client-Id': adminApiTokenId ?? ``,
'CF-Access-Client-Secret': adminApiTokenSecret ?? ``,
},
body: JSON.stringify({
database_url: uri,
region: `us-east-1`,
Expand Down
11 changes: 7 additions & 4 deletions examples/nextjs/app/shape-proxy/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ export async function GET(request: Request) {
originUrl.searchParams.set(key, value)
})

if (process.env.DATABASE_ID) {
originUrl.searchParams.set(`source_id`, process.env.DATABASE_ID)
if (process.env.ELECTRIC_SOURCE_ID) {
originUrl.searchParams.set(`source_id`, process.env.ELECTRIC_SOURCE_ID)
}

const headers = new Headers()
if (process.env.ELECTRIC_TOKEN) {
originUrl.searchParams.set(`token`, process.env.ELECTRIC_TOKEN)
if (process.env.ELECTRIC_SOURCE_SECRET) {
originUrl.searchParams.set(
`source_secret`,
process.env.ELECTRIC_SOURCE_SECRET
)
}

const newRequest = new Request(originUrl.toString(), {
Expand Down
Loading

0 comments on commit 2cd85ec

Please sign in to comment.