Skip to content

Add GitHub Actions release workflow and CMake pre-built managed artifact support - #5

Draft
jpfeuffer with Copilot wants to merge 3 commits into
mainfrom
copilot/add-github-actions-release-workflow-again
Draft

Add GitHub Actions release workflow and CMake pre-built managed artifact support#5
jpfeuffer with Copilot wants to merge 3 commits into
mainfrom
copilot/add-github-actions-release-workflow-again

Conversation

Copilot AI commented Apr 28, 2026

Copy link
Copy Markdown

Downstream C++ consumers currently need a full .NET 8 SDK at build time solely to run dotnet publish for the managed shim. This PR pre-builds and publishes the managed output directory as GitHub Release artifacts and adds CMake options to consume them, so only the .NET 8 runtime is required at build/runtime.

Release workflow (.github/workflows/release.yml)

  • Triggers on v* tags; builds a 3-leg matrix (linux-x64, win-x64, osx-x64)
  • macOS leg uses the existing x64/Rosetta workaround (curl-install to ~/.dotnet-x64, --os osx -a x64)
  • Each leg downloads Thermo vendor .nupkg files, writes a local NuGet config, runs dotnet publish, and zips the output as openms-thermo-bridge-managed-<platform>-<version>.zip
  • A dependent publish-release job collects all three zips and creates the GitHub Release via softprops/action-gh-release@v2
  • actions/download-artifact pinned to v4.1.3 (fixes arbitrary file write CVE affecting >= 4.0.0, < 4.1.3)

New CMake options

OPENMS_THERMO_BRIDGE_PREBUILT_MANAGED_DIR (empty PATH, default off)
Point at an unpacked release artifact zip. Skips dotnet publish; validates that ThermoWrapperManaged.dll and ThermoWrapperManaged.runtimeconfig.json are present before proceeding.

cmake -S . -B build \
  -DOPENMS_THERMO_BRIDGE_PREBUILT_MANAGED_DIR=/path/to/unpacked/zip

OPENMS_THERMO_BRIDGE_DOWNLOAD_PREBUILT_MANAGED (BOOL, default OFF)
Auto-fetches the correct platform zip from GitHub Releases at configure time, extracts it into ${CMAKE_CURRENT_BINARY_DIR}/prebuilt-managed/, and uses it. Re-configure skips the download if the zip is already cached. Falls back with FATAL_ERROR if download fails and no SDK is available.

cmake -S . -B build \
  -DOPENMS_THERMO_BRIDGE_DOWNLOAD_PREBUILT_MANAGED=ON

On Apple Silicon both options always resolve to the osx-x64 artifact (Rosetta), consistent with the existing workaround. The add_dependencies / openms_thermo_bridge_copy_runtime_files build graph is unchanged in both paths.

Documentation (README.md)

  • New "Option 3: use pre-built managed DLLs" section covering both manual and auto-download workflows
  • Requirements updated: .NET 8 SDK not required when using pre-built artifacts
Original prompt

Goal

Pre-build and publish the managed C# output directory as GitHub Release artifacts so downstream C++ users only need CMake and a .NET runtime (not SDK) at build time.

Tasks

1. Add GitHub Actions release workflow (.github/workflows/release.yml)

  • Trigger on push to tags matching v*.
  • Build a matrix of three platform targets: ubuntu-latestlinux-x64, windows-latestwin-x64, macos-latestosx-x64 (using the existing arm64/Rosetta workaround so the artifact works on Apple Silicon via --os osx -a x64).
  • Each matrix leg:
    • Checks out the repo.
    • Installs .NET 8 SDK (macOS uses the existing x64 workaround: curl-install to ~/.dotnet-x64, set DOTNET_ROOT, DOTNET_ROOT_X64).
    • Runs dotnet publish ThermoWrapperManaged.csproj -c Release --nologo --self-contained false (macOS adds -r osx-x64) to produce the managed directory.
    • Zips the output as openms-thermo-bridge-managed-<platform>-<version>.zip.
  • The final step uses softprops/action-gh-release to create a GitHub Release and attach all three zips as assets.
  • Grants contents: write permission to the job.

