Skip to content

Commit 92a1d5d

Browse files
authored
ci(publish): only pack tarballs that need to be published (#4051)
* ci(publish): only pack tarballs that need to be published * update publish dry run * fix env var * dont fail if no _packed * always make dir * Skip publish stage if nothing to publish
1 parent a665611 commit 92a1d5d

File tree

4 files changed

+68
-14
lines changed

4 files changed

+68
-14
lines changed

.ado/azure-pipelines.publish.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,19 @@ extends:
7878
displayName: 'Pack all public packages'
7979
8080
- script: |
81-
echo "Packed tarballs:"
8281
ls -la $(System.DefaultWorkingDirectory)/_packed/
82+
if ls $(System.DefaultWorkingDirectory)/_packed/*.tgz > /dev/null 2>&1; then
83+
echo "##vso[task.setvariable variable=hasTarballs;isOutput=true]true"
84+
else
85+
echo "##vso[task.setvariable variable=hasTarballs;isOutput=true]false"
86+
fi
87+
name: check
8388
displayName: 'List packed tarballs'
8489
8590
- stage: Publish
8691
displayName: Publish to NPM
8792
dependsOn: Build
88-
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'), not(${{ parameters.skipNpmPublish }}))
93+
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'), not(${{ parameters.skipNpmPublish }}), eq(stageDependencies.Build.BuildAndPack.outputs['check.hasTarballs'], 'true'))
8994
jobs:
9095
- job: PublishPackages
9196
displayName: Publish NPM Packages

.github/workflows/pr.yml

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,12 @@ jobs:
301301
- name: Validate changesets
302302
run: yarn change:check
303303

304-
publish-dry-run:
305-
name: NPM Publish Dry Run
304+
publish-dry-run-pack:
305+
name: NPM Publish Dry Run — Pack
306306
runs-on: ubuntu-latest
307307
timeout-minutes: 60
308+
outputs:
309+
has-tarballs: ${{ steps.check.outputs.has-tarballs }}
308310
steps:
309311
- name: Checkout
310312
uses: actions/checkout@v4
@@ -323,6 +325,47 @@ jobs:
323325
- name: Pack packages
324326
run: yarn lage pack --verbose --grouped
325327

328+
- name: List packed tarballs
329+
id: check
330+
run: |
331+
ls -la _packed/
332+
if ls _packed/*.tgz > /dev/null 2>&1; then
333+
echo "has-tarballs=true" >> $GITHUB_OUTPUT
334+
else
335+
echo "has-tarballs=false" >> $GITHUB_OUTPUT
336+
fi
337+
338+
- name: Upload packed tarballs
339+
if: steps.check.outputs.has-tarballs == 'true'
340+
uses: actions/upload-artifact@v4
341+
with:
342+
name: packed-tarballs-dry-run
343+
path: _packed/
344+
345+
publish-dry-run:
346+
name: NPM Publish Dry Run — Publish
347+
runs-on: ubuntu-latest
348+
timeout-minutes: 60
349+
needs: publish-dry-run-pack
350+
if: needs.publish-dry-run-pack.outputs.has-tarballs == 'true'
351+
steps:
352+
- name: Checkout
353+
uses: actions/checkout@v4
354+
355+
- name: Set up toolchain
356+
uses: microsoft/react-native-test-app/.github/actions/setup-toolchain@5.0.14
357+
with:
358+
node-version: 22
359+
360+
- name: Install dependencies
361+
run: yarn
362+
363+
- name: Download packed tarballs
364+
uses: actions/download-artifact@v4
365+
with:
366+
name: packed-tarballs-dry-run
367+
path: _packed/
368+
326369
- name: Simulate publish
327370
run: yarn lage publish-dry-run --verbose --grouped
328371

@@ -357,6 +400,7 @@ jobs:
357400
- windows
358401
- win32
359402
- check-changesets
403+
- publish-dry-run-pack
360404
- publish-dry-run
361405
- test-links
362406
steps:

scripts/src/worker/pack.mts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ export const run: WorkerRunnerFunction = async ({ target }) => {
2727
const stagingDir = resolve(outputDir);
2828
await fs.mkdirp(stagingDir);
2929

30+
// Skip if this version is already published
31+
const result = await $`npm view ${pkg.name}@${pkg.version} version`.nothrow().quiet();
32+
if (result.exitCode === 0) {
33+
console.log(`Skipping ${pkg.name}@${pkg.version} — already published`);
34+
return;
35+
}
36+
3037
// Build a safe filename: @fluentui-react-native/button@1.0.0 -> fluentui-react-native-button-1.0.0.tgz
3138
const safeName = (pkg.name as string).replace(/@/g, '').replace(/\//g, '-');
3239
const tgzFilename = `${safeName}-${pkg.version}.tgz`;

scripts/src/worker/publish.mts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,15 @@ export const run: WorkerRunnerFunction = async ({ target }) => {
3838

3939
const dryRun = target.options?.dryRun ?? false;
4040
const outputDir = target.options?.outputDir as string | undefined;
41-
42-
// If an outputDir is configured, look for a pre-packed tarball
4341
const tarball = outputDir ? await findTarball(pkg, outputDir) : undefined;
4442

45-
if (tarball) {
46-
// yarn npm publish doesn't support tarballs, so use npm directly
47-
const args = ['publish', tarball, '--access', 'public', ...(dryRun ? ['--dry-run'] : [])];
48-
await $({ cwd: target.cwd, verbose: true })`npm ${args}`;
49-
} else {
50-
// No tarball found — publish from source (local dev / dry-run)
51-
const args = ['--tolerate-republish', ...(dryRun ? ['--dry-run'] : [])];
52-
await $({ cwd: target.cwd, verbose: true })`yarn npm publish ${args}`;
43+
if (!tarball) {
44+
// No tarball means pack skipped this package (already published) — nothing to do
45+
console.log(`Skipping ${pkg.name}@${pkg.version} — no tarball found`);
46+
return;
5347
}
48+
49+
// yarn npm publish doesn't support tarballs, so use npm directly
50+
const args = ['publish', tarball, '--access', 'public', ...(dryRun ? ['--dry-run'] : [])];
51+
await $({ cwd: target.cwd, verbose: true })`npm ${args}`;
5452
};

0 commit comments

Comments
 (0)