Skip to content

feat: npm distribution#29

Merged
dsherret merged 1 commit into
mainfrom
npm-distribution-and-gagen
May 23, 2026
Merged

feat: npm distribution#29
dsherret merged 1 commit into
mainfrom
npm-distribution-and-gagen

Conversation

@dsherret

Copy link
Copy Markdown
Member

Summary

Two changes bundled together because the npm publish steps land naturally on top of the gagen-generated workflow:

1. Convert ci.yml to gagen (ci.ts + ci.generated.yml)

Single-job structure preserved — still runs everything on macos-14 so dotnet can cross-compile every target. ci.ts has a #!/usr/bin/env -S deno run -A shebang and is 100755 in git so it can be invoked directly; the workflow lint step (./.github/workflows/ci.ts --lint) is wired in.

2. Publish an npm distribution of the plugin

Adds three scripts and the corresponding workflow steps so a tag push publishes @dprint/roslyn (main) plus seven per-platform sub-packages alongside the existing GitHub release.

  • scripts/create_npm_packages.ts — extracts each platform zip and uses the new packageContents option in @dprint/automation@0.11.3 to ship the whole directory as the per-platform sub-package. Necessary because roslyn is a self-contained .NET app — the executable references ~200 sibling DLLs and runtime files. Produces npm-dist/publish-manifest.json with the main tarball's sha256.
  • scripts/publish_npm_packages.ts — reads the manifest, publishes sub-package tarballs first (so the main's optionalDependencies resolve) then the main. Uses --access public --provenance. Publishes the tarballs directly so npm uploads the exact bytes whose sha256 is in the main plugin.json.
  • scripts/generate_release_notes.ts — bumped to @dprint/automation@0.11.3. When the manifest is present, appends an "Alternatively, run dprint config add npm:@dprint/roslyn" block under step 1, matching the existing prose style.

draft_release in ci.ts gets permissions: { contents: write, "id-token": write } so npm publish --provenance can do the OIDC handshake.

npm package layout

Matches the convention already in use by @dprint/exec:

  • Main: @dprint/roslyn
  • Per-platform sub-packages: @dprint/roslyn-<os>-<arch>[-<libc>], e.g. @dprint/roslyn-linux-x64-glibc, @dprint/roslyn-darwin-arm64, @dprint/roslyn-win32-x64. Each carries os/cpu/libc filters so npm only installs the matching one.

Test plan

  • deno run -A .github/workflows/ci.ts --lint passes (idempotent generation).
  • deno check clean on all four scripts and on ci.ts.
  • End-to-end smoke via a manual bootstrap publish (outside this branch): extracted the actual 0.20.1 release zips, ran create_npm_packages.ts in WSL, inspected the resulting tarballs — 206 entries each (205 .NET files + package.json), executable mode is 0o755, all DLLs and runtimes/ files end up alongside the binary, and the sha256 of each tarball equals the per-platform checksum written into the main plugin.json.
  • First-publish chicken-and-egg. None of the seven @dprint/roslyn-* sub-packages exist on npm yet, so npm trusted publishing can't be configured on them ahead of time. The first version needs to be published manually with a regular token; after that, configure the GitHub repo as trusted publisher on each package and subsequent tag-driven publishes go through OIDC.

Pre-merge notes

  • The pre-existing README.md modification on main is unrelated and not part of this PR.
  • Bumps @dprint/automation from 0.10.3 to 0.11.3 (latest) in create_plugin_file.ts-adjacent scripts. The existing create_plugin_file.ts is left on 0.10.3 since nothing requires it to be on the newer version — happy to bump it for consistency if you'd like.

- ci.yml -> ci.ts (gagen). Single-job structure preserved (still runs
  everything on macos-14 with dotnet cross-compile). ci.ts has a
  shebang and is +x in git so it can be invoked directly. The lint
  workflow check (`./.github/workflows/ci.ts --lint`) is wired in.
- Add scripts/create_npm_packages.ts: extracts each platform zip and
  ships the whole directory as the per-platform sub-package
  (`packageContents` — needed because roslyn is a self-contained .NET
  app where the executable references ~200 sibling DLLs and runtime
  files). Produces npm-dist/publish-manifest.json with the main
  tarball's sha256.
- Add scripts/publish_npm_packages.ts: reads the manifest, publishes
  sub-package tarballs first (so the main's optionalDependencies
  resolve), then the main. Uses --access public --provenance.
- Update scripts/generate_release_notes.ts: bump to
  @dprint/automation@0.11.3 and, when the manifest is present, append
  an "Alternatively, run `dprint config add npm:@dprint/roslyn`" block
  under step 1.
- draft_release in ci.ts has permissions: contents: write,
  id-token: write so npm publish --provenance can do the OIDC
  handshake when trusted publishing is configured.

npm package layout for @dprint/roslyn (matching the convention used
by other dprint plugins):
- main package: @dprint/roslyn
- per-platform sub-packages: @dprint/roslyn-<os>-<arch>[-<libc>]
  (e.g. @dprint/roslyn-linux-x64-glibc, @dprint/roslyn-darwin-arm64)

Worth noting for the first publish: the seven sub-packages don't
exist on npm yet, so npm trusted publishing can't be configured on
them ahead of time (chicken-and-egg). The first version needs to be
published manually with a regular token; afterward you can add the
GitHub repo as the trusted publisher for each package and CI will
take over via OIDC on subsequent tags.
@dsherret dsherret changed the title feat: gagen-based workflow and npm distribution feat: npm distribution May 23, 2026
@dsherret dsherret merged commit d4a65dc into main May 23, 2026
1 check passed
@dsherret dsherret deleted the npm-distribution-and-gagen branch May 23, 2026 19:42
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