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
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:
72
internal/scripts/dotcom/cleanup-test-files.ts
Normal file
72
internal/scripts/dotcom/cleanup-test-files.ts
Normal 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)
|
||||
182
internal/scripts/dotcom/copy-random-files-to-staging.ts
Normal file
182
internal/scripts/dotcom/copy-random-files-to-staging.ts
Normal 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)
|
||||
Reference in New Issue
Block a user