Skip to content

fix: support AL 18 flat VSIX bin layout for marketplace/bc-artifact TFM detection - #7

Merged
Arthurvdv merged 2 commits into
mainfrom
fix/al18-flat-vsix-layout
Sep 9, 2026
Merged

Arthurvdv merged 2 commits into
mainfrom
fix/al18-flat-vsix-layout

Conversation

@Arthurvdv

Copy link
Copy Markdown
Member

Problem

detect-tfm marketplace prerelease (and ALCopsDownloadAnalyzers@1 with detectFrom: marketplace) fails on AL Language 18.0.2668733 with:

Entry not found in ZIP: extension/bin/Analyzers/Microsoft.Dynamics.Nav.CodeAnalysis.dll

The DLL is still bundled in the VSIX — it moved. Verified against the real artifacts:

Artifact Microsoft.Dynamics.Nav.CodeAnalysis.dll TFM
AL VSIX 17.0.2273547 extension/bin/Analyzers/ (+ copies under bin/win32|linux|darwin) net8.0
AL VSIX 18.0.2668733 extension/bin/ flat, no Analyzers/, no platform folders net10.0, framework-dependent
NuGet DevTools 18.0.40.43394-beta tools/net8.0/any/ and tools/net10.0/any/ both

So this is a path fix, not a TFM mismatch. src/types.ts hard-coded the legacy path, used by both the marketplace detector (remote HTTP-Range extraction) and detectTfmFromVsixBuffer (used by the bc-artifact VSIX fallbacks).

Fix

  • VSIX_DLL_PATH_CANDIDATES replaces the single constant: flat extension/bin/ first (AL 18+ / BC 29), legacy extension/bin/Analyzers/ second. The order is unambiguous — legacy VSIXs never place the DLL directly in extension/bin/. VSIX_DLL_PATH remains exported as a @deprecated alias for the legacy path, so the public API stays source-compatible.
  • extractRemoteZipFirstEntry(url, entryPaths, logger) (src/http-range.ts) and extractZipFirstEntryFromBuffer(zipBuffer, entryPaths, logger) (src/zip-local.ts): read the central directory once, probe candidates in order with exact path matching, return { buffer, entryPath }. On a miss they throw ... Probed: <a>, <b>. The existing single-path functions keep their current behaviour and error messages (including the basename fallback) and now share the central-directory helper.
  • detectTfmFromVsixBuffer and detectFromMarketplace use the candidate list and log which layout matched (flat (AL 18+) / legacy (AL <= 17)).
  • Actionable marketplace error when neither layout matches: names the version, lists the probed paths and points at --detect-from nuget-devtools / --tfm. Only a genuine layout miss is wrapped — transport failures (TLS, HTTP) propagate unchanged rather than being reported as a missing DLL.
  • src/detectors/bc-artifact.ts needed no change: its VSIX fallbacks go through detectTfmFromVsixBuffer.
  • New exports from src/index.ts: VSIX_DLL_PATH_CANDIDATES, describeVsixLayout, extractRemoteZipFirstEntry, extractZipFirstEntryFromBuffer.
  • README: the marketplace Features bullet notes both layouts, plus a short "AL 18 / BC 29 notes" subsection (net10.0 framework-dependent VSIX, DevTools multi-TFM with newest-preferred detection, compiler-path / --tfm when building with the net8.0 toolset).

Verification

npm run lint, npm run build and npm run bundle all pass.

npm test: 206 passed (17 files), up from 189 — 17 new tests, none weakened:

  • tests/shared/zip-local.test.ts and tests/shared/http-range.test.ts: flat-only, legacy-only, both-present (flat wins), neither (error lists both probed paths), and no basename fallback for candidate probing. The http-range suite serves a real fflate.zipSync ZIP over the mocked https layer and asserts the central-directory range is requested exactly once.
  • tests/shared/vsix-tfm.e2e.test.ts (new, unmocked): packs the real tests/fixtures/compiler-net80 CodeAnalysis DLL into both layouts and asserts net8.0 / assembly version 17.0.0.0 from each, plus the both-paths-probed error.
  • tests/detectors/marketplace.test.ts: updated to the candidate call shape, plus the actionable-error case (asserts it mentions nuget-devtools) and a case proving transport errors are not relabelled.

