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:
42
apps/vscode/extension/scripts/build.ts
Normal file
42
apps/vscode/extension/scripts/build.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import esbuild from 'esbuild'
|
||||
import { logEnv } from './cli'
|
||||
import { copyEditor, removeDistDirectory } from './helpers'
|
||||
|
||||
const log = logEnv('extension')
|
||||
|
||||
async function build() {
|
||||
await copyEditor({ log })
|
||||
await removeDistDirectory({ log })
|
||||
|
||||
try {
|
||||
const entryPoints = ['./src/extension.ts']
|
||||
log({ cmd: 'esbuild', args: { entryPoints } })
|
||||
await esbuild.build({
|
||||
entryPoints,
|
||||
outdir: 'dist/web',
|
||||
minify: false,
|
||||
bundle: true,
|
||||
format: 'cjs',
|
||||
target: 'es6',
|
||||
platform: 'node',
|
||||
define: {
|
||||
'process.env.NODE_ENV': '"production"',
|
||||
},
|
||||
tsconfig: './tsconfig.json',
|
||||
external: ['vscode'],
|
||||
loader: {
|
||||
'.woff2': 'dataurl',
|
||||
'.woff': 'dataurl',
|
||||
'.svg': 'file',
|
||||
'.png': 'file',
|
||||
'.json': 'file',
|
||||
},
|
||||
})
|
||||
|
||||
log({ cmd: 'esbuild:success', args: { entryPoints } })
|
||||
} catch (error) {
|
||||
log({ cmd: 'esbuild:error', args: { error } })
|
||||
throw error
|
||||
}
|
||||
}
|
||||
build()
|
||||
58
apps/vscode/extension/scripts/cli.ts
Normal file
58
apps/vscode/extension/scripts/cli.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import path from 'path'
|
||||
|
||||
const displayRelative = (from: string, to: string) => {
|
||||
const outpath = path.relative(from, to)
|
||||
if (!outpath.match(/^\./)) {
|
||||
return `./${outpath}`
|
||||
}
|
||||
return outpath
|
||||
}
|
||||
|
||||
type LogDef =
|
||||
| { cmd: 'remove'; env: string; args: { target: string } }
|
||||
| { cmd: 'copy'; env: string; args: { source: string; dest: string } }
|
||||
| { cmd: 'esbuild'; env: string; args: { entryPoints: string[] } }
|
||||
| { cmd: 'esbuild:success'; env: string; args: any }
|
||||
| { cmd: 'esbuild:error'; env: string; args: { error: string } }
|
||||
| { cmd: 'esbuild:serve'; env: string; args: { host: string; port: number | string } }
|
||||
|
||||
export function log(def: LogDef) {
|
||||
const printStderr = (icon: string, cmd: string, ...args: unknown[]) => {
|
||||
console.error(`${icon} [${def.env ?? 'unknown'}/${cmd}]`, ...args)
|
||||
}
|
||||
|
||||
if (def.cmd === 'remove') {
|
||||
const { target } = def.args
|
||||
printStderr('🗑 ', 'remove', displayRelative(process.cwd(), target))
|
||||
} else if (def.cmd === 'copy') {
|
||||
const { source, dest } = def.args
|
||||
printStderr(
|
||||
'🏠',
|
||||
'copy',
|
||||
`${displayRelative(process.cwd(), source)} -> ${displayRelative(process.cwd(), dest)}`
|
||||
)
|
||||
} else if (def.cmd === 'esbuild') {
|
||||
printStderr(
|
||||
'🤖',
|
||||
'esbuild',
|
||||
`${def.args.entryPoints.map((pathname) => displayRelative(process.cwd(), pathname))}`
|
||||
)
|
||||
} else if (def.cmd === 'esbuild:success') {
|
||||
printStderr('✅', `esbuild`, `build successful (${new Date().toISOString()})`)
|
||||
} else if (def.cmd === 'esbuild:error') {
|
||||
printStderr(`❌`, `esbuild`, `error`)
|
||||
console.error(def.args.error)
|
||||
} else if (def.cmd === 'esbuild:serve') {
|
||||
const { host = 'localhost', port } = def.args
|
||||
printStderr(`🌎`, `esbuild`, `serving <http://${host}:${port}>`)
|
||||
} else {
|
||||
// @ts-ignore
|
||||
printStderr(`❓`, def.cmd, JSON.stringify(def.args))
|
||||
}
|
||||
}
|
||||
|
||||
export function logEnv(env: string) {
|
||||
return (opts: any) => {
|
||||
log({ ...opts, env })
|
||||
}
|
||||
}
|
||||
60
apps/vscode/extension/scripts/dev.ts
Normal file
60
apps/vscode/extension/scripts/dev.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { join } from 'path'
|
||||
import esbuild from 'esbuild'
|
||||
import { logEnv } from './cli'
|
||||
import { copyEditor, removeDistDirectory } from './helpers'
|
||||
import { getDirname } from './path'
|
||||
|
||||
const rootDir = getDirname(import.meta.url, '../')
|
||||
const log = logEnv('extension')
|
||||
|
||||
async function dev() {
|
||||
await copyEditor({ log })
|
||||
await removeDistDirectory({ log })
|
||||
const entryPoints = [join(rootDir, 'src', 'extension.ts')]
|
||||
|
||||
log({ cmd: 'esbuild', args: { entryPoints } })
|
||||
try {
|
||||
const builder = await esbuild.context({
|
||||
entryPoints,
|
||||
outdir: join(rootDir, 'dist', 'web'),
|
||||
minify: false,
|
||||
bundle: true,
|
||||
format: 'cjs',
|
||||
target: 'es6',
|
||||
sourcemap: 'inline',
|
||||
platform: 'node',
|
||||
define: {
|
||||
'process.env.NODE_ENV': '"development"',
|
||||
},
|
||||
tsconfig: './tsconfig.json',
|
||||
external: ['vscode'],
|
||||
plugins: [
|
||||
{
|
||||
name: 'log-builds',
|
||||
setup(build) {
|
||||
build.onEnd((result) => {
|
||||
if (result.errors.length) {
|
||||
log({ cmd: 'esbuild:error', args: { err: result.errors } })
|
||||
} else {
|
||||
copyEditor({ log })
|
||||
log({ cmd: 'esbuild:success', args: {} })
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
],
|
||||
loader: {
|
||||
'.woff2': 'dataurl',
|
||||
'.woff': 'dataurl',
|
||||
'.svg': 'file',
|
||||
'.png': 'file',
|
||||
'.json': 'file',
|
||||
},
|
||||
})
|
||||
await builder.watch()
|
||||
} catch (error) {
|
||||
log({ cmd: 'esbuild:error', args: { error } })
|
||||
throw error
|
||||
}
|
||||
}
|
||||
dev()
|
||||
25
apps/vscode/extension/scripts/helpers.ts
Normal file
25
apps/vscode/extension/scripts/helpers.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import fs from 'fs'
|
||||
import { join } from 'path'
|
||||
import fse from 'fs-extra'
|
||||
import { exists, getDirname } from './path'
|
||||
|
||||
const vscodeDir = getDirname(import.meta.url, '../../')
|
||||
|
||||
export async function copyEditor({ log }: { log(opts: any): void }) {
|
||||
const editorRoot = join(vscodeDir, 'editor')
|
||||
const extensionRoot = join(vscodeDir, 'extension')
|
||||
|
||||
const source = join(editorRoot, 'dist')
|
||||
const dest = join(extensionRoot, 'editor')
|
||||
|
||||
log({ cmd: 'copy', args: { source, dest } })
|
||||
await fse.copy(source, dest)
|
||||
}
|
||||
|
||||
export async function removeDistDirectory({ log }: { log(opts: any): void }) {
|
||||
const target = join(vscodeDir, 'extension', 'dist')
|
||||
if (await exists(target)) {
|
||||
log({ cmd: 'remove', args: { target } })
|
||||
await fs.promises.rm(target, { recursive: true })
|
||||
}
|
||||
}
|
||||
38
apps/vscode/extension/scripts/package.ts
Normal file
38
apps/vscode/extension/scripts/package.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { exec } from 'child_process'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
|
||||
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8'))
|
||||
|
||||
const { log: jslog } = console
|
||||
|
||||
async function main() {
|
||||
if (fs.existsSync('./editor')) {
|
||||
fs.rmSync('./editor', { recursive: true })
|
||||
}
|
||||
if (fs.existsSync('./temp')) {
|
||||
fs.rmSync('./temp', { recursive: true })
|
||||
}
|
||||
|
||||
fs.mkdirSync('./temp')
|
||||
|
||||
const preRelease = process.argv.includes('--pre-release')
|
||||
try {
|
||||
exec(
|
||||
`cp -r ../editor/dist editor; vsce package${preRelease ? ' --pre-release' : ''}; mv ${pkg.name}-${pkg.version}.vsix ${'./temp'}`,
|
||||
(error, stdout, stderr) => {
|
||||
if (error) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
if (stderr && !/^(warning|\(node:)/.test(stderr)) {
|
||||
throw new Error(stderr)
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e) {
|
||||
jslog(`× ${pkg.name}: Build failed due to an error.`)
|
||||
jslog(e)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
16
apps/vscode/extension/scripts/path.ts
Normal file
16
apps/vscode/extension/scripts/path.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
export function getDirname(metaUrl: string, targetPath: string) {
|
||||
const dirname = path.dirname(metaUrl.replace('file://', ''))
|
||||
return path.normalize(path.join(dirname, targetPath))
|
||||
}
|
||||
|
||||
export async function exists(targetFolder: string) {
|
||||
try {
|
||||
await fs.promises.access(targetFolder)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
82
apps/vscode/extension/scripts/publish.ts
Normal file
82
apps/vscode/extension/scripts/publish.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { exec } from 'child_process'
|
||||
import { readdirSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { promisify } from 'util'
|
||||
|
||||
const execAsync = promisify(exec)
|
||||
const MAX_REGISTRY_PUBLISH_ATTEMPTS = 3
|
||||
const REGISTRY_PUBLISH_RETRY_DELAY_MS = 10_000
|
||||
|
||||
class AmbiguousPublishError extends Error {}
|
||||
|
||||
async function publishWithRetry(command: string) {
|
||||
for (let attempt = 1; attempt <= MAX_REGISTRY_PUBLISH_ATTEMPTS; attempt++) {
|
||||
try {
|
||||
await execAsync(command)
|
||||
return
|
||||
} catch (err) {
|
||||
const error = err as Error & { stdout?: string; stderr?: string }
|
||||
if (
|
||||
[error.message, error.stdout, error.stderr].some((text) => text?.includes('already exists'))
|
||||
) {
|
||||
if (attempt > 1) {
|
||||
throw new AmbiguousPublishError('An earlier publish attempt may have succeeded.', {
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
throw err
|
||||
}
|
||||
if (attempt === MAX_REGISTRY_PUBLISH_ATTEMPTS) {
|
||||
throw err
|
||||
}
|
||||
console.error(
|
||||
`Publish attempt ${attempt}/${MAX_REGISTRY_PUBLISH_ATTEMPTS} failed; retrying in ${REGISTRY_PUBLISH_RETRY_DELAY_MS / 1000}s...`,
|
||||
err
|
||||
)
|
||||
await new Promise((resolve) => setTimeout(resolve, REGISTRY_PUBLISH_RETRY_DELAY_MS))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getVsixPath(): string {
|
||||
const tempDir = join(__dirname, '../temp')
|
||||
const files = readdirSync(tempDir)
|
||||
const vsixFile = files.find((file) => file.endsWith('.vsix'))
|
||||
if (!vsixFile) {
|
||||
throw new Error('No .vsix file found in temp directory')
|
||||
}
|
||||
return join(tempDir, vsixFile)
|
||||
}
|
||||
|
||||
async function publishToVSCodeMarketplace(preRelease: boolean) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Publishing to VS Code Marketplace${preRelease ? ' (pre-release)' : ''}`)
|
||||
await publishWithRetry(`vsce publish${preRelease ? ' --pre-release' : ''}`)
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Successfully published to VS Code Marketplace')
|
||||
}
|
||||
|
||||
async function publishToOpenVSX(preRelease: boolean) {
|
||||
const vsixPath = getVsixPath()
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Publishing to Open VSX...')
|
||||
// An upload can succeed even if its response is lost; retrying must accept that version.
|
||||
await publishWithRetry(
|
||||
`npx ovsx publish --skip-duplicate${preRelease ? ' --pre-release' : ''} ${vsixPath}`
|
||||
)
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Successfully published to Open VSX')
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const preRelease = process.argv.includes('--pre-release')
|
||||
|
||||
await publishToVSCodeMarketplace(preRelease)
|
||||
await publishToOpenVSX(preRelease)
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
// The outer publisher must not interpret the duplicate in the cause as a version conflict.
|
||||
process.exit(err instanceof AmbiguousPublishError ? 75 : 1)
|
||||
})
|
||||
Reference in New Issue
Block a user