feat(build): update workflow to trigger on feat/* and change MSVC set… #346
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
| name: build | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - dev | |
| - release/* | |
| - feat/* | |
| workflow_dispatch: | |
| # release.yml builds through this rather than duplicating ~150 lines of | |
| # toolchain and compile steps. Everything here is unsigned by design: code | |
| # signing and the installer live in release.yml, so a push build stays fast | |
| # and needs no secrets at all. | |
| # | |
| # An unsigned payload is complete and runnable but cannot activate — the boot | |
| # requires both the embedded signature and Authenticode, and a build that | |
| # skipped signing has neither. That is intentional, not a gap. | |
| workflow_call: | |
| jobs: | |
| build: | |
| name: build-${{ matrix.platform }} | |
| runs-on: ${{ matrix.os }} | |
| defaults: | |
| run: | |
| shell: bash | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: windows | |
| os: windows-2022 | |
| - platform: macos | |
| os: macos-26 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.ref }} | |
| submodules: true | |
| - name: Prepare environment variables | |
| run: | | |
| echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV" | |
| echo "APP_VERSION=$(node -p "require('./package.json').version")" >> "$GITHUB_ENV" | |
| # ─── Toolchains ───────────────────────────────────────────────────── | |
| # Xcode first: Microsoft.macOS.Sdk.net10.0_26.4 requires Xcode 26.x, and | |
| # selecting it before the SDK step keeps that ordering guarantee now that | |
| # the workload is installed as part of setup-dotnet. | |
| - name: Select latest Xcode | |
| if: runner.os == 'macOS' | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: latest-stable | |
| # .NET 10 for both Pengu.Windows (AOT) and Pengu.MacOS. The macos | |
| # workload comes from the `workloads` input rather than a separate | |
| # `dotnet workload install` step — it needs v5, v4 has no such input, and | |
| # it installs into the SDK setup-dotnet just laid down so there is no | |
| # sudo involved. | |
| - name: Setup .NET SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: 10.0.x | |
| workloads: ${{ runner.os == 'macOS' && 'macos' || '' }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: 24 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| with: | |
| version: 9 | |
| run_install: | | |
| - recursive: true | |
| # MSBuild + the VS 2022 C++ workload (preinstalled on windows-2022). | |
| # PublishAot relies on the C++ toolchain shipped with the workload. | |
| - name: Setup MSBuild | |
| if: runner.os == 'Windows' | |
| uses: microsoft/setup-msbuild@v3 | |
| # Puts cl.exe / link.exe / rc.exe on PATH for the rest of the job. Ninja | |
| # invokes the compiler directly rather than going through MSBuild, so it | |
| # needs the VC environment that a Developer Command Prompt would set. | |
| - name: Setup MSVC environment | |
| if: runner.os == 'Windows' | |
| uses: TheMrMilchmann/setup-msvc-dev@v4 | |
| with: | |
| arch: x64 | |
| # ─── Build (shared) ───────────────────────────────────────────────── | |
| # Preload bundle is #include'd into core (renderer.cc embeds preload.g.h). | |
| # Build it before core so the header exists. | |
| - name: Build preload | |
| run: pnpm --filter @pengujs/preload build | |
| # ─── Build (Windows) ──────────────────────────────────────────────── | |
| # core.dll and boot.dll, both landing in core/bin/x64/Release/. | |
| # | |
| # Built here rather than left to the ProjectReference in | |
| # Pengu.Windows.csproj, because the .NET SDK's MSBuild has no C++ targets | |
| # — $(VCTargetsPath) is unset under `dotnet build`, so a vcxproj reference | |
| # fails outright. That is what SkipNativeBuild exists for, and why the | |
| # publish step below sets it. | |
| # | |
| # CMake + Ninja rather than MSBuild: one configure covers both targets and | |
| # the whole native build takes seconds. core/core.vcxproj and | |
| # core/boot/boot.vcxproj still exist for Visual Studio via pengu.slnx and | |
| # produce identical output to the same directory — if you add a source | |
| # file, add it to both. | |
| - name: Build native (windows) | |
| if: runner.os == 'Windows' | |
| run: | | |
| cmake -S core -B core/build -G Ninja -DCMAKE_BUILD_TYPE=Release | |
| cmake --build core/build | |
| # Unit tests for the CEF-free logic under core/src — range parsing, the | |
| # path sandbox, config parsing. Seconds to run, and they gate the | |
| # artifact: a failure here should stop the build, not ship. | |
| - name: Test native (windows) | |
| if: runner.os == 'Windows' | |
| run: ctest --test-dir core/build --output-on-failure | |
| # AOT-publish the .NET 10 host. The csproj's BuildHubBundle target runs | |
| # `pnpm --filter @pengujs/hub build` and zips packages/hub/dist/ into | |
| # app.dat as part of the build, and the PublishAppDat target adds app.dat | |
| # to ResolvedFileToPublish — so a single dotnet publish produces | |
| # Pengu.exe + app.dat in the output dir. | |
| # | |
| # SkipNativeBuild drops the vcxproj ProjectReferences: the two steps above | |
| # already produced those binaries with a toolchain the SDK's MSBuild does | |
| # not have. | |
| - name: Publish app/Pengu.Windows (AOT) | |
| if: runner.os == 'Windows' | |
| run: | | |
| dotnet publish app/Pengu.Windows \ | |
| -c Release \ | |
| -r win-x64 \ | |
| -p:SkipNativeBuild=true \ | |
| --output app-publish | |
| # Clean portable payload: extract the artifact archive anywhere, run Pengu.exe. | |
| # app.dat is embedded inside Pengu.exe via <EmbeddedResource> — no | |
| # separate file ships alongside the exe. | |
| # | |
| # The native pair comes from the C++ output directory rather than from | |
| # app-publish, since SkipNativeBuild means the publish never staged them. | |
| - name: Stage portable payload (windows) | |
| if: runner.os == 'Windows' | |
| run: | | |
| mkdir -p out/ | |
| cp app-publish/Pengu.exe out/ | |
| cp app-publish/WebView2Loader.dll out/ | |
| cp core/bin/x64/Release/core.dll out/ | |
| cp core/bin/x64/Release/boot.dll out/ | |
| # ─── Build (macOS) ────────────────────────────────────────────────── | |
| # C++ core -> core/bin/core.dylib (the makefile's LIB_OUT_PATH). | |
| - name: Build core (macos) | |
| if: runner.os == 'macOS' | |
| run: make -C core -j release | |
| # Publish the .NET 10 macOS host as AOT + universal (arm64 + x86_64). | |
| # The csproj's <RuntimeIdentifiers> drives multi-arch — no -r flag. | |
| # The macOS workload publishes each RID, lipo's the resulting native | |
| # binaries, and stages the universal Pengu binary plus app.dat inside | |
| # Pengu.app/Contents/{MacOS,Resources}/. Expect 30–60 minutes due to | |
| # AOT compilation + per-RID lipo on a CI runner. | |
| - name: Publish app/Pengu.MacOS (AOT, universal) | |
| if: runner.os == 'macOS' | |
| run: | | |
| dotnet publish app/Pengu.MacOS \ | |
| -c Release \ | |
| --output app-publish | |
| # Stage two deliverables for the macOS artifact: | |
| # - Pengu-<ver>.pkg — installer with the universal AOT app inside | |
| # - Pengu.app — universal AOT build (x86_64 + arm64, ~28 MB), | |
| # drag-to-Applications form | |
| # | |
| # The .pkg lands in --output (app-publish/). The universal .app | |
| # always lands at bin/Release/net10.0-macos/Pengu.app regardless of | |
| # --output — `--output` only stages the .pkg installer, not the | |
| # bundle. The bin/.../Pengu.app already has full <BundleResource> | |
| # staging (app-icon.icns, core.dylib), lipo'd Mach-O, and the | |
| # workload's codesign applied. The per-RID .apps under | |
| # bin/Release/.../{osx-arm64,osx-x64}/ are intermediate skeletons — | |
| # not used for distribution. | |
| - name: Stage macOS deliverables | |
| if: runner.os == 'macOS' | |
| run: | | |
| mkdir -p out/ | |
| cp app-publish/*.pkg out/ | |
| cp -R app/Pengu.MacOS/bin/Release/net10.0-macos/Pengu.app out/Pengu.app | |
| codesign --verify --verbose=2 out/Pengu.app | |
| # ─── Artifact ─────────────────────────────────────────────────────── | |
| # release.yml picks the Windows one up by the `pengu-*-windows` pattern, | |
| # so the name shape here is load-bearing for that workflow. | |
| - name: Upload portable artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: pengu-v${{ env.APP_VERSION }}-${{ env.SHORT_SHA }}-${{ matrix.platform }} | |
| path: out/ | |
| if-no-files-found: error |