Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .ado/azure-pipelines.publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,19 @@ extends:
displayName: 'Pack all public packages'

- script: |
echo "Packed tarballs:"
ls -la $(System.DefaultWorkingDirectory)/_packed/
if ls $(System.DefaultWorkingDirectory)/_packed/*.tgz > /dev/null 2>&1; then
echo "##vso[task.setvariable variable=hasTarballs;isOutput=true]true"
else
echo "##vso[task.setvariable variable=hasTarballs;isOutput=true]false"
fi
name: check
displayName: 'List packed tarballs'

- stage: Publish
displayName: Publish to NPM
dependsOn: Build
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'), not(${{ parameters.skipNpmPublish }}))
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'), not(${{ parameters.skipNpmPublish }}), eq(stageDependencies.Build.BuildAndPack.outputs['check.hasTarballs'], 'true'))
jobs:
- job: PublishPackages
displayName: Publish NPM Packages
Expand Down
48 changes: 46 additions & 2 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,12 @@ jobs:
- name: Validate changesets
run: yarn change:check

publish-dry-run:
name: NPM Publish Dry Run
publish-dry-run-pack:
name: NPM Publish Dry Run — Pack
runs-on: ubuntu-latest
timeout-minutes: 60
outputs:
has-tarballs: ${{ steps.check.outputs.has-tarballs }}
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -323,6 +325,47 @@ jobs:
- name: Pack packages
run: yarn lage pack --verbose --grouped

- name: List packed tarballs
id: check
run: |
ls -la _packed/
if ls _packed/*.tgz > /dev/null 2>&1; then
echo "has-tarballs=true" >> $GITHUB_OUTPUT
else
echo "has-tarballs=false" >> $GITHUB_OUTPUT
fi

- name: Upload packed tarballs
if: steps.check.outputs.has-tarballs == 'true'
uses: actions/upload-artifact@v4
with:
name: packed-tarballs-dry-run
path: _packed/

publish-dry-run:
name: NPM Publish Dry Run — Publish
runs-on: ubuntu-latest
timeout-minutes: 60
needs: publish-dry-run-pack
if: needs.publish-dry-run-pack.outputs.has-tarballs == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up toolchain
uses: microsoft/react-native-test-app/.github/actions/setup-toolchain@5.0.14
with:
node-version: 22

- name: Install dependencies
run: yarn

- name: Download packed tarballs
uses: actions/download-artifact@v4
with:
name: packed-tarballs-dry-run
path: _packed/

- name: Simulate publish
run: yarn lage publish-dry-run --verbose --grouped

Expand Down Expand Up @@ -357,6 +400,7 @@ jobs:
- windows
- win32
- check-changesets
- publish-dry-run-pack
- publish-dry-run
- test-links
steps:
Expand Down
7 changes: 7 additions & 0 deletions scripts/src/worker/pack.mts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ export const run: WorkerRunnerFunction = async ({ target }) => {
const stagingDir = resolve(outputDir);
await fs.mkdirp(stagingDir);

// Skip if this version is already published
const result = await $`npm view ${pkg.name}@${pkg.version} version`.nothrow().quiet();
if (result.exitCode === 0) {
console.log(`Skipping ${pkg.name}@${pkg.version} — already published`);
return;
}

// Build a safe filename: @fluentui-react-native/button@1.0.0 -> fluentui-react-native-button-1.0.0.tgz
const safeName = (pkg.name as string).replace(/@/g, '').replace(/\//g, '-');
const tgzFilename = `${safeName}-${pkg.version}.tgz`;
Expand Down
18 changes: 8 additions & 10 deletions scripts/src/worker/publish.mts
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,15 @@ export const run: WorkerRunnerFunction = async ({ target }) => {

const dryRun = target.options?.dryRun ?? false;
const outputDir = target.options?.outputDir as string | undefined;

// If an outputDir is configured, look for a pre-packed tarball
const tarball = outputDir ? await findTarball(pkg, outputDir) : undefined;

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

// yarn npm publish doesn't support tarballs, so use npm directly
const args = ['publish', tarball, '--access', 'public', ...(dryRun ? ['--dry-run'] : [])];
await $({ cwd: target.cwd, verbose: true })`npm ${args}`;
};
Loading