From f870d0d7833c0512192a57442823580aa59648c3 Mon Sep 17 00:00:00 2001 From: venetak Date: Wed, 14 Feb 2024 17:30:29 +0200 Subject: [PATCH] Add publish script and workflow --- .github/workflows/publish.yml | 43 ++++++++++++++ publish.js | 103 ++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 .github/workflows/publish.yml create mode 100644 publish.js diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000000..aa1a6411b9c --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,43 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Publish + +on: + push: + branches: [main] + +jobs: + package: + runs-on: windows-latest + + strategy: + matrix: + node-version: [20.11.0] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - name: Setup Chrome + uses: browser-actions/setup-chrome@v0.0.0 + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + + - run: npm config set '//registry.npmjs.org/:_authToken' "${{ secrets.NPM_TOKEN }}" + - name: Package cohtml react-scripts + run: npm pack + working-directory: ./packages/react-scripts + + - name: Package cra-template-cohtml + run: npm pack + working-directory: ./packages/cra-template-cohtml + + - name: Publish cohtml react-scripts and template + run: node publish.js + + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/publish.js b/publish.js new file mode 100644 index 00000000000..9947bb2db73 --- /dev/null +++ b/publish.js @@ -0,0 +1,103 @@ +'use strict'; + +const path = require('path'); +const fs = require('fs'); +const { execSync } = require('child_process'); +const reactScriptsPath = path.join(__dirname, 'packages/react-scripts'); +const craTemplateCohtmlPath = path.join( + __dirname, + 'packages/cra-template-cohtml' +); + +const reactScriptsPackageJSON = getPackageJSON(reactScriptsPath); +const craTemplateCohtmlPackageJSON = getPackageJSON(craTemplateCohtmlPath); + +/** + * Will get package json for some package + * @param {string} directory + * @returns {Object} + */ +function getPackageJSON(directory) { + const packageJSONPath = path.join(directory, 'package.json'); + const fsStats = fs.lstatSync(packageJSONPath, { throwIfNoEntry: false }); + if (!fsStats || !fsStats.isFile()) { + console.error(`Could not find package.json in ${directory}.`); + return null; + } + return JSON.parse(fs.readFileSync(packageJSONPath)); +} + +/** + * Gets the latest version of some npm package + * @param {string} npmPackage - The npm package name + * @returns {string} + */ +function getPublicVersion(npmPackage) { + return execSync(`npm view ${npmPackage} version`, { + encoding: 'utf8', + }).replace('\n', ''); +} + +/** + * Checks if some component should be updated in npm if its version is bumped + * @param {string} packageJSON + * @returns {boolean} + */ +function shouldUpdate(packageJSON) { + if (!packageJSON) { + return false; + } + + const name = packageJSON.name; + console.log(`Checking if ${name} should be published...`); + // if a package doesn't exist in the registry then it must be published + if ( + !JSON.parse(execSync(`npm search ${name} --json`, { encoding: 'utf8' })) + .length + ) { + console.log( + `Package ${name} does not exist on the public registry - it should be published!` + ); + return true; + } + + const localVersion = packageJSON.version; + const publicVersion = getPublicVersion(name); + + if (localVersion !== publicVersion) { + console.log( + `Package ${name} has new local version - ${localVersion}. The current npm version is ${publicVersion}.` + ); + return true; + } + + console.log(`Package ${name} needs no publish.`); + return false; +} + +/** + * Publish a package to npm + * @param {string} name + * @param {string} directory + */ +function publish(name, directory) { + try { + execSync(`npm publish`, { + cwd: directory, + encoding: 'utf8', + stdio: 'inherit', + }); + console.log(`Successfully published ${name}.`); + } catch (error) { + console.error(error); + } +} + +module.exports = (() => { + if (shouldUpdate(reactScriptsPackageJSON)) { + publish(reactScriptsPackageJSON.name, reactScriptsPath); + } + if (shouldUpdate(craTemplateCohtmlPackageJSON)) { + publish(craTemplateCohtmlPackageJSON.name, craTemplateCohtmlPath); + } +})();