kopia lustrzana https://github.com/Tldraw/Tldraw
cherry-pick tooling changes too i guess
rodzic
ba6cba64c6
commit
d5401bd168
|
@ -0,0 +1,61 @@
|
|||
name: Publish patch release
|
||||
# This bumps the patch version, updates the changelogs in the release branch only, publishes a GitHub release, and publishes the packages to npm.
|
||||
|
||||
# Prevent more than one non-canary npm publishing job from running at the same time
|
||||
concurrency:
|
||||
group: npm-publish
|
||||
|
||||
# Package publishing is manually triggered on github actions dashboard
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'v*.*.x'
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Publish patch release
|
||||
environment: npm deploy
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest-16-cores-open
|
||||
outputs:
|
||||
is_latest_version: ${{ steps.publish_step.outputs.is_latest_version }}
|
||||
|
||||
steps:
|
||||
- name: Generate GH token
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
|
||||
with:
|
||||
app_id: ${{ secrets.HUPPY_APP_ID }}
|
||||
private_key: ${{ secrets.HUPPY_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
|
||||
- name: Prepare repository
|
||||
# Fetch full git history and tags for auto
|
||||
run: git fetch --unshallow --tags
|
||||
|
||||
- name: Run our setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Publish
|
||||
id: publish_step
|
||||
run: |
|
||||
git config --global user.name 'huppy-bot[bot]'
|
||||
git config --global user.email '128400622+huppy-bot[bot]@users.noreply.github.com'
|
||||
yarn tsx ./scripts/publish-patch.ts
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
HUPPY_TOKEN: ${{ secrets.HUPPY_TOKEN }}
|
||||
|
||||
publish_templates:
|
||||
name: Publishes code templates to separate repositories
|
||||
uses: tldraw/tldraw/.github/workflows/publish-templates.yml@main
|
||||
if: ${{ needs.deploy.outputs.is_latest_version == 'true' }}
|
||||
secrets:
|
||||
VITE_TEMPLATE_REPO_SSH_DEPLOY_KEY: ${{ secrets.VITE_TEMPLATE_REPO_SSH_DEPLOY_KEY }}
|
||||
NEXTJS_TEMPLATE_REPO_SSH_DEPLOY_KEY: ${{ secrets.NEXTJS_TEMPLATE_REPO_SSH_DEPLOY_KEY }}
|
||||
needs: deploy
|
|
@ -103,7 +103,7 @@ function topologicalSortPackages(packages: Record<string, PackageDetails>) {
|
|||
return sorted
|
||||
}
|
||||
|
||||
export async function publish() {
|
||||
export async function publish(distTag?: string) {
|
||||
const npmToken = process.env.NPM_TOKEN
|
||||
if (!npmToken) {
|
||||
throw new Error('NPM_TOKEN not set')
|
||||
|
@ -117,9 +117,9 @@ export async function publish() {
|
|||
const publishOrder = topologicalSortPackages(packages)
|
||||
|
||||
for (const packageDetails of publishOrder) {
|
||||
const prereleaseTag = parse(packageDetails.version)?.prerelease[0] ?? 'latest'
|
||||
const tag = distTag ?? parse(packageDetails.version)?.prerelease[0] ?? 'latest'
|
||||
nicelog(
|
||||
`Publishing ${packageDetails.name} with version ${packageDetails.version} under tag @${prereleaseTag}`
|
||||
`Publishing ${packageDetails.name} with version ${packageDetails.version} under tag @${tag}`
|
||||
)
|
||||
|
||||
await retry(
|
||||
|
@ -128,15 +128,7 @@ export async function publish() {
|
|||
try {
|
||||
await exec(
|
||||
`yarn`,
|
||||
[
|
||||
'npm',
|
||||
'publish',
|
||||
'--tag',
|
||||
String(prereleaseTag),
|
||||
'--tolerate-republish',
|
||||
'--access',
|
||||
'public',
|
||||
],
|
||||
['npm', 'publish', '--tag', String(tag), '--tolerate-republish', '--access', 'public'],
|
||||
{
|
||||
pwd: packageDetails.dir,
|
||||
processStdoutLine: (line) => {
|
||||
|
|
|
@ -1,39 +1,25 @@
|
|||
import { exec } from './lib/exec'
|
||||
import { nicelog } from './lib/nicelog'
|
||||
import { getLatestVersion, publish, setAllVersions } from './lib/publishing'
|
||||
|
||||
async function main() {
|
||||
const sha = (await exec('git', ['rev-parse', 'HEAD'])).trim().slice(0, 12)
|
||||
|
||||
async function setCanaryVersions(bump: 'major' | 'minor' | 'patch') {
|
||||
async function setCanaryVersions() {
|
||||
const latestVersion = await getLatestVersion()
|
||||
|
||||
const nextVersion = latestVersion.prerelease.length
|
||||
? // if the package is in prerelease mode, we want to release a canary for the current version rather than bumping
|
||||
latestVersion
|
||||
: latestVersion?.inc(bump)
|
||||
: latestVersion?.inc('minor')
|
||||
const versionString = `${nextVersion.major}.${nextVersion.minor}.${nextVersion.patch}-canary.${sha}`
|
||||
|
||||
await setAllVersions(versionString)
|
||||
}
|
||||
|
||||
// module was called directly
|
||||
const bumpType = (await exec('npx', ['auto', 'version'])).trim() as
|
||||
| 'major'
|
||||
| 'minor'
|
||||
| 'patch'
|
||||
| ''
|
||||
|
||||
nicelog('bumpType', bumpType)
|
||||
if (bumpType === '') {
|
||||
nicelog('nothing to do')
|
||||
} else if (['major', 'minor', 'patch'].includes(bumpType)) {
|
||||
nicelog('setting canary versions')
|
||||
setCanaryVersions(bumpType)
|
||||
publish()
|
||||
} else {
|
||||
throw new Error('Invalid bump type provided')
|
||||
}
|
||||
setCanaryVersions()
|
||||
publish('canary')
|
||||
}
|
||||
|
||||
main()
|
||||
|
|
|
@ -1,8 +1,22 @@
|
|||
import { publish } from './lib/publishing'
|
||||
import { appendFileSync } from 'fs'
|
||||
import { exec } from './lib/exec'
|
||||
import { getLatestVersion, publish } from './lib/publishing'
|
||||
|
||||
// This expects the package.json files to be in the correct state.
|
||||
// You might want to run this locally after a failed publish attempt on CI.
|
||||
// Or if you need to hotfix a package it might be desirable to run this.
|
||||
|
||||
// Generate a npm automation token and run this with the NPM_TOKEN env var set.
|
||||
publish()
|
||||
async function main() {
|
||||
const latestVersionInBranch = await getLatestVersion()
|
||||
const latestVersionOnNpm = (await exec('npm', ['show', 'tldraw', 'version'])).trim()
|
||||
|
||||
const isLatestVersion = latestVersionInBranch.format() === latestVersionOnNpm
|
||||
if (process.env.GITHUB_OUTPUT) {
|
||||
appendFileSync(process.env.GITHUB_OUTPUT, `is_latest_version=${isLatestVersion}\n`)
|
||||
}
|
||||
|
||||
publish()
|
||||
}
|
||||
|
||||
main()
|
||||
|
|
|
@ -70,6 +70,8 @@ async function main() {
|
|||
const releaseType = getReleaseType()
|
||||
const nextVersion = await getNextVersion(releaseType)
|
||||
|
||||
const isPrerelease = parse(nextVersion)!.prerelease.length > 0
|
||||
|
||||
console.log('Releasing version', nextVersion)
|
||||
|
||||
await setAllVersions(nextVersion)
|
||||
|
@ -111,10 +113,18 @@ async function main() {
|
|||
title: `v${nextVersion}`,
|
||||
})
|
||||
|
||||
const gitTag = `v${nextVersion}`
|
||||
|
||||
// create and push a new tag
|
||||
await exec('git', ['tag', '-f', `v${nextVersion}`])
|
||||
await exec('git', ['tag', '-f', gitTag])
|
||||
await exec('git', ['push', '--follow-tags'])
|
||||
|
||||
// create new 'release' branch called e.g. v2.0.x or v4.3.x, for making patch releases
|
||||
if (!isPrerelease) {
|
||||
const { major, minor } = parse(nextVersion)!
|
||||
await exec('git', ['push', 'origin', `${gitTag}:refs/heads/v${major}.${minor}.x`])
|
||||
}
|
||||
|
||||
// create a release on github
|
||||
await auto.runRelease({ useVersion: nextVersion })
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
import { Auto } from '@auto-it/core'
|
||||
import fetch from 'cross-fetch'
|
||||
import glob from 'glob'
|
||||
import { assert } from 'node:console'
|
||||
import { appendFileSync } from 'node:fs'
|
||||
import { exec } from './lib/exec'
|
||||
import { nicelog } from './lib/nicelog'
|
||||
import { getLatestVersion, publish, setAllVersions } from './lib/publishing'
|
||||
import { getAllWorkspacePackages } from './lib/workspace'
|
||||
|
||||
async function main() {
|
||||
const huppyToken = process.env.HUPPY_TOKEN
|
||||
assert(huppyToken && typeof huppyToken === 'string', 'HUPPY_ACCESS_KEY env var must be set')
|
||||
|
||||
const latestVersionInBranch = await getLatestVersion()
|
||||
const latestVersionOnNpm = (await exec('npm', ['show', 'tldraw', 'version'])).trim()
|
||||
|
||||
const isLatestVersion = latestVersionInBranch.format() === latestVersionOnNpm
|
||||
if (process.env.GITHUB_OUTPUT) {
|
||||
appendFileSync(process.env.GITHUB_OUTPUT, `is_latest_version=${isLatestVersion}\n`)
|
||||
}
|
||||
|
||||
const nextVersion = latestVersionInBranch.inc('patch').format()
|
||||
// check we're on the main branch on HEAD
|
||||
const currentBranch = (await exec('git', ['rev-parse', '--abbrev-ref', 'HEAD'])).toString().trim()
|
||||
if (currentBranch !== `v${latestVersionInBranch.major}.${latestVersionInBranch.minor}.x`) {
|
||||
throw new Error('Branch name does not match expected format: v{major}.{minor}.x')
|
||||
}
|
||||
|
||||
// we could probably do this a lot earlier in the yml file but 🤷♂️
|
||||
const numberOfCommitsSinceBranch = Number(
|
||||
(await exec('git', ['rev-list', '--count', `HEAD`, '^main'])).toString().trim()
|
||||
)
|
||||
|
||||
if (numberOfCommitsSinceBranch === 0) {
|
||||
// Skip release if there are no commits since this branch was created during the initial release
|
||||
// for this <major>.<minor> version.
|
||||
nicelog('Initial push, skipping release')
|
||||
return
|
||||
}
|
||||
|
||||
nicelog('Releasing version', nextVersion)
|
||||
|
||||
await setAllVersions(nextVersion)
|
||||
|
||||
// stage the changes
|
||||
const packageJsonFilesToAdd = []
|
||||
for (const workspace of await getAllWorkspacePackages()) {
|
||||
if (workspace.relativePath.startsWith('packages/')) {
|
||||
packageJsonFilesToAdd.push(`${workspace.relativePath}/package.json`)
|
||||
}
|
||||
}
|
||||
const versionFilesToAdd = glob.sync('**/*/version.ts', {
|
||||
ignore: ['node_modules/**'],
|
||||
follow: false,
|
||||
})
|
||||
console.log('versionFilesToAdd', versionFilesToAdd)
|
||||
await exec('git', [
|
||||
'add',
|
||||
'--update',
|
||||
'lerna.json',
|
||||
...packageJsonFilesToAdd,
|
||||
...versionFilesToAdd,
|
||||
])
|
||||
|
||||
const auto = new Auto({
|
||||
plugins: ['npm'],
|
||||
baseBranch: currentBranch,
|
||||
owner: 'tldraw',
|
||||
repo: 'tldraw',
|
||||
verbose: true,
|
||||
disableTsNode: true,
|
||||
})
|
||||
|
||||
await auto.loadConfig()
|
||||
|
||||
// this creates a new commit
|
||||
await auto.changelog({
|
||||
useVersion: nextVersion,
|
||||
title: `v${nextVersion}`,
|
||||
})
|
||||
|
||||
// create and push a new tag
|
||||
await exec('git', ['tag', '-f', `v${nextVersion}`])
|
||||
await exec('git', ['push', '--follow-tags'])
|
||||
|
||||
// create a release on github
|
||||
await auto.runRelease({ useVersion: 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 (isLatestVersion) {
|
||||
nicelog('Notifying huppy of release...')
|
||||
const huppyResponse = await fetch('https://tldraw-repo-sync.fly.dev/api/on-release', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ apiKey: huppyToken, tagToRelease: `v${nextVersion}`, canary: false }),
|
||||
})
|
||||
nicelog(
|
||||
`huppy: [${huppyResponse.status} ${huppyResponse.statusText}] ${await huppyResponse.text()}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
Ładowanie…
Reference in New Issue