Jens-G opened a new pull request, #3896:
URL: https://github.com/apache/thrift/pull/3896

   > **Stacked on [#3893](https://github.com/apache/thrift/pull/3893) 
(THRIFT-6310) → [#3894](https://github.com/apache/thrift/pull/3894) 
(THRIFT-6312).** It uses `check-portable-exe.ps1` from #3893. Review those 
first; this branch contains both.
   
   A .NET developer on Windows who wants the Thrift compiler has to find the 
download page, pick the right file and put it on `PATH` by hand. Every other 
build-time tool in that ecosystem comes from `dotnet tool install`, and can be 
pinned per repository in a `dotnet-tools.json` manifest so everyone building a 
project uses the same compiler version.
   
   ```shell
   dotnet tool install --global Apache.Thrift.Compiler
   thrift --version
   ```
   
   ## The package id
   
   Checked against nuget.org:
   
   | id | |
   |---|---|
   | `ApacheThrift` | the existing netstd runtime library — stays what it is |
   | `Apache.Thrift` | **not available.** Held by a third party and delisted. 
NuGet ids are permanent, so a delisted id cannot be reused. |
   | `Apache.Thrift.Compiler` | free, and follows the `Apache.Avro` / 
`Apache.Arrow` naming sibling ASF projects use |
   
   `Apache.*` is not a reserved prefix on nuget.org (`Apache.Avro`, 
`Apache.Arrow` and `ApacheThrift` are all unverified), so a push under this id 
will be accepted. Only `Apache.NMS*` and `Apache.Ignite*` are reserved, and 
neither covers it.
   
   ## Why there is a managed launcher
   
   A .NET tool package needs a managed entry point, and the payload is a native 
executable. So the package carries a small launcher that finds `thrift.exe` 
next to itself and hands over — arguments, standard streams and exit code all 
pass straight through.
   
   .NET 10 *can* name a native executable as the entry point directly, with no 
managed code (`ToolCommandRunner=executable`). I tested it: a package built 
that way **cannot be installed by the .NET 8 or .NET 9 SDK at all** — 
`unsupported runner 'executable'` — and the two MSBuild properties involved are 
undocumented. The launcher costs one 72 KB assembly and works on every 
supported SDK, so the package targets `net8.0`.
   
   ## Platforms
   
   The package carries the Windows compiler only, and NuGet installs a tool 
package on any platform without gating. So the launcher checks and says so, 
pointing at the download page, rather than failing to start a Windows 
executable. If the compiler is built for other platforms later, .NET 10's 
RID-specific tool packages turn this into an install-time refusal without 
changing the install command.
   
   ## Testing
   
   `dotnet-tool/test-dotnet-tool.ps1` looks inside the `.nupkg` and then 
**installs it into a throwaway directory and runs it**. Two things can go wrong 
with a tool package wrapping a native executable, and neither shows up before 
somebody installs it: the payload can be missing, and the layout can be such 
that the tool installs but does not run.
   
   18 checks: package layout, `DotnetToolSettings.xml` command name and entry 
point, nuspec id/version/`DotnetTool` package type/licence expression, exactly 
one copy of the payload, non-empty `LICENSE` and `NOTICE`, install, and run.
   
   It runs anywhere PowerShell and the .NET SDK do — I developed it against the 
real .NET 8 SDK on Linux, where it exercises the platform-guard path; on 
Windows it checks the compiler's actual output instead. It already earned its 
keep: it caught that `LICENSE`/`NOTICE` were **not** being packed by the `<None 
Pack="true">` items I first wrote, because a tool package is built from the 
*publish* output and does not use the ordinary pack file set. They now travel 
as content and land next to the executable, where the user actually gets them.
   
   ## Publishing
   
   `release: published`, not a pre-release — the gate `pypi.yml`, 
`release_rust.yml` and `release_ruby.yml` use. The workflow refuses to publish 
when the release tag and the version in `CMakeLists.txt` disagree, as 
`release_rust.yml` does for the crate.
   
   Because **a NuGet version can never be replaced**, the compiler is asserted 
self-contained *before* the package is built, not only afterwards in 
`cmake.yml`.
   
   Authentication is NuGet **trusted publishing** via `NuGet/login` (on the ASF 
allowlist), matching PyPI in `pypi.yml` and crates.io in `release_rust.yml` — 
no long-lived key is stored in the repo.
   
   ### What is needed before the first release
   
   - a trusted publishing policy on nuget.org for `apache/thrift`, the 
`.github/workflows/dotnet-tool.yml` workflow and the `release` environment;
   - a repository variable `NUGET_USER` naming the nuget.org account that owns 
it.
   
   Both are noted in `doc/ReleaseManagement.md`. If trusted publishing turns 
out not to be workable for a not-yet-existing package, swapping in an API-key 
secret is a three-line change — tell me and I will.
   
   ## Notes
   
   - `.gitignore` gains the tool project's `bin`/`obj`.
   - No version in the `.csproj`; it arrives on the command line, so 
`build/veralign.sh` gains nothing to keep in step.
   - Building without `-Compiler` fails loudly rather than producing a package 
with no compiler in it.
   - `zizmor` is clean on the new workflow.
   
   JIRA: [THRIFT-6313](https://issues.apache.org/jira/browse/THRIFT-6313)
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to