Manual smoke check against the live marketplace (node dist/cli.js):

$ node dist/cli.js detect-tfm marketplace prerelease
Querying VS Marketplace for AL Language extension...
Resolved extension version: 18.0.2668733 (pre-release)
Extracting CodeAnalysis DLL from VSIX...
Extracting first of 2 candidate entries from remote ZIP
Found CodeAnalysis DLL at 'extension/bin/Microsoft.Dynamics.Nav.CodeAnalysis.dll' (flat (AL 18+))
Reading target framework from CodeAnalysis DLL
Assembly version: 18.0.40.47373, TFM: net10.0
{
  "tfm": "net10.0",
  "source": "vs-marketplace",
  "details": "extensionVersion=18.0.2668733, assemblyVersion=18.0.40.47373",
  "extensionVersion": "18.0.2668733",
  "assemblyVersion": "18.0.40.47373"
}

$ node dist/cli.js detect-tfm marketplace 17.0.2273547
Querying VS Marketplace for AL Language extension...
Resolved extension version: 17.0.2273547
Extracting CodeAnalysis DLL from VSIX...
Extracting first of 2 candidate entries from remote ZIP
Found CodeAnalysis DLL at 'extension/bin/Analyzers/Microsoft.Dynamics.Nav.CodeAnalysis.dll' (legacy (AL <= 17))
Reading target framework from CodeAnalysis DLL
Assembly version: 17.0.34.45391, TFM: net8.0
{
  "tfm": "net8.0",
  "source": "vs-marketplace",
  "details": "extensionVersion=17.0.2273547, assemblyVersion=17.0.34.45391",
  "extensionVersion": "17.0.2273547",
  "assemblyVersion": "17.0.34.45391"
}

Both layouts resolve correctly against the real CDN artifacts.

Follow-ups (deliberately out of scope)

  • Normalise channel keywords across detectors (latest/preview router vs current/prerelease marketplace vs latest/prerelease ALCops version).
  • resolveDetectSource doc comment and README promise local-path → compiler-path routing that does not exist (src/resolve-detect-source.ts:16-23).
  • detectFromMarketplace reports source: 'vs-marketplace' while the DetectSource type says 'marketplace'.
  • An explicit runtime hint for multi-TFM DevTools packages, for pipelines that compile with the net8.0 toolset.

Refs ALCops/azure-devops-extension#47, ALCops/Analyzers discussion #442.

🤖 Generated with Claude Code

Arthurvdv and others added 2 commits September 9, 2026 11:18
…FM detection

AL Language 18.0.2668733 moved Microsoft.Dynamics.Nav.CodeAnalysis.dll from
extension/bin/Analyzers/ to a flat extension/bin/, which made
`detect-tfm marketplace prerelease` fail with
"Entry not found in ZIP: extension/bin/Analyzers/Microsoft.Dynamics.Nav.CodeAnalysis.dll".

Replace the single hard-coded VSIX path with VSIX_DLL_PATH_CANDIDATES and probe
the flat AL 18+ layout first, falling back to the legacy AL <= 17 path. The order
is unambiguous: legacy VSIXs never place the DLL directly in extension/bin/.

- add extractRemoteZipFirstEntry / extractZipFirstEntryFromBuffer, which read the
  central directory once and return the first matching candidate plus its path
- marketplace detection reports an actionable error when no candidate matches,
  pointing at --detect-from nuget-devtools / --tfm; transport failures still
  surface as themselves
- bc-artifact detection is fixed implicitly via detectTfmFromVsixBuffer
- VSIX_DLL_PATH stays exported as a deprecated alias for the legacy path

Refs: ALCops/azure-devops-extension#47
Refs: ALCops/Analyzers#442

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The layout details are already covered in the "AL 18 / BC 29 notes" section.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Arthurvdv
Arthurvdv merged commit aeb4e86 into main Sep 9, 2026
2 checks passed
@Arthurvdv
Arthurvdv deleted the fix/al18-flat-vsix-layout branch September 9, 2026 10:09
Arthurvdv added a commit that referenced this pull request Sep 9, 2026
First release with the download command (#3) and the AL 18 flat VSIX
layout fix (#7). Bumps the minor version so GitVersion publishes 0.2.0
instead of 0.1.3.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant