snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-23 16:12:52 +05:00
commit a774ac673a
4541 changed files with 770499 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'
import { Client } from 'pg'
import { makeEnv } from '../lib/makeEnv'
const env = makeEnv([
'CLOUDFLARE_ACCOUNT_ID',
'R2_ACCESS_KEY_ID',
'R2_ACCESS_KEY_SECRET',
'SUPABASE_STAGING_DB_URL',
'STAGING_OWNER_ID',
])
const R2_URL = `https://${env.CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`
const R2_STAGING_BUCKET = 'rooms-preview'
const R2 = new S3Client({
region: 'auto',
endpoint: R2_URL,
credentials: {
accessKeyId: env.R2_ACCESS_KEY_ID,
secretAccessKey: env.R2_ACCESS_KEY_SECRET,
},
})
async function cleanupTestFiles() {
const stagingClient = new Client({
connectionString: env.SUPABASE_STAGING_DB_URL,
})
await stagingClient.connect()
try {
const selectQuery = `SELECT id FROM file WHERE file."owningGroupId" = $1 AND id LIKE 'test_%'`
const selectResult = await stagingClient.query(selectQuery, [env.STAGING_OWNER_ID])
const fileIds = selectResult.rows.map((row: any) => row.id)
for (const fileId of fileIds) {
try {
const deleteParams = {
Bucket: R2_STAGING_BUCKET,
Key: `app_rooms/${fileId}`,
}
const deleteResponse = await R2.send(new DeleteObjectCommand(deleteParams))
if (
!deleteResponse.$metadata.httpStatusCode ||
(deleteResponse.$metadata.httpStatusCode !== 200 &&
deleteResponse.$metadata.httpStatusCode !== 204)
) {
console.error('Failed to delete file from R2 staging bucket')
continue
}
const deleteFileQuery = `DELETE FROM file WHERE id = $1`
const deleteResult = await stagingClient.query(deleteFileQuery, [fileId])
if (deleteResult.rowCount === 0) {
console.error('Failed to delete file from Supabase database - no rows affected')
continue
}
} catch (error) {
console.error('Failed to delete file', error)
}
}
console.log(`Successfully cleaned up ${fileIds.length} test files`)
} finally {
await stagingClient.end()
}
}
cleanupTestFiles().catch(console.error)

View File

@@ -0,0 +1,182 @@
import { writeFileSync } from 'fs'
import { join } from 'path'
import { GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3'
import type { TlaFile } from '@tldraw/dotcom-shared'
import { nanoid } from 'nanoid'
import { Client } from 'pg'
import { makeEnv } from '../lib/makeEnv'
const env = makeEnv([
'CLOUDFLARE_ACCOUNT_ID',
'R2_ACCESS_KEY_ID',
'R2_ACCESS_KEY_SECRET',
'SUPABASE_PRODUCTION_DB_URL',
'SUPABASE_STAGING_DB_URL',
'STAGING_OWNER_ID',
])
const R2_URL = `https://${env.CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`
const R2_PRODUCTION_BUCKET = 'rooms'
const R2_STAGING_BUCKET = 'rooms-preview'
const R2 = new S3Client({
region: 'auto',
endpoint: R2_URL,
credentials: {
accessKeyId: env.R2_ACCESS_KEY_ID,
secretAccessKey: env.R2_ACCESS_KEY_SECRET,
},
})
async function getRandomFileIds(n: number): Promise<string[]> {
const client = new Client({
connectionString: env.SUPABASE_PRODUCTION_DB_URL,
})
await client.connect()
const threeDays = 3 * 24 * 60 * 60 * 1000
const query = `
SELECT * FROM file
TABLESAMPLE BERNOULLI(30)
WHERE "shared" = true
AND ("updatedAt" - "createdAt") >= $1
LIMIT $2;
`
const { rows } = await client.query(query, [threeDays, n])
await client.end()
if (!rows || rows.length === 0) {
console.log('No files found matching the criteria')
return []
}
return rows.map((r) => r.id)
}
async function copyFilesToStaging(fileIds: string[]) {
const copiedIds: string[] = []
// Create one staging client for all database operations
const stagingClient = new Client({
connectionString: env.SUPABASE_STAGING_DB_URL,
})
await stagingClient.connect()
try {
for (const fileId of fileIds) {
try {
const getParams = {
Bucket: R2_PRODUCTION_BUCKET,
Key: `app_rooms/${fileId}`,
}
const getResponse = await R2.send(new GetObjectCommand(getParams))
if (!getResponse.Body) {
console.error('Failed to download file - no body')
continue
}
const fileContent = await getResponse.Body.transformToByteArray()
const newId = `test_${nanoid()}`
const putParams = {
Bucket: R2_STAGING_BUCKET,
Key: `app_rooms/${newId}`,
Body: Buffer.from(fileContent),
ContentType: 'application/octet-stream',
}
const putResponse = await R2.send(new PutObjectCommand(putParams))
if (!putResponse.$metadata.httpStatusCode || putResponse.$metadata.httpStatusCode !== 200) {
console.error('Failed to upload file to staging bucket')
continue
}
const now = Date.now()
const testFile: TlaFile = {
id: newId,
name: 'Test File',
ownerName: 'Test User',
thumbnail: '',
shared: false,
sharedLinkType: 'link',
published: false,
lastPublished: 0,
publishedSlug: nanoid(),
createdAt: now,
updatedAt: now,
isEmpty: false,
isDeleted: false,
createSource: null,
// the staging user's home workspace: home group id is the user's own id. Must be set —
// file_owner_xor_check rejects a row with neither owner, and cleanup-test-files finds
// these rows by owningGroupId.
owningGroupId: env.STAGING_OWNER_ID,
}
const insertQuery = `
INSERT INTO file (id, name, "ownerName", thumbnail, shared, "sharedLinkType", published, "lastPublished", "publishedSlug", "createdAt", "updatedAt", "isEmpty", "isDeleted", "owningGroupId")
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
`
await stagingClient.query(insertQuery, [
testFile.id,
testFile.name,
testFile.ownerName,
testFile.thumbnail,
testFile.shared,
testFile.sharedLinkType,
testFile.published,
testFile.lastPublished,
testFile.publishedSlug,
testFile.createdAt,
testFile.updatedAt,
testFile.isEmpty,
testFile.isDeleted,
testFile.owningGroupId,
])
await stagingClient.query(
`INSERT INTO group_file ("fileId", "groupId", "createdAt", "updatedAt", "index")
VALUES ($1, $2, $3, $4, NULL)`,
[testFile.id, testFile.owningGroupId, now, now]
)
copiedIds.push(newId)
} catch (error) {
console.error('Error copying file:', error)
}
}
} finally {
await stagingClient.end()
}
console.log(`Successfully copied ${copiedIds.length} files to staging`)
if (copiedIds.length > 0) {
const testFilesPath = join(
__dirname,
'../../../apps/dotcom/client/e2e/fixtures/test-files.json'
)
writeFileSync(testFilesPath, JSON.stringify(copiedIds, null, 2))
console.log('Updated test files')
}
}
async function main() {
const n = parseInt(process.env.STAGING_TEST_FILES_COUNT || '10')
console.log(`Getting ${n} random file IDs...`)
const fileIds = await getRandomFileIds(n)
if (fileIds.length === 0) {
console.log('No files found to copy')
return
}
console.log('\nCopying files to staging...')
await copyFilesToStaging(fileIds)
}
main().catch(console.error)