2. Extend CMake with OPENMS_THERMO_BRIDGE_PREBUILT_MANAGED_DIR option

  • Add a new CMake cache variable OPENMS_THERMO_BRIDGE_PREBUILT_MANAGED_DIR (empty by default).
  • When set:
    • Skip the add_custom_command that runs dotnet publish.
    • Validate that ThermoWrapperManaged.dll and ThermoWrapperManaged.runtimeconfig.json exist in the given directory.
    • Set OPENMS_THERMO_BRIDGE_MANAGED_DIR to the provided path.
    • Emit a status message confirming the pre-built path is being used.
  • The existing add_dependencies(openms_thermo_bridge openms_thermo_bridge_managed) and openms_thermo_bridge_copy_runtime_files machinery already uses OPENMS_THERMO_BRIDGE_MANAGED_DIR, so everything downstream works unchanged.

3. Add OPENMS_THERMO_BRIDGE_DOWNLOAD_PREBUILT_MANAGED for auto-download

  • Add a boolean option OPENMS_THERMO_BRIDGE_DOWNLOAD_PREBUILT_MANAGED (default OFF).
  • When ON, CMake (using file(DOWNLOAD ...)) fetches the correct platform zip from the GitHub Releases API URL (parameterised by project version tag).
  • Extracts the zip into ${CMAKE_CURRENT_BINARY_DIR}/prebuilt-managed/ using cmake -E tar.
  • Sets OPENMS_THERMO_BRIDGE_PREBUILT_MANAGED_DIR to that extracted directory.
  • Falls back gracefully with a FATAL_ERROR message if the download fails and neither a local prebuilt nor a dotnet SDK is available.

4. macOS arm64 workaround for the pre-built artifact

  • In the release workflow, the macOS leg always uses the x64 workaround (dotnet publish --os osx -a x64), so the published zip is always osx-x64.
  • In CMake, when OPENMS_THERMO_BRIDGE_DOWNLOAD_PREBUILT_MANAGED=ON on Apple Silicon:
    • The platform-detection code selects the osx-x64 artifact URL.
    • CMAKE_OSX_ARCHITECTURES is still forced to x86_64 (existing behaviour).
    • A STATUS message informs the user that the pre-built osx-x64 artifact is being used through Rosetta.
  • If OPENMS_THERMO_BRIDGE_PREBUILT_MANAGED_DIR is set manually on Apple Silicon, CMake emits the same Rosetta performance warning it currently does, but does not block the build.

5. Update documentation (README.md)

  • Add a new "Option 3: use pre-built managed DLLs" section below the existing two build options:
    • Show how to pass -DOPENMS_THERMO_BRIDGE_PREBUILT_MANAGED_DIR=/path/to/unpacked/zip for manually downloaded artifacts.
    • Show how to use -DOPENMS_THERMO_BRIDGE_DOWNLOAD_PREBUILT_MANAGED=ON for automatic download.
  • Update the Requirements section: note that dotnet SDK is not required when using pre-built artifacts (only the .NET 8 runtime is needed at runtime).
  • Add a note that on Apple Silicon, pre-built artifacts are always osx-x64 and run via Rosetta, consistent with the existing workaround documentation.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: Analysis: Can the C# Wrapper Be Eliminated?

No — the C# wrapper (ThermoWrapperManaged.cs) cannot be removed.

The Thermo RawFileReader library (ThermoFisher.CommonCore.*) is a managed .NET assembly. It exposes entirely managed types: IRawDataPlus, Scan, ChromatogramTraceSettings, managed strings, LINQ, managed exceptions, etc. There is no native C or C++ API surface — the library exists only in managed code.

The nethost/hostfxr mechanism that the C++ side uses can only call across the managed/native boundary via [UnmanagedCallersOnly] entry points. Those entry points are the methods in ThermoWrapperManaged.cs that:

  1. Receive raw IntPtr/int/double arguments from C++,

  2. Unmarshal them into managed .NET types,

  3. Call the RawFileReader managed API,

  4. Marshal results back into native-compatible primitives (blittable arrays via Marshal.Copy, UTF-8 strings into caller-provided buffers, sentinel error values, etc.).

Without this shim, C++ would have no way to turn a managed IRawDat...

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Add GitHub Actions release workflow for managed C# artifacts Add GitHub Actions release workflow and CMake pre-built managed artifact support Apr 28, 2026
Copilot AI requested a review from jpfeuffer April 28, 2026 13:51
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.

2 participants