From 03479d06d1294bb738e200d6eac66411cd7f9add Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 10 May 2019 07:43:37 -0700 Subject: [PATCH] Publish beta and stable builds to npm automatically --- azure-pipelines.yml | 26 +++++++++++++++++++ scripts/publish.js | 62 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 scripts/publish.js diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b078d70d6..169374311 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -21,6 +21,7 @@ jobs: - script: | npm run lint displayName: 'Lint' + - job: macOS pool: vmImage: 'xcode9-macos10.13' @@ -38,6 +39,7 @@ jobs: - script: | npm run lint displayName: 'Lint' + - job: Windows pool: vmImage: 'vs2017-win2016' @@ -55,3 +57,27 @@ jobs: - script: | npm run lint displayName: 'Lint' + +- job: Release + dependsOn: + - Linux + - macOS + - Windows + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: NodeTool@0 + inputs: + versionSpec: '8.x' + displayName: 'Install Node.js' + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.9.4" + displayName: 'Install Yarn' + - script: | + npm i + displayName: 'Install dependencies and build' + - script: | + NPM_AUTH_TOKEN="$(NPM_AUTH_TOKEN)" node ./scripts/publish.js + displayName: 'Publish to npm' diff --git a/scripts/publish.js b/scripts/publish.js new file mode 100644 index 000000000..968531e14 --- /dev/null +++ b/scripts/publish.js @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2019, Microsoft Corporation (MIT License). + */ + +const cp = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const packageJson = require('../package.json'); + +// Setup auth +fs.writeFileSync(`${process.env['HOME']}/.npmrc`, `//registry.npmjs.org/:_authToken=${process.env['NPM_AUTH_TOKEN']}`); + +// Determine if this is a stable or beta release +const publishedVersions = getPublishedVersions(); +const isStableRelease = publishedVersions.indexOf(packageJson.version) === -1; + +// Get the next version +let nextVersion = isStableRelease ? packageJson.version : getNextBetaVersion(); +console.log(`Publishing version: ${nextVersion}`); + +// Set the version in package.json +const packageJsonFile = path.resolve(__dirname, '..', 'package.json'); +packageJson.version = nextVersion; +fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2)); + +// Publish +const args = ['publish']; +if (!isStableRelease) { + args.push('--tag', 'beta'); +} +const result = cp.spawn('npm', args, { stdio: 'inherit' }); +result.on('exit', code => process.exit(code)); + +function getNextBetaVersion() { + if (!/^[0-9]+\.[0-9]+\.[0-9]+$/.exec(packageJson.version)) { + console.error('The package.json version must be of the form x.y.z'); + process.exit(1); + } + const tag = 'beta'; + const stableVersion = packageJson.version.split('.'); + const nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.0`; + const publishedVersions = getPublishedVersions(nextStableVersion, tag); + if (publishedVersions.length === 0) { + return `${nextStableVersion}-${tag}1`; + } + const latestPublishedVersion = publishedVersions.sort((a, b) => { + const aVersion = parseInt(a.substr(a.search(/[0-9]+$/))); + const bVersion = parseInt(b.substr(b.search(/[0-9]+$/))); + return aVersion > bVersion ? -1 : 1; + })[0]; + const latestTagVersion = parseInt(latestPublishedVersion.substr(latestPublishedVersion.search(/[0-9]+$/)), 10); + return `${nextStableVersion}-${tag}${latestTagVersion + 1}`; +} + +function getPublishedVersions(version, tag) { + const versionsProcess = cp.spawnSync('npm', ['view', packageJson.name, 'versions', '--json']); + const versionsJson = JSON.parse(versionsProcess.stdout); + if (tag) { + return versionsJson.filter(v => !v.search(new RegExp(`${version}-${tag}[0-9]+`))); + } + return versionsJson; +}