Skip to content

Commit 46aabca

Browse files
authored
Use ESRP release and private npm registry in publish build (#4192)
1 parent c2d181a commit 46aabca

17 files changed

Lines changed: 56729 additions & 196 deletions

File tree

.ado/azure-pipelines.publish.yml

Lines changed: 103 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ variables:
2020
- group: InfoSec-SecurityResults
2121
- name: tags
2222
value: production,externalfacing
23+
# Use the private registry mirror due to network restrictions (this is added to .npmrc in a step below)
24+
- name: REGISTRY_URL
25+
value: https://pkgs.dev.azure.com/office/_packaging/Office/npm/registry/
26+
- name: YARN_NPM_REGISTRY_SERVER
27+
value: $(REGISTRY_URL)
28+
- name: YARN_NPM_ALWAYS_AUTH
29+
value: 1
30+
# Enable yarn-plugin-npmrc
31+
- name: YARN_NPMRC_AUTH_ENABLED
32+
value: 1
33+
- name: packagesArtifactName
34+
value: packed-tarballs
35+
- name: releaseToolArtifactName
36+
value: release-api-tool
2337

2438
resources:
2539
repositories:
@@ -35,6 +49,8 @@ extends:
3549
name: Azure-Pipelines-1ESPT-ExDShared
3650
image: windows-latest
3751
os: windows
52+
settings:
53+
networkIsolationPolicy: AzureActiveDirectory,AzureKeyVault,AzureResourceManager,AzureStorage,GitHub
3854
sdl:
3955
eslint:
4056
configuration: 'recommended'
@@ -54,19 +70,36 @@ extends:
5470
name: Azure-Pipelines-1ESPT-ExDShared
5571
image: ubuntu-latest
5672
os: linux
73+
variables:
74+
# set in lage.config.mjs under BUILD_STAGINGDIRECTORY
75+
packagesArtifactPath: $(Build.StagingDirectory)/_packed
76+
releaseToolArtifactPath: $(Build.StagingDirectory)/${{ variables.releaseToolArtifactName }}
5777
templateContext:
78+
# run SDL tasks once on this directory for all outputs
79+
outputParentDirectory: $(Build.StagingDirectory)
5880
outputs:
5981
- output: pipelineArtifact
60-
targetPath: $(System.DefaultWorkingDirectory)/_packed
61-
artifactName: packed-tarballs
82+
targetPath: $(packagesArtifactPath)
83+
artifactName: ${{ variables.packagesArtifactName }}
84+
- output: pipelineArtifact
85+
targetPath: $(releaseToolArtifactPath)
86+
artifactName: ${{ variables.releaseToolArtifactName }}
6287
steps:
6388
- task: UseNode@1
6489
inputs:
6590
version: '22.x'
6691
displayName: 'Use Node.js 22.x'
6792

93+
- script: echo 'registry=$(REGISTRY_URL)' >> .npmrc
94+
displayName: 'Configure npm registry'
95+
96+
- task: npmAuthenticate@0
97+
inputs:
98+
workingFile: $(Build.SourcesDirectory)/.npmrc
99+
displayName: 'npm authenticate'
100+
68101
- script: |
69-
yarn
102+
yarn --immutable
70103
displayName: 'yarn install'
71104
72105
- script: |
@@ -75,75 +108,97 @@ extends:
75108
76109
- script: |
77110
yarn lage pack --verbose --grouped
78-
displayName: 'Pack all public packages'
111+
displayName: 'Pack public packages (new versions only)'
79112
80113
- script: |
81-
ls -la $(System.DefaultWorkingDirectory)/_packed/
114+
ls -laR '$(packagesArtifactPath)'
82115
displayName: 'List packed tarballs'
83116
117+
- script: |
118+
mkdir -p '$(releaseToolArtifactPath)'
119+
cp scripts/esrp-npm-release-temp/index.mjs '$(releaseToolArtifactPath)'
120+
displayName: 'Copy ESRP release tool'
121+
84122
- stage: Publish
85123
displayName: Publish to NPM
86124
dependsOn: Build
87-
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'), ne('${{ parameters.skipNpmPublish }}', 'true'))
125+
# TODO uncomment
126+
# condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'), ne('${{ parameters.skipNpmPublish }}', 'true'))
88127
jobs:
89128
- job: PublishPackages
90129
displayName: Publish NPM Packages
91130
pool:
92131
name: Azure-Pipelines-1ESPT-ExDShared
93132
image: ubuntu-latest
94133
os: linux
134+
variables:
135+
packagesArtifactPath: $(Agent.BuildDirectory)/${{ variables.packagesArtifactName }}
136+
releaseToolArtifactPath: $(Agent.BuildDirectory)/${{ variables.releaseToolArtifactName }}
137+
templateContext:
138+
type: releaseJob
139+
isProduction: true
140+
inputs:
141+
- input: pipelineArtifact
142+
artifactName: ${{ variables.packagesArtifactName }}
143+
targetPath: $(packagesArtifactPath)
144+
- input: pipelineArtifact
145+
artifactName: ${{ variables.releaseToolArtifactName }}
146+
targetPath: $(releaseToolArtifactPath)
95147
steps:
96148
- task: UseNode@1
97149
inputs:
98150
version: '22.x'
99151
displayName: 'Use Node.js 22.x'
100152

101-
- task: DownloadPipelineArtifact@2
102-
inputs:
103-
artifactName: packed-tarballs
104-
targetPath: $(System.DefaultWorkingDirectory)/_packed
105-
displayName: 'Download packed tarballs'
106-
107153
- script: |
108154
echo "Downloaded tarballs:"
109-
ls -la $(System.DefaultWorkingDirectory)/_packed/
110-
if ls $(System.DefaultWorkingDirectory)/_packed/*.tgz > /dev/null 2>&1; then
111-
echo "##vso[task.setvariable variable=hasTarballs]true"
155+
ls -laR '$(packagesArtifactPath)'
156+
if ls "$(packagesArtifactPath)/*/*.tgz" > /dev/null 2>&1; then
157+
echo "##vso[task.setvariable variable=hasTarballs]yes"
112158
else
113159
echo "No tarballs found — nothing to publish."
114-
echo "##vso[task.setvariable variable=hasTarballs]false"
160+
echo "##vso[task.setvariable variable=hasTarballs]no"
115161
fi
116162
displayName: 'Check downloaded tarballs'
117163
118-
- script: |
119-
yarn
120-
displayName: 'yarn install'
121-
condition: eq(variables['hasTarballs'], 'true')
122-
123-
- script: |
124-
yarn config set npmPublishAccess public
125-
yarn config set npmPublishRegistry "https://registry.npmjs.org"
126-
yarn config set npmAuthToken $(npmAuth)
127-
npm config set //registry.npmjs.org/:_authToken $(npmAuth)
128-
displayName: 'Configure npm publishing auth'
129-
condition: eq(variables['hasTarballs'], 'true')
130-
131-
- script: |
132-
# https://github.com/changesets/changesets/issues/432
133-
# We can't use `changeset publish` because it doesn't support workspaces, so we have to publish each package individually
134-
yarn lage publish --verbose --grouped --reporter azureDevops
135-
displayName: 'Publish NPM Packages'
136-
condition: eq(variables['hasTarballs'], 'true')
137-
138-
- script: |
139-
yarn config unset npmPublishAccess
140-
yarn config unset npmAuthToken
141-
yarn config unset npmPublishRegistry
142-
npm config delete //registry.npmjs.org/:_authToken
143-
displayName: 'Cleanup npm publishing auth'
144-
condition: always()
145-
146-
- script: |
147-
git clean -dfx
148-
displayName: 'Clean up working directory'
149-
condition: always()
164+
- task: AzureCLI@2
165+
displayName: 'Get credentials for staging blob storage'
166+
condition: eq(variables['hasTarballs'], 'yes')
167+
inputs:
168+
azureSubscription: ogx-esrp-infra-bot
169+
scriptType: bash
170+
scriptLocation: inlineScript
171+
addSpnToEnvironment: true
172+
inlineScript: |
173+
echo "##vso[task.setvariable variable=STAGING_TENANT_ID]$tenantId"
174+
echo "##vso[task.setvariable variable=STAGING_CLIENT_ID]$servicePrincipalId"
175+
echo "##vso[task.setvariable variable=STAGING_ID_TOKEN;issecret=true]$idToken"
176+
177+
- task: AzureKeyVault@2
178+
displayName: 'Get ESRP certificates from Key Vault'
179+
condition: eq(variables['hasTarballs'], 'yes')
180+
inputs:
181+
azureSubscription: ESRP-JSHost3
182+
KeyVaultName: OGX-JSHost-KV
183+
SecretsFilter: OGX-JSHost-Auth4,OGX-JSHost-Sign3
184+
185+
# TODO uncomment
186+
# - script: node '$(releaseToolArtifactPath)/index.mjs'
187+
# displayName: 'Publish packages using ESRP Release API'
188+
# condition: eq(variables['hasTarballs'], 'yes')
189+
# retryCountOnTaskFailure: 3
190+
# env:
191+
# PACKED_PACKAGES_PATH: $(packagesArtifactPath)
192+
# ESRP_PRODUCT_NAME: fluentui-react-native
193+
# ESRP_NPM_TAG: latest
194+
# # TODO should be somebody else
195+
# ESRP_USER: elcraig@microsoft.com
196+
# ESRP_APPROVERS: dannyvv@microsoft.com
197+
# ESRP_TENANT_ID: cdc5aeea-15c5-4db6-b079-fcadd2505dc2
198+
# ESRP_CLIENT_ID: 0a35e01f-eadf-420a-a2bf-def002ba898d
199+
# ESRP_AUTH_CERT: $(OGX-JSHost-Auth4)
200+
# ESRP_REQUEST_SIGNING_CERT: $(OGX-JSHost-Sign3)
201+
# STAGING_STORAGE_ACCOUNT_NAME: ogxesrptempstorage
202+
# STAGING_CLIENT_ID: $(STAGING_CLIENT_ID)
203+
# STAGING_TENANT_ID: $(STAGING_TENANT_ID)
204+
# STAGING_ID_TOKEN: $(STAGING_ID_TOKEN)

.changeset/two-buttons-joke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@fluentui-react-native/dependency-profiles': patch
3+
---
4+
5+
Update `workspace-tools` to `^0.42.0`

.github/workflows/pr.yml

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ jobs:
334334
- name: List packed tarballs
335335
id: check
336336
run: |
337-
ls -la _packed/
338-
if ls _packed/*.tgz > /dev/null 2>&1; then
337+
ls -laR _packed/
338+
if ls _packed/*/*.tgz > /dev/null 2>&1; then
339339
echo "has-tarballs=true" >> $GITHUB_OUTPUT
340340
else
341341
echo "has-tarballs=false" >> $GITHUB_OUTPUT
@@ -348,33 +348,6 @@ jobs:
348348
name: packed-tarballs-dry-run
349349
path: _packed/
350350

351-
publish-dry-run:
352-
name: NPM Publish Dry Run — Publish
353-
runs-on: ubuntu-latest
354-
timeout-minutes: 60
355-
needs: publish-dry-run-pack
356-
if: needs.publish-dry-run-pack.outputs.has-tarballs == 'true'
357-
steps:
358-
- name: Checkout
359-
uses: actions/checkout@v6
360-
361-
- name: Set up toolchain
362-
uses: microsoft/react-native-test-app/.github/actions/setup-toolchain@5.2.3
363-
with:
364-
node-version: 22
365-
366-
- name: Install dependencies
367-
run: yarn
368-
369-
- name: Download packed tarballs
370-
uses: actions/download-artifact@v8
371-
with:
372-
name: packed-tarballs-dry-run
373-
path: _packed/
374-
375-
- name: Simulate publish
376-
run: yarn lage publish:dry-run --verbose --grouped
377-
378351
test-links:
379352
name: Test repo links
380353
runs-on: ubuntu-latest
@@ -407,7 +380,6 @@ jobs:
407380
- win32
408381
- check-changesets
409382
- publish-dry-run-pack
410-
- publish-dry-run
411383
- test-links
412384
steps:
413385
- name: Check for failures or cancellations

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ apps/*/.vscode/.react/
117117
!**/.yarn/sdks
118118
!**/.yarn/versions
119119

120+
# May contain credentials
121+
.npmrc
122+
120123
# Ccache
121124
.ccache
122125

.oxfmtrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"**/lib-commonjs/**",
1212
"**/dist/**",
1313
"packages/components/Callout/windows/FRNCallout/codegen/**",
14+
"**/esrp-npm-release-temp/**",
1415
"**/CHANGELOG.*",
1516
"**/CODE_OF_CONDUCT.md",
1617
"**/SECURITY.md",

.vscode/settings.json

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,19 @@
4040
"**/lib-amd": true
4141
},
4242

43-
"javascript.preferences.quoteStyle": "single",
44-
4543
"json.format.enable": false,
4644

47-
"typescript.preferences.quoteStyle": "single",
48-
"typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false,
49-
"typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,
45+
"js/ts.preferences.quoteStyle": "single",
46+
"js/ts.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false,
47+
"js/ts.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,
5048
// Points at the workspace's typescript package (7.0.2, native tsc). The
5149
// TypeScript 7 (native-preview) extension detects that this tsdk has no
5250
// tsserver.js and automatically runs it as a native LSP server.
53-
"typescript.tsdk": "./node_modules/typescript/lib",
51+
"js/ts.tsdk.path": "./node_modules/typescript/lib",
5452

5553
"search.exclude": {
5654
"**/node_modules": true,
55+
"**/.yarn": true,
5756
"**/lib": true,
5857
"**/lib-amd": true,
5958
"**/lib-commonjs": true,

0 commit comments

Comments
 (0)