Automatically publish prereleases to npm (#155)
This commit creates `x.x.x-insiders.COMMIT_HASH` builds of all of our public packages, and publishes them to npm with the `insiders` tag, so one could say `npm install @theatre/core@0.4.8-insiders.bsdf387` and use the package at that particular commit. Co-authored-by: Aria Minaei <aria.minaei@gmail.com>
This commit is contained in:
parent
3d10325873
commit
8520c74116
5 changed files with 196 additions and 3 deletions
10
.github/.yarnrc.publish.yml
vendored
Normal file
10
.github/.yarnrc.publish.yml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Auth config for publishing to npm registry.
|
||||
# It's put in /.github so it's only picked up by
|
||||
# github actions.
|
||||
|
||||
npmPublishRegistry: 'https://registry.npmjs.org'
|
||||
|
||||
npmRegistries:
|
||||
//registry.npmjs.org:
|
||||
npmAlwaysAuth: true
|
||||
npmAuthToken: ${NODE_AUTH_TOKEN}
|
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -7,7 +7,7 @@ on:
|
|||
branches: [main]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
Test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
|
|
34
.github/workflows/publish-prerelease.yml
vendored
Normal file
34
.github/workflows/publish-prerelease.yml
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
name: 'Publish Prerelease'
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
|
||||
- uses: actions/cache@v2
|
||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- run: yarn install
|
||||
- name: Build the theatre packages
|
||||
run: yarn build
|
||||
- name: Update .yarnrc.yml with the auth config for the npmPublishRegistry
|
||||
run: cat .github/.yarnrc.publish.yml >> .yarnrc.yml
|
||||
- name: Publish the theatre packages
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
# LATEST_COMMIT_HASH: ${{ github.event.pull_request.head.sha }}
|
||||
run: yarn zx scripts/prerelease.mjs
|
|
@ -2,8 +2,8 @@ nodeLinker: node-modules
|
|||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-compat.cjs
|
||||
spec: "@yarnpkg/plugin-compat"
|
||||
spec: '@yarnpkg/plugin-compat'
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||
spec: "@yarnpkg/plugin-interactive-tools"
|
||||
spec: '@yarnpkg/plugin-interactive-tools'
|
||||
|
||||
yarnPath: .yarn/releases/yarn-3.2.0.cjs
|
||||
|
|
149
scripts/prerelease.mjs
Normal file
149
scripts/prerelease.mjs
Normal file
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* This script publishes the insider packages from the CI. You can't run it locally unless you have a a valid npm access token and you store its value in the `NPM_TOKEN` environmental variable.
|
||||
*/
|
||||
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
|
||||
const packagesToPublish = [
|
||||
'@theatre/core',
|
||||
'@theatre/studio',
|
||||
'@theatre/dataverse',
|
||||
'@theatre/react',
|
||||
'@theatre/browser-bundles',
|
||||
'@theatre/r3f',
|
||||
]
|
||||
|
||||
/**
|
||||
* Receives a version number and returns it without the tags, if there are any
|
||||
*
|
||||
* @param {string} version - Version number
|
||||
* @returns Version number without the tags
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const version_1 = '0.4.8-dev3-ec175817'
|
||||
* const version_2 = '0.4.8'
|
||||
*
|
||||
* stripTag(version_1) === stripTag(version_2) === '0.4.8' // returns `true`
|
||||
* ```
|
||||
*/
|
||||
function stripTag(version) {
|
||||
const regExp = /^[0-9]+\.[0-9]+\.[0-9]+/g
|
||||
const matches = version.match(regExp)
|
||||
if (!matches) {
|
||||
throw new Error(`Version number not found in "${version}"`)
|
||||
}
|
||||
|
||||
return matches[0]
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a version number like `0.4.8-insiders.ec175817`
|
||||
*
|
||||
* @param {string} packageName - Name of the package
|
||||
* @param {string} commitHash - A commit hash
|
||||
*/
|
||||
function getNewVersionName(packageName, commitHash) {
|
||||
// The `r3f` package has its own release schedule, so its version numbers
|
||||
// are almost always different from the rest of the packages.
|
||||
const pathToPackageJson =
|
||||
packageName === '@theatre/r3f'
|
||||
? path.resolve(__dirname, '..', 'packages', 'r3f', 'package.json')
|
||||
: path.resolve(__dirname, '../', './package.json')
|
||||
|
||||
const jsonData = JSON.parse(
|
||||
fs.readFileSync(pathToPackageJson, {encoding: 'utf-8'}),
|
||||
)
|
||||
const strippedVersion = stripTag(jsonData.version)
|
||||
|
||||
return `${strippedVersion}-insiders.${commitHash}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the new versions to the packages
|
||||
*
|
||||
* @param {{name: string, location: string}[]} workspacesListObjects - An Array of objects containing information about the workspaces
|
||||
* @param {string} latestCommitHash - Hash of the latest commit
|
||||
*/
|
||||
async function assignVersions(workspacesListObjects, latestCommitHash) {
|
||||
for (const workspaceData of workspacesListObjects) {
|
||||
const pathToPackage = path.resolve(
|
||||
__dirname,
|
||||
'../',
|
||||
workspaceData.location,
|
||||
'./package.json',
|
||||
)
|
||||
|
||||
const original = JSON.parse(
|
||||
fs.readFileSync(pathToPackage, {encoding: 'utf-8'}),
|
||||
)
|
||||
|
||||
let {version, dependencies, peerDependencies, devDependencies} = original
|
||||
// The @theatre/r3f package curently doesn't track the same version number of the other packages like @theatre/core,
|
||||
// so we need to generate version numbers independently for each package
|
||||
version = getNewVersionName(workspaceData.name, latestCommitHash)
|
||||
// Normally we don't have to override the package versions in dependencies because yarn would already convert
|
||||
// all the "workspace:*" versions to a fixed version before publishing. However, packages like @theatre/studio
|
||||
// have a peerDependency on @theatre/core set to "*" (meaning they would work with any version of @theatre/core).
|
||||
// This is not the desired behavior in pre-release versions, so here, we'll fix those "*" versions to the set version.
|
||||
for (const deps of [dependencies, peerDependencies, devDependencies]) {
|
||||
if (!deps) continue
|
||||
for (const wpObject of workspacesListObjects) {
|
||||
if (deps[wpObject.name]) {
|
||||
deps[wpObject.name] = getNewVersionName(
|
||||
wpObject.name,
|
||||
latestCommitHash,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
const newJson = {
|
||||
...original,
|
||||
version,
|
||||
dependencies,
|
||||
peerDependencies,
|
||||
devDependencies,
|
||||
}
|
||||
fs.writeFileSync(
|
||||
path.join(pathToPackage),
|
||||
JSON.stringify(newJson, undefined, 2),
|
||||
{encoding: 'utf-8'},
|
||||
)
|
||||
await $`prettier --write ${workspaceData.location + '/package.json'}`
|
||||
}
|
||||
}
|
||||
|
||||
;(async function () {
|
||||
// @ts-ignore ignore
|
||||
process.env.THEATRE_IS_PUBLISHING = true
|
||||
// In the CI `git log -1` points to a fake merge commit,
|
||||
// so we have to use the value of a special GitHub context variable
|
||||
// through the `GITHUB_SHA` environmental variable.
|
||||
|
||||
// The length of the abbreviated commit hash can change, that's why we
|
||||
// need the lenght of the fake merge commit's abbreviated hash.
|
||||
const fakeMergeCommitHashLength = (await $`git log -1 --pretty=format:%h`)
|
||||
.stdout.length
|
||||
|
||||
const latestCommitHash = process.env.GITHUB_SHA.slice(
|
||||
0,
|
||||
fakeMergeCommitHashLength,
|
||||
)
|
||||
|
||||
const workspacesListString = await $`yarn workspaces list --json`
|
||||
const workspacesListObjects = workspacesListString.stdout
|
||||
.split(os.EOL)
|
||||
// strip out empty lines
|
||||
.filter(Boolean)
|
||||
.map((x) => JSON.parse(x))
|
||||
|
||||
await assignVersions(workspacesListObjects, latestCommitHash)
|
||||
|
||||
await Promise.all(
|
||||
packagesToPublish.map((workspaceName) => {
|
||||
const npmTag = 'insiders'
|
||||
return $`yarn workspace ${workspaceName} npm publish --access public --tag ${npmTag}`
|
||||
}),
|
||||
)
|
||||
})()
|
Loading…
Reference in a new issue