[ci] Prepare publish workflow (#32488)

Fixes up a few things in the script and workflow to make it possible to
run in CI without interactive prompts.
This commit is contained in:
lauren 2025-02-27 15:24:57 -05:00 committed by GitHub
parent 227e8414cc
commit 4c9392b43e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 156 additions and 74 deletions

View File

@ -12,22 +12,22 @@ on:
description: Version to publish for the specified packages
type: string
only_packages:
description: Space separated list of packages to publish on NPM. Use this OR skip_packages, not together.
description: Packages to publish (space separated)
type: string
skip_packages:
description: Space separated list of packages to NOT publish on NPM. Use this OR only_packages, not together.
description: Packages to NOT publish (space separated)
type: string
tags:
description: Space separated list of tags to tag the release with on NPM
description: NPM tags (space separated)
type: string
default: "['untagged']"
default: untagged
dry:
required: true
description: Don't actually publish, just run a dry run
description: Dry run instead of publish?
type: boolean
default: true
force_notify:
description: Force a Discord notification
description: Force a Discord notification?
type: boolean
default: false
@ -52,8 +52,8 @@ jobs:
embed-author-icon-url: ${{ github.event.sender.avatar_url }}
embed-title: '⚠️ Publishing release from NPM'
embed-description: |
```
inputs: ${{ toJson(inputs) }}
```json
${{ toJson(inputs) }}
```
embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }}
@ -80,12 +80,44 @@ jobs:
working-directory: scripts/release
- run: cp ./scripts/release/ci-npmrc ~/.npmrc
- if: '${{ inputs.only_packages }}'
name: 'Prepare and publish ${{ inputs.only_packages }}'
run: |
scripts/release/prepare-release-from-npm.js --skipTests --version=${{ inputs.version_to_promote }} --onlyPackages=${{ inputs.only_packages }}
echo -e "===== Preparing release from NPM =====\n"
scripts/release/prepare-release-from-npm.js \
--ci \
--skipTests \
--version=${{ inputs.version_to_promote }} \
--publishVersion=${{ inputs.version_to_publish }} \
--onlyPackages=${{ inputs.only_packages }}
echo -e "\n\n===== Check prepared files =====\n"
ls -R build/node_modules
# scripts/release/publish.js --ci --tags=${{ inputs.tags }} --publishVersion=${{ inputs.version_to_publish }} --onlyPackages=${{ inputs.only_packages }} --dry=${{ inputs.dry || 'false' }}
echo -e "\n\n===== Publishing to NPM =====\n"
scripts/release/publish.js \
--ci \
--tags=${{ inputs.tags }} \
--publishVersion=${{ inputs.version_to_publish }} \
--onlyPackages=${{ inputs.only_packages }} \
--dry=${{ inputs.dry }}
- if: '${{ inputs.skip_packages }}'
name: 'Prepare and publish all packages EXCEPT ${{ inputs.skip_packages }}'
run: |
scripts/release/prepare-release-from-npm.js --skipTests --version=${{ inputs.version_to_promote }} --skipPackages=${{ inputs.skip_packages }}
echo -e "===== Preparing release from NPM =====\n"
scripts/release/prepare-release-from-npm.js \
--ci \
--skipTests \
--version=${{ inputs.version_to_promote }} \
--publishVersion=${{ inputs.version_to_publish }} \
--skipPackages=${{ inputs.skip_packages }}
echo -e "\n\n===== Check prepared files =====\n"
ls -R build/node_modules
# scripts/release/publish.js --ci --tags=${{ inputs.tags }} --publishVersion=${{ inputs.version_to_publish }} --skipPackages=${{ inputs.skip_packages }} --dry=${{ inputs.dry || 'false' }}
echo -e "\n\n===== Publishing to NPM =====\n"
scripts/release/publish.js \
--ci \
--tags=${{ inputs.tags }} \
--publishVersion=${{ inputs.version_to_publish }} \
--skipPackages=${{ inputs.skip_packages }} \
--dry=${{ inputs.dry }}

View File

@ -7,7 +7,7 @@ const semver = require('semver');
const theme = require('../theme');
const {confirm} = require('../utils');
const run = async ({skipPackages}, versionsMap) => {
const run = async ({ci, skipPackages}, versionsMap) => {
const groupedVersionsMap = new Map();
// Group packages with the same source versions.
@ -22,7 +22,8 @@ const run = async ({skipPackages}, versionsMap) => {
}
});
// Prompt user to confirm or override each version group.
if (ci !== true) {
// Prompt user to confirm or override each version group if not running in CI.
const entries = [...groupedVersionsMap.entries()];
for (let i = 0; i < entries.length; i++) {
const [bestGuessVersion, packages] = entries[i];
@ -62,6 +63,7 @@ const run = async ({skipPackages}, versionsMap) => {
i--;
}
}
}
};
// Run this directly because it's fast,

View File

@ -5,7 +5,10 @@
const semver = require('semver');
const {execRead, logPromise} = require('../utils');
const run = async ({cwd, packages, skipPackages}, versionsMap) => {
const run = async (
{cwd, packages, skipPackages, ci, publishVersion},
versionsMap
) => {
const branch = await execRead('git branch | grep \\* | cut -d " " -f2', {
cwd,
});
@ -13,6 +16,16 @@ const run = async ({cwd, packages, skipPackages}, versionsMap) => {
for (let i = 0; i < packages.length; i++) {
const packageName = packages[i];
if (ci === true) {
if (publishVersion != null) {
versionsMap.set(packageName, publishVersion);
} else {
console.error(
'When running in CI mode, a publishVersion must be supplied'
);
process.exit(1);
}
} else {
try {
// In case local package JSONs are outdated,
// guess the next version based on the latest NPM release.
@ -39,6 +52,7 @@ const run = async ({cwd, packages, skipPackages}, versionsMap) => {
versionsMap.set(packageName, null);
}
}
}
};
module.exports = async (params, versionsMap) => {

View File

@ -39,6 +39,17 @@ const paramDefinitions = [
description:
'Version of published "next" release (e.g. 0.0.0-0e526bcec-20210202)',
},
{
name: 'publishVersion',
type: String,
description: 'Version to publish',
},
{
name: 'ci',
type: Boolean,
description: 'Run in automated environment, without interactive prompts.',
defaultValue: false,
},
];
module.exports = () => {

View File

@ -9,7 +9,7 @@ const {join, relative} = require('path');
const {confirm, execRead, printDiff} = require('../utils');
const theme = require('../theme');
const run = async ({cwd, packages, version}, versionsMap) => {
const run = async ({cwd, packages, version, ci}, versionsMap) => {
const nodeModulesPath = join(cwd, 'build/node_modules');
// Cache all package JSONs for easy lookup below.
@ -107,7 +107,9 @@ const run = async ({cwd, packages, version}, versionsMap) => {
printDependencies(packageJSON.dependencies, 'dependency');
printDependencies(packageJSON.peerDependencies, 'peer');
}
if (ci !== true) {
await confirm('Do the versions above look correct?');
}
clear();
@ -167,7 +169,9 @@ const run = async ({cwd, packages, version}, versionsMap) => {
console.log(
theme`A full diff is available at {path ${relative(cwd, diffPath)}}.`
);
if (ci !== true) {
await confirm('Do the changes above look correct?');
}
} else {
console.log(
theme`Skipping React renderer version update because React is not included in the release.`

View File

@ -26,6 +26,13 @@ const run = async () => {
params.version = await getLatestNextVersion();
}
if (params.onlyPackages.length > 0 && params.skipPackages.length > 0) {
console.error(
'--onlyPackages and --skipPackages cannot be used together'
);
process.exit(1);
}
params.packages = await getPublicPackages(isExperimental);
params.packages = params.packages.filter(packageName => {
if (params.onlyPackages.length > 0) {

View File

@ -38,6 +38,9 @@ const run = async ({cwd, packages, tags, ci}) => {
console.log(
theme`• {package ${packageName}} {version ${packageJSON.version}}`
);
if (ci) {
console.log(packageJSON);
}
}
if (!ci) {

View File

@ -27,7 +27,9 @@ const run = async ({cwd, dry, tags, ci}, packageName, otp) => {
await confirm('Is this expected?');
}
} else {
console.log(theme`{spinnerSuccess ✓} Publishing {package ${packageName}}`);
console.log(
theme`{spinnerSuccess ✓} Publishing {package ${packageName}}${dry ? ' (dry-run)' : ''}`
);
// Publish the package and tag it.
if (!dry) {

View File

@ -31,6 +31,13 @@ const run = async () => {
params.cwd = join(__dirname, '..', '..');
params.packages = await getPublicPackages(isExperimental);
if (params.onlyPackages.length > 0 && params.skipPackages.length > 0) {
console.error(
'--onlyPackages and --skipPackages cannot be used together'
);
process.exit(1);
}
if (params.onlyPackages.length > 0) {
params.packages = params.packages.filter(packageName => {
return params.onlyPackages.includes(packageName);