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:
138
internal/scripts/publish-patch.ts
Normal file
138
internal/scripts/publish-patch.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import { appendFileSync, readFileSync } from 'node:fs'
|
||||
import { Octokit } from '@octokit/rest'
|
||||
import { parse } from 'semver'
|
||||
import { extractChangelog } from './extract-draft-changelog'
|
||||
import { getAnyPackageDiff } from './lib/didAnyPackageChange'
|
||||
import { exec } from './lib/exec'
|
||||
import { nicelog } from './lib/nicelog'
|
||||
import {
|
||||
getLatestTldrawVersionFromNpm,
|
||||
publish,
|
||||
publishProductionDocsAndExamplesAndBemo,
|
||||
setAllVersions,
|
||||
triggerBumpVersionsWorkflow,
|
||||
} from './lib/publishing'
|
||||
import { uploadStaticAssets } from './lib/upload-static-assets'
|
||||
|
||||
async function main() {
|
||||
const currentBranch = (await exec('git', ['rev-parse', '--abbrev-ref', 'HEAD'])).toString().trim()
|
||||
const match = currentBranch.match(/^v(\d+)\.(\d+)\.x$/)
|
||||
if (!match) {
|
||||
throw new Error('Branch name does not match expected format: v{major}.{minor}.x')
|
||||
}
|
||||
const [major, minor] = match.slice(1).map(Number)
|
||||
const latestVersionInBranch = await getLatestTldrawVersionFromNpm({
|
||||
versionPrefix: `${major}.${minor}`,
|
||||
})
|
||||
|
||||
// Check if this commit is already tagged with the initial release for this major.minor version
|
||||
const expectedInitialTag = `v${latestVersionInBranch.major}.${latestVersionInBranch.minor}.0`
|
||||
const tagsAtThisCommit = (await exec('git', ['tag', '--points-at', 'HEAD']))
|
||||
.toString()
|
||||
.trim()
|
||||
.split('\n')
|
||||
|
||||
if (tagsAtThisCommit.includes(expectedInitialTag)) {
|
||||
// Skip release if this is the initial release commit for this major.minor version
|
||||
nicelog('Initial release commit, skipping patch release')
|
||||
return
|
||||
} else {
|
||||
nicelog('Not an initial release commit, continuing with patch release')
|
||||
}
|
||||
|
||||
const latestVersion = await getLatestTldrawVersionFromNpm()
|
||||
const isLatestVersion = latestVersion.compare(latestVersionInBranch) === 0
|
||||
|
||||
if (isLatestVersion) {
|
||||
await publishProductionDocsAndExamplesAndBemo()
|
||||
}
|
||||
|
||||
// Ensure asset directories exist before comparing package contents.
|
||||
// CI may skip postinstall (and thus refresh-assets) when install-state.gz is cached.
|
||||
await exec('yarn', ['refresh-assets', '--force'])
|
||||
|
||||
// Skip releasing a new version if the package contents are identical.
|
||||
// This may happen when cherry-picking docs-only changes.
|
||||
if (!(await getAnyPackageDiff(latestVersionInBranch.format()))) {
|
||||
nicelog('No packages have changed, skipping release')
|
||||
return
|
||||
}
|
||||
|
||||
if (process.env.GITHUB_OUTPUT) {
|
||||
appendFileSync(process.env.GITHUB_OUTPUT, `is_latest_version=${isLatestVersion}\n`)
|
||||
}
|
||||
|
||||
// Capture the previous tag BEFORE calling .inc(): semver's SemVer.prototype.inc()
|
||||
// mutates the instance in place, so reading latestVersionInBranch.format() afterwards
|
||||
// would return the new version and leave prevTag === tag, producing an empty changelog.
|
||||
const prevTag = `v${latestVersionInBranch.format()}`
|
||||
|
||||
// Determine the version to bump from. Normally this is the latest version
|
||||
// published on npm for this branch. But if a previous patch release was
|
||||
// interrupted after the "v X.Y.Z [skip ci]" version-bump commit was pushed
|
||||
// but before npm publish completed, the local package.json files (and the
|
||||
// matching git tag) will be ahead of npm. In that case we bump from the
|
||||
// local version so we sidestep the orphaned version+tag entirely instead
|
||||
// of trying to re-create them - both `git commit` (no staged changes) and
|
||||
// `git push --follow-tags` (tag already exists at a different commit on
|
||||
// origin) would otherwise fail and permanently wedge the branch.
|
||||
const localTldrawVersion = parse(
|
||||
JSON.parse(readFileSync('packages/tldraw/package.json', 'utf8')).version
|
||||
)
|
||||
const baseVersion =
|
||||
localTldrawVersion && localTldrawVersion.compare(latestVersionInBranch) > 0
|
||||
? localTldrawVersion
|
||||
: latestVersionInBranch
|
||||
if (baseVersion !== latestVersionInBranch) {
|
||||
nicelog(
|
||||
`Local package version ${baseVersion.format()} is ahead of latest npm version ` +
|
||||
`${latestVersionInBranch.format()}; bumping from local to skip past orphaned version.`
|
||||
)
|
||||
}
|
||||
|
||||
// .inc() mutates baseVersion; reparse so callers downstream of us see the
|
||||
// original instance unchanged.
|
||||
const nextVersion = parse(baseVersion.format())!.inc('patch').format()
|
||||
nicelog('Releasing version', nextVersion)
|
||||
|
||||
await setAllVersions(nextVersion, { stageChanges: true })
|
||||
|
||||
const tag = `v${nextVersion}`
|
||||
|
||||
// create and push a new tag
|
||||
await exec('git', ['commit', '-m', `${tag} [skip ci]`])
|
||||
await exec('git', ['tag', '-a', tag, '-m', tag, '-f'])
|
||||
await exec('git', ['push', '--follow-tags'])
|
||||
|
||||
// Generate changelog and create GitHub release
|
||||
nicelog('Generating changelog...')
|
||||
const changelog = await extractChangelog(prevTag, 'HEAD')
|
||||
|
||||
nicelog('Creating GitHub release...')
|
||||
const octokit = new Octokit({ auth: process.env.GH_TOKEN })
|
||||
await octokit.repos.createRelease({
|
||||
owner: 'tldraw',
|
||||
repo: 'tldraw',
|
||||
tag_name: tag,
|
||||
name: tag,
|
||||
body: changelog,
|
||||
draft: false,
|
||||
prerelease: false,
|
||||
})
|
||||
|
||||
await uploadStaticAssets(nextVersion)
|
||||
|
||||
// if we're on the latest version, publish to npm under 'latest' tag.
|
||||
// otherwise we don't want to overwrite the latest tag, so we publish under 'revision'.
|
||||
// semver rules will still be respected because there's no prerelease tag in the version,
|
||||
// so clients will get the updated version if they have a range like ^1.0.0
|
||||
await publish(isLatestVersion ? 'latest' : 'revision')
|
||||
|
||||
// If this is the latest version, trigger version bump on main branch to sync all package versions
|
||||
if (isLatestVersion) {
|
||||
nicelog('This is the latest version, triggering version bump on main branch')
|
||||
await triggerBumpVersionsWorkflow(process.env.GH_TOKEN!)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user