Skip to content

Skip ADO feed 403 'already contains' when re-publishing an existing version#4813

Merged
timotheeguerin merged 12 commits into
mainfrom
timotheeguerin/ado-feed-skip-already-contains
Jul 3, 2026
Merged

Skip ADO feed 403 'already contains' when re-publishing an existing version#4813
timotheeguerin merged 12 commits into
mainfrom
timotheeguerin/ado-feed-skip-already-contains

Conversation

@timotheeguerin

Copy link
Copy Markdown
Member

Problem

The ADO azure-sdk-for-js feed publish step (added in #4807) fails when a package version already exists in the feed:

npm http fetch PUT 403 .../@azure-tools%2fazure-http-specs
HttpErrorGeneral: 403 Forbidden - The feed 'azure-sdk-for-js' already contains file
'azure-http-specs-0.1.0-alpha.43-dev.0.tgz' in package '@azure-tools/azure-http-specs 0.1.0-alpha.43-dev.0'.

Azure DevOps Artifacts npm feeds are immutable: re-publishing an already-existing version returns an HTTP 403 with an already contains file ... in package ... message, not the npm 409 / EPUBLISHCONFLICT that the skip logic currently matches. As a result a harmless re-publish fails the pipeline.

There is no npm flag (--force, --skip-existing) that bypasses feed immutability, so the 403 must be tolerated explicitly.

Change

Extend the "already published, treat as no-op" detection in ado-feed-release.yml to also match the ADO immutability message (already contains file, already contains ... in package). The match is intentionally specific — a bare 403 is not matched — so genuine auth/permission 403s still fail the job.

Notes

Azure DevOps npm feeds are immutable and reject re-publishing an existing version with an HTTP 403 'already contains file ... in package ...' message rather than the npm 409 / EPUBLISHCONFLICT. Match that specific phrase so a re-publish is treated as a no-op, while genuine auth/permission 403s still fail the job.
@azure-sdk-automation

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

⚡ Benchmark Results

⚠️ 10 metric(s) regressed above the +5% threshold:

Metric Baseline Current Change
resolver 🟢 36.5ms 🟢 41.0ms +12.4% 🔴
checker 🟡 333.0ms 🟡 350.1ms +5.1% 🔴
validation 🟢 78.4ms 🟢 86.2ms +9.9% 🔴
 ↳ validation/@typespec/http 🟡 13.8ms 🟡 15.0ms +8.0% 🔴
 ↳ validation/@typespec/versioning 🔴 48.0ms 🔴 53.4ms +11.4% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-child-resources 🟡 18.3ms 🟡 19.4ms +6.4% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 5.1ms 🟢 8.2ms +61.7% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🟡 15.1ms 🟡 16.2ms +7.3% 🔴
 ↳ emit/@typespec/openapi3 🟢 100.4ms 🟢 105.8ms +5.4% 🔴
 ↳ emit/@typespec/openapi3/compute 🟢 87.2ms 🟢 91.9ms +5.3% 🔴
Full details – comparing 177703a vs baseline rolling-baseline-1140c23-a3462c5 (rolling baseline (20 main runs))
Metric Baseline Current Change
total 🔴 934.1ms 🔴 969.3ms +3.8%
loader 🟡 281.0ms 🟡 287.1ms +2.2%
resolver 🟢 36.5ms 🟢 41.0ms +12.4% 🔴
checker 🟡 333.0ms 🟡 350.1ms +5.1% 🔴
validation 🟢 78.4ms 🟢 86.2ms +9.9% 🔴
 ↳ validation/@azure-tools/typespec-azure-core 🟡 11.4ms 🟡 11.9ms +4.2%
 ↳ validation/@typespec/http 🟡 13.8ms 🟡 15.0ms +8.0% 🔴
 ↳ validation/@typespec/rest 🟢 1.5ms 🟢 1.8ms +20.3%
 ↳ validation/@typespec/versioning 🔴 48.0ms 🔴 53.4ms +11.4% 🔴
 ↳ validation/compiler 🟢 3.5ms 🟢 4.0ms +12.0%
linter 🟢 198.8ms 🟡 203.6ms +2.4%
 ↳ linter/@azure-tools/typespec-azure-core/auth-required 🟢 0.1ms 🟢 0.1ms +9.2%
 ↳ linter/@azure-tools/typespec-azure-core/bad-record-type 🟢 0.5ms 🟢 0.6ms +13.5%
 ↳ linter/@azure-tools/typespec-azure-core/byos 🟢 7.8ms 🟢 8.2ms +5.0%
 ↳ linter/@azure-tools/typespec-azure-core/casing-style 🟢 1.3ms 🟢 1.4ms +8.6%
 ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance 🟢 0.2ms 🟢 0.2ms +12.0%
 ↳ linter/@azure-tools/typespec-azure-core/documentation-required 🟢 1.8ms 🟢 1.9ms +9.7%
 ↳ linter/@azure-tools/typespec-azure-core/friendly-name 🟢 1.3ms 🟢 1.4ms +7.1%
 ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required 🟢 0.3ms 🟢 0.4ms +7.1%
 ↳ linter/@azure-tools/typespec-azure-core/known-encoding 🟢 0.4ms 🟢 0.5ms +4.4%
 ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required 🟢 0.7ms 🟢 0.8ms +10.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch 🟢 0.6ms 🟢 0.7ms +7.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union 🟢 0.9ms 🟢 1.0ms +14.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-enum 🟢 0.2ms 🟢 0.2ms +12.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes 🟢 0.3ms 🟢 0.3ms +10.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops 🟢 0.2ms 🟢 0.2ms +6.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-format 🟢 0.8ms 🟢 0.8ms +4.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric 🟢 0.8ms 🟢 0.9ms +11.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🔴 24.6ms 🔴 24.3ms -1.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage 🟢 1.8ms 🟢 2.0ms +9.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator 🟢 0.2ms 🟢 0.2ms +5.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-nullable 🟢 0.4ms 🟢 0.4ms +4.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime 🟢 1.8ms 🟢 1.9ms +4.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-openapi 🟢 2.2ms 🟢 2.3ms +3.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-private-usage 🟢 2.9ms 🟢 3.1ms +9.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🔴 25.9ms 🔴 25.6ms -1.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🔴 31.1ms 🔴 31.9ms +2.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟢 0.1ms 🟢 0.1ms +12.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🟢 7.1ms 🟢 7.1ms -0.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params 🟢 0.4ms 🟢 0.4ms +6.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator 🟢 0.1ms 🟢 0.1ms +8.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-unknown 🟢 0.3ms 🟢 0.3ms +2.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union 🟢 0.7ms 🟢 0.8ms +9.4%
 ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version 🟢 0.3ms 🟢 0.4ms +13.2%
 ↳ linter/@azure-tools/typespec-azure-core/request-body-problem 🟢 0.4ms 🟢 0.5ms +6.4%
 ↳ linter/@azure-tools/typespec-azure-core/require-versioned 🟢 0.1ms 🟢 0.1ms +11.2%
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 30.3ms 🔴 31.0ms +2.4%
 ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body 🟢 0.6ms 🟢 0.7ms +5.3%
 ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model 🟢 0.4ms 🟢 0.4ms +4.6%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-names 🟢 7.1ms 🟢 7.2ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-operations 🟢 0.2ms 🟢 0.3ms +14.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-child-resources 🟡 18.3ms 🟡 19.4ms +6.4% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-lifecycle-operations 🟢 0.2ms 🟢 0.2ms +6.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🟡 10.8ms 🟡 11.3ms +5.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key 🟢 0.2ms 🟢 0.2ms -0.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage 🟢 0.1ms 🟢 0.1ms +3.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 5.1ms 🟢 8.2ms +61.7% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🟡 15.1ms 🟡 16.2ms +7.3% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 0.6ms 🟢 0.6ms +3.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes 🟢 1.3ms 🟢 1.3ms +3.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes 🟢 0.2ms 🟢 0.2ms +20.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment 🟢 0.4ms 🟢 0.4ms +4.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property 🟢 0.3ms 🟢 0.3ms +4.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator 🟢 0.1ms 🟢 0.1ms +12.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb 🟢 0.1ms 🟢 0.2ms +7.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property 🟢 0.2ms 🟢 0.2ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format 🟢 0.2ms 🟢 0.2ms +8.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars 🟢 0.4ms 🟢 0.4ms +2.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern 🟢 0.1ms 🟢 0.1ms +7.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation 🟢 0.5ms 🟢 0.5ms +4.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 8.2ms 🟢 8.4ms +3.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch 🟢 0.8ms 🟢 0.8ms +8.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars 🟢 0.4ms 🟢 0.4ms +4.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state 🟢 0.4ms 🟢 0.4ms +7.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels 🟢 0.2ms 🟢 0.2ms +4.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties 🟢 0.4ms 🟢 0.4ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation 🟢 0.1ms 🟢 0.1ms +6.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🟡 18.1ms 🟡 17.7ms -2.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint 🟢 0.1ms 🟢 0.1ms +5.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers 🟢 0.9ms 🟢 1.0ms +11.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model 🟢 0.2ms 🟢 0.2ms +1.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-override-props 🟢 0.3ms 🟢 0.3ms +10.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation 🟢 0.4ms 🟢 0.4ms -0.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 27.5ms 🔴 27.0ms -1.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope 🟢 0.4ms 🟢 0.4ms +4.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name 🟢 0.4ms 🟢 0.4ms +3.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop 🟢 4.9ms 🟢 5.4ms +10.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type 🟢 0.6ms 🟢 0.7ms +5.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/version-progression 🟢 0.3ms 🟢 0.3ms +13.3%
 ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict 🟢 2.1ms 🟢 2.2ms +6.4%
 ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix 🟢 1.4ms 🟢 1.6ms +14.5%
emit 🔴 5.80s 🔴 5.86s +0.9%
 ↳ emit/@Azure-Tools 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@azure-tools/typespec-autorest 🟢 116.0ms 🟢 121.0ms +4.4%
 ↳ emit/@azure-tools/typespec-python 🔴 2.18s 🔴 2.18s +0.1%
 ↳ emit/@typespec 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@typespec/http-client-js 🔴 539.1ms 🔴 557.4ms +3.4%
 ↳ emit/@typespec/openapi3 🟢 100.4ms 🟢 105.8ms +5.4% 🔴
 ↳ emit/@typespec/openapi3/compute 🟢 87.2ms 🟢 91.9ms +5.3% 🔴
 ↳ emit/@typespec/openapi3/write 🟢 12.9ms 🟢 13.6ms +5.2%

Averaged across 3 specs (azure-arm-resource-manager, azure-core-dataplane, azure-full).
Threshold: changes > ±5% are highlighted.
🟢 Fast · 🟡 Moderate (stages >200ms, rules >10ms) · 🔴 Slow (stages >400ms, rules >20ms)

@timotheeguerin timotheeguerin marked this pull request as ready for review July 3, 2026 15:48
github-actions Bot added 11 commits July 3, 2026 12:19
The feed also rejects a publish with a 403 'cannot be published to the feed because it exists in at least one of the feed's upstream sources' when the version is already available upstream (npmjs). Treat this as a no-op too.
The ADO 'pwsh' task runs with $ErrorActionPreference='Stop' and pwsh 7.4+ defaults $PSNativeCommandUseErrorActionPreference to $true, so a non-zero 'npm publish' exit (e.g. version already exists) threw a terminating error before the $LASTEXITCODE inspection, defeating the skip logic. Relax both so the skip check runs.
Use core's publish-npm-packages.ts (skips already-existing versions, fails on real errors) and bump the core submodule to pick it up. The deployment job now checks out sources (with submodules) and pins Node to run the TypeScript directly.
Do not merge: temporarily comments out non-essential build-for-publish steps (tests, python/ts e2e, coverage, bundler/manifest/playground uploads) to shorten publish-feed retry cycles.
1ES release jobs forbid 'checkout', so the shared Node script cannot run in the publish deployment job. Go back to inline pwsh and fix the real failure: a skipped 'npm publish' left a non-zero $LASTEXITCODE that leaked as the pwsh process exit code and failed the task. Capture the exit code immediately, classify the output, and exit 0 explicitly when there is no genuine error. Bump the core submodule to pick up the matching change.
The ADO PowerShell task appends 'exit $LASTEXITCODE' after the inline script (unless ignoreLASTEXITCODE is set). After a skipped 'npm publish' the leftover non-zero code fails the task even though we handled it. Reset $global:LASTEXITCODE explicitly (0 on success/skip, 1 on genuine error) plus our own exit. Bump core submodule to match.
Replace the inline pwsh publish with the shared publish-npm-packages.ts (from core) run by node. It classifies each package as published/skipped/failed (treating ADO feed immutability and existing-upstream 403s as skippable no-ops), emits Azure DevOps log groups with colored status, prints a summary, and controls its own exit code. 1ES release jobs forbid checkout, so the script is copied into the packages artifact at pack time and the release job downloads the whole artifact and runs it with a NodeTool-pinned Node. Bump core submodule to match.
Re-enables tests, python/ts e2e, coverage and the bundler/manifest/playground uploads that were temporarily commented out (6374f45) to speed up ADO-feed publish retries.
…feed-skip-already-contains

# Conflicts:
#	core
NodeTool@0 is deprecated; switch to UseNode@1 (input 'version' instead of 'versionSpec'). Keeps this template byte-identical with the core copy.
@timotheeguerin timotheeguerin merged commit 5554949 into main Jul 3, 2026
26 checks passed
@timotheeguerin timotheeguerin deleted the timotheeguerin/ado-feed-skip-already-contains branch July 3, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant