Skip to content

Commit 9ea203f

Browse files
authored
ci: convert publish-if-needed script back to plain node (#4017)
1 parent b89fcfc commit 9ea203f

File tree

4 files changed

+58
-33
lines changed

4 files changed

+58
-33
lines changed

.ado/azure-pipelines.publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ extends:
8484
# https://github.com/changesets/changesets/issues/432
8585
# We can't use `changeset publish` because it doesn't support workspaces, so we have to publish each package individually
8686
yarn workspaces foreach --all --topological --no-private \
87-
exec zx $(Build.SourcesDirectory)/.github/scripts/publish-package-if-needed.mts
87+
exec node $(Build.SourcesDirectory)/.github/scripts/publish-package-if-needed.mts
8888
displayName: 'Publish NPM Packages'
8989
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'), not(${{ parameters.skipNpmPublish }}))
9090
Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,64 @@
1-
#!/usr/bin/env zx
2-
import 'zx/globals';
1+
#!/usr/bin/env node
2+
import { readFileSync } from 'node:fs';
3+
import { spawnSync } from 'node:child_process';
34

4-
// Type declaration for process (zx doesn't include Node.js types)
5-
declare const process: {
6-
env: Record<string, string | undefined>;
7-
cwd: () => string;
8-
argv: string[];
9-
exit: (code: number) => never;
10-
};
5+
interface PackageJson {
6+
name: string;
7+
version: string;
8+
private?: boolean;
9+
}
1110

1211
/**
1312
* Publish a single package to npm if needed
1413
*
1514
* This script:
1615
* - Operates on the current workspace directory
17-
* - Checks npm registry before publishing
16+
* - Checks npm registry before publishing (idempotent - safe to retry)
17+
* - Requires yarn npm authentication to be configured (npmAuthToken)
1818
* - Skips private packages automatically
1919
*
2020
* Usage:
2121
* # In a workspace directory:
22-
* npx zx publish-package-if-needed.mts # Publish for real
23-
* npx zx publish-package-if-needed.mts --dry-run # Simulate publishing
22+
* node publish-package-if-needed.mts # Publish for real
23+
* node publish-package-if-needed.mts --dry-run # Simulate publishing
2424
*
2525
* # For all workspaces in topological order:
2626
* yarn workspaces foreach --all --topological --no-private \
27-
* exec npx zx .github/scripts/publish-package-if-needed.mts
27+
* exec node .github/scripts/publish-package-if-needed.mts
2828
*/
2929

30-
// Parse command line arguments
3130
const isDryRun = process.argv.includes('--dry-run');
3231

33-
// Read package.json from current directory
34-
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
32+
const packageJson: PackageJson = JSON.parse(readFileSync('package.json', 'utf-8'));
3533
const { name, version, private: isPrivate } = packageJson;
3634

37-
// Skip private packages
3835
if (isPrivate) {
39-
echo(`⊘ Skipping private package: ${name}`);
36+
console.log(`⊘ Skipping private package: ${name}`);
4037
process.exit(0);
4138
}
4239

4340
// Check if package@version already exists on npm
44-
const result = await $`npm view ${name}@${version} version 2>&1`.nothrow().quiet();
45-
const shouldPublish = result.exitCode !== 0 || result.stdout.trim() !== version;
41+
const checkResult = spawnSync('npm', ['view', `${name}@${version}`, 'version'], {
42+
encoding: 'utf-8',
43+
stdio: 'pipe',
44+
});
45+
const alreadyPublished = checkResult.status === 0 && checkResult.stdout.trim() === version;
4646

47-
if (!shouldPublish) {
48-
echo(`✓ Already published: ${name}@${version}`);
47+
if (alreadyPublished) {
48+
console.log(`✓ Already published: ${name}@${version}`);
4949
process.exit(0);
5050
}
5151

52-
// Publish the package
5352
const startMsg = isDryRun ? 'Simulating publish' : 'Publishing';
5453
const endMsg = isDryRun ? 'Dry-run successful for' : 'Successfully published';
5554

56-
echo(`→ ${startMsg}: ${name}@${version}`);
55+
console.log(`→ ${startMsg}: ${name}@${version}`);
5756

58-
const publishCmd = isDryRun
59-
? $`yarn npm publish --access public --dry-run`
60-
: $`yarn npm publish --access public`;
57+
const publishArgs = ['npm', 'publish', '--access', 'public'];
58+
if (isDryRun) publishArgs.push('--dry-run');
6159

62-
await publishCmd;
63-
echo(`✓ ${endMsg}: ${name}@${version}`);
60+
const publishResult = spawnSync('yarn', publishArgs, { stdio: 'inherit' });
61+
if (publishResult.status !== 0) {
62+
process.exit(publishResult.status ?? 1);
63+
}
64+
console.log(`✓ ${endMsg}: ${name}@${version}`);

.github/workflows/changesets-version.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ jobs:
3232
with:
3333
app-id: ${{ vars.APP_ID }}
3434
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
35-
permissions: |
36-
contents: write
37-
pull-requests: write
35+
permission-contents: write # for GH releases and Git tags (Changesets)
36+
permission-pull-requests: write # version PRs (Changesets)
3837

3938
- name: Create Version Bump PR
4039
id: changesets

.github/workflows/pr.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,30 @@ jobs:
305305
- name: Validate changesets
306306
run: yarn changeset:validate
307307

308+
publish-dry-run:
309+
name: NPM Publish Dry Run
310+
runs-on: ubuntu-latest
311+
timeout-minutes: 60
312+
steps:
313+
- name: Checkout
314+
uses: actions/checkout@v4
315+
316+
- name: Set up toolchain
317+
uses: microsoft/react-native-test-app/.github/actions/setup-toolchain@5.0.14
318+
with:
319+
node-version: 22
320+
321+
- name: Install dependencies
322+
run: yarn
323+
324+
- name: Build packages
325+
run: yarn build
326+
327+
- name: Simulate publish
328+
run: |
329+
yarn workspaces foreach --all --topological --no-private \
330+
exec node $(pwd)/.github/scripts/publish-package-if-needed.mts --dry-run
331+
308332
test-links:
309333
name: Test repo links
310334
runs-on: ubuntu-latest
@@ -336,6 +360,7 @@ jobs:
336360
- windows
337361
- win32
338362
- check-changesets
363+
- publish-dry-run
339364
- test-links
340365
steps:
341366
- name: All required jobs passed

0 commit comments

Comments
 (0)