Repo standardization + Shipwright NativeAOT release pipeline#17
Merged
Conversation
…uild The v0.12.0 release failed at the CI gate with FS0225: Types.Generated.fs is gitignored and rebuilt from Types.td, but the release gate + AOT build legs never regenerated it. Add a cross-platform scripts/generate-types.sh and a typeDiagram generate step to the gate, all 6 build legs, and publish-nuget so the F# build/ publish has the generated source on a fresh checkout.
…packaging Two release blockers found shipping v0.12.0: 1. NativeAOT binary fail-fasts (exit 139) on any host without ICU/libicu — e.g. a pristine ubuntu:24.04 — because the first log line formats a date via CurrentCulture. A binary that needs libicu pre-installed is not the zero-dependency native binary the deployment contract requires. Compile with InvariantGlobalization=true (correct + deterministic for an HTTP/protocol tool). Proven: linux-x64 AOT now runs --version + --version --json in bare ubuntu:24.04 with zero .NET runtime and zero ICU. 2. The win32-arm64 leg failed packaging its VSIX: @vscode/vsce-sign ships no win32-arm build, so `npm ci` aborts on a Windows-ARM runner. vsce packaging only zips the staged native binary + manifest (it never executes it), so move all per-platform VSIX packaging off the native runners into a single Linux matrix that consumes the uploaded raw binaries. Also kills the Windows EPERM npm flakiness. Each leg stamps the version, stages only its own platform, and verifies VSIX contents. Marketplace publish now fails fast with an actionable message if the VSCE_PAT secret is absent (instead of an opaque TF400813).
The extension's binary resolver (bundledBinaryPath / Shipwright) looks for the
bundled native CLI at bin/<process.platform>-<process.arch>/napper — the same
layout the shipped per-platform VSIX uses. But scripts/build-cli.sh staged it at
a FLAT bin/napper, so in local dev and the e2e test run the extension (and the
LSP it spawns) could not find the bundled binary. That surfaced as 6 failing
e2e tests: 3 OpenAPI "generate" tests calling execFile('') (the test's own
resolver returned the now-empty DEFAULT_CLI_PATH) and 3 "Copy as Curl" tests
whose LSP-backed command had no binary to spawn.
- build-cli.sh: stage the binary under bin/<node-platform>/napper (mapping the
.NET RID to the node platform-arch string, incl. linux-arm64), matching the
resolver and the real VSIX. Keep a flat bin/napper copy so the CI Shipwright
version-contract gate (which adds bin/ to PATH) still resolves `napper`.
- openApiImport.e2e.test.ts: resolve the CLI via the real bundledBinaryPath
instead of the empty DEFAULT_CLI_PATH, so the test exercises the deployed
resolution path ([SWR-IDE-RESOLUTION]) rather than a removed PATH fallback.
Proven locally: e2e goes 91→97 passing. The only remaining failure is
"downloadSpec follows redirects", which depends on httpbin.org (currently 503) —
an external outage, not a regression.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TLDR
Repo standardization plus a Shipwright-compliant release pipeline that ships
napperas a self-contained NativeAOT native binary (zero .NET runtime for end users) via GitHub Releases / Homebrew / Scoop and bundled inside a per-platform VSIX for all 6 targets, with build-time version stamping and a network-free release gate.Details
Deployment / release (Shipwright)
release.ymlrebuilt: tag-triggered → CI gate (lint + build + manifest validate + version-contract tests on0.0.0-devsource) → per-platform NativeAOT build on native runners (macos-15,macos-15-intel,ubuntu-latest,ubuntu-24.04-arm,windows-latest,windows-11-arm) → per-platform VSIX (vsce package --target) with content verification →package-cli(archives + per-archive.sha256+ combined checksums) → GitHub Release + Marketplace + Homebrew + Scoop. Downstream jobs useif: !cancelled() && needs.build.result != 'skipped'so one flaky leg can't block shipping the rest.dotnet publish --self-containedpath; the shipped artifact is the same NativeAOT binary the Makefile builds. A clean-room step proves the binary runs with no .NET runtime present (pristineubuntu:24.04container / empty env).0.0.0-dev; new first-class structured-parser stamperscripts/stamp-version.fsx(XDocument + System.Text.Json) rewritesDirectory.Build.props, the extensionpackage.json, andshipwright.json(product.version+ everyexpectedVersion) from the tag.make stamptarget added.shipwright.json:expectedVersion→0.0.0-dev;sourcescascade fixed touser-setting → env → bundled(dropped forbiddenpath/dotnet-toolstartup sources + thedotnetToolblock) per[SWR-IDE-RESOLUTION].dotnet toolNuGet kept as a secondary, non-blocking channel (publish-nuget,continue-on-error, not a dependency of any release job).schemas/shipwright.schema.json; CI + release validate the manifest with@nimblesite/shipwright-validate-manifest --schema.DEFAULT_CLI_PATHnow''to match thenapper.cliPathdefault sogetCliPath()falls through to the Shipwright-resolved bundled binary instead of returning an empty path.LSP / core / website: LSP protocol layer rebuilt (
Protocol.fs,Server.fs, wire/driver test harnesses),Types.tdtypeDiagram migration, website scripting docs.How Do The Automated Tests Prove It Works?
VersionContractTests.fs(4 black-box tests, all pass):napper --version→ exactlynapper 0.0.0-dev+ exit 0;--version --jsonconforms to the version-manifest schema; the stamper rewrites every carrier from a tag; dry-run is a no-op and bad input exits non-zero.shipwrightManifest.test.ts(4) +cliConfig.test.ts(DEFAULT_CLI_PATH matches napper.cliPath default) pass — 135 TS unit tests green.make package-vsixverified end-to-end locally: thenapper-darwin-arm64VSIX contains the real 9.5 MB Mach-O arm64 NativeAOT binary atextension/bin/darwin-arm64/napper+ the stampedshipwright.json(bin/darwin-arm64/napper: OK).-warnaserrorclean; Fantomas / ESLint / cargo-fmt clean.actionlintclean (runner labels valid).