Merge pull request #114 from royalapplications/codex/upgrade-avalonia… #31
Workflow file for this run
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: Release | |
| on: | |
| push: | |
| tags: ['v*'] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| DOTNET_VERSION: '10.0.x' | |
| DOTNET_NOLOGO: true | |
| DOTNET_CLI_TELEMETRY_OPTOUT: true | |
| jobs: | |
| # ───────────────────────────────────────────── | |
| # Native builds for each platform | |
| # ───────────────────────────────────────────── | |
| native-macos: | |
| name: Native (macOS ${{ matrix.arch }}) | |
| # Pin macOS 15 for reproducible SDK compatibility with the native artifacts. | |
| runs-on: macos-15 | |
| strategy: | |
| matrix: | |
| arch: [arm64, x64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| submodules: recursive | |
| - name: Setup Zig | |
| uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - name: Build libghostty-vt | |
| working-directory: external/ghostty | |
| run: | | |
| if [ "${{ matrix.arch }}" = "arm64" ]; then | |
| zig build -Doptimize=ReleaseFast -Dapp-runtime=none -Demit-lib-vt=true -Demit-xcframework=false -Demit-macos-app=false | |
| else | |
| zig build -Doptimize=ReleaseFast -Dapp-runtime=none -Demit-lib-vt=true -Demit-xcframework=false -Demit-macos-app=false -Dtarget=x86_64-macos | |
| fi | |
| - name: Build ghostty-renderer-capi | |
| working-directory: native/ghostty-renderer-capi | |
| run: | | |
| if [ "${{ matrix.arch }}" = "arm64" ]; then | |
| zig build -Doptimize=ReleaseFast | |
| else | |
| zig build -Doptimize=ReleaseFast -Dtarget=x86_64-macos | |
| fi | |
| - name: Collect artifacts | |
| run: | | |
| mkdir -p artifacts | |
| find external/ghostty/zig-out -name "libghostty-vt*.dylib" -exec cp -L {} artifacts/ \; | |
| if [ -f native/ghostty-renderer-capi/zig-out/lib/libghostty-renderer-capi.dylib ]; then | |
| cp -L native/ghostty-renderer-capi/zig-out/lib/libghostty-renderer-capi.dylib artifacts/ | |
| fi | |
| ls -la artifacts/ | |
| - name: Verify required native artifacts (macOS) | |
| run: | | |
| set -euo pipefail | |
| required=( | |
| "libghostty-vt.dylib" | |
| "libghostty-renderer-capi.dylib" | |
| ) | |
| for file in "${required[@]}"; do | |
| if [ ! -f "artifacts/${file}" ]; then | |
| echo "::error::Missing required macOS native artifact: ${file}" | |
| exit 1 | |
| fi | |
| done | |
| - name: Upload | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: native-osx-${{ matrix.arch }} | |
| path: artifacts/ | |
| native-linux: | |
| name: Native (Linux ${{ matrix.arch }}) | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| matrix: | |
| include: | |
| - arch: x64 | |
| runner: ubuntu-latest | |
| zig-target: x86_64-linux-gnu | |
| - arch: arm64 | |
| runner: ubuntu-24.04-arm | |
| zig-target: aarch64-linux-gnu | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| submodules: recursive | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| pkg-config \ | |
| libbz2-dev \ | |
| libfreetype6-dev \ | |
| libharfbuzz-dev \ | |
| libfontconfig1-dev \ | |
| libpng-dev \ | |
| zlib1g-dev \ | |
| libonig-dev \ | |
| glslang-dev \ | |
| libspirv-cross-c-shared-dev | |
| multiarch="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" | |
| if [ -f "/usr/lib/${multiarch}/libbz2.so" ] && [ ! -e "/usr/lib/${multiarch}/libbzip2.so" ]; then | |
| sudo ln -s "/usr/lib/${multiarch}/libbz2.so" "/usr/lib/${multiarch}/libbzip2.so" | |
| fi | |
| if [ -f "/usr/lib/${multiarch}/libbz2.a" ] && [ ! -e "/usr/lib/${multiarch}/libbzip2.a" ]; then | |
| sudo ln -s "/usr/lib/${multiarch}/libbz2.a" "/usr/lib/${multiarch}/libbzip2.a" | |
| fi | |
| - name: Setup Zig | |
| uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - name: Build libghostty-vt | |
| working-directory: external/ghostty | |
| run: | | |
| # Keep Linux native packages on a portable CPU baseline. A runner-native | |
| # Ghostty build can SIGILL during terminal/PageList startup on another | |
| # machine with the same RID. Do not force -fsys dependencies here: | |
| # explicit targets make Zig use cross-target system-library discovery. | |
| build_args=( | |
| build | |
| -Doptimize=ReleaseFast | |
| -Dapp-runtime=none | |
| -Demit-lib-vt=true | |
| -Dtarget=${{ matrix.zig-target }} | |
| -Dsimd=false | |
| ) | |
| zig "${build_args[@]}" | |
| - name: Build ghostty-renderer-capi | |
| working-directory: native/ghostty-renderer-capi | |
| run: | | |
| build_args=(build -Doptimize=ReleaseFast -Dtarget=${{ matrix.zig-target }}) | |
| zig "${build_args[@]}" | |
| - name: Collect artifacts | |
| run: | | |
| mkdir -p artifacts | |
| find external/ghostty/zig-out -name "libghostty-vt.so*" -exec cp -L {} artifacts/ \; | |
| find native/ghostty-renderer-capi/zig-out -name "libghostty-renderer-capi.so*" -exec cp -L {} artifacts/ \; || true | |
| for base in libghostty-vt libghostty-renderer-capi; do | |
| if [ ! -f "artifacts/${base}.so" ]; then | |
| candidate="$(find artifacts -maxdepth 1 -type f -name "${base}.so*" | head -n1 || true)" | |
| if [ -n "${candidate}" ]; then | |
| cp -f "${candidate}" "artifacts/${base}.so" | |
| fi | |
| fi | |
| done | |
| ls -la artifacts/ | |
| - name: Verify required native artifacts (Linux) | |
| run: | | |
| set -euo pipefail | |
| required=( | |
| "libghostty-vt.so" | |
| "libghostty-renderer-capi.so" | |
| ) | |
| for file in "${required[@]}"; do | |
| if [ ! -f "artifacts/${file}" ]; then | |
| echo "::error::Missing required Linux native artifact: ${file}" | |
| exit 1 | |
| fi | |
| done | |
| - name: Upload | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: native-linux-${{ matrix.arch }} | |
| path: artifacts/ | |
| native-windows: | |
| name: Native (Windows ${{ matrix.arch }}) | |
| runs-on: windows-latest | |
| strategy: | |
| matrix: | |
| arch: [x64, arm64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| submodules: recursive | |
| - name: Setup Zig | |
| uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - name: Build libghostty-vt | |
| working-directory: external/ghostty | |
| shell: bash | |
| run: | | |
| cpu="" | |
| simd="" | |
| if [ "${{ matrix.arch }}" = "arm64" ]; then | |
| target="-Dtarget=aarch64-windows-gnu" | |
| # Zig 0.16.0's Windows ARM64 stdlib stack-trace code fails to | |
| # compile when Ghostty's vendored SIMD archive is enabled. | |
| simd="-Dsimd=false" | |
| else | |
| # Keep win-x64 release artifacts on a true baseline x64 CPU model. | |
| # x86_64-windows-msvc alone still allows LLVM/third-party SIMD code | |
| # to leave VEX/AVX instructions in startup paths. Disable Zig's | |
| # vzeroupper feature and Ghostty's SIMD bundle for the compatibility | |
| # DLL; CI verifies the resulting DLL with disassembly below. | |
| target="-Dtarget=x86_64-windows-msvc" | |
| cpu="-Dcpu=x86_64-vzeroupper" | |
| simd="-Dsimd=false" | |
| fi | |
| zig build -Doptimize=ReleaseFast -Dapp-runtime=none -Demit-lib-vt=true ${target} ${cpu} ${simd} | |
| - name: Build ghostty-renderer-capi | |
| working-directory: native/ghostty-renderer-capi | |
| shell: bash | |
| run: | | |
| cpu="" | |
| if [ "${{ matrix.arch }}" = "arm64" ]; then | |
| target="-Dtarget=aarch64-windows-gnu" | |
| else | |
| target="-Dtarget=x86_64-windows-msvc" | |
| cpu="-Dcpu=x86_64-vzeroupper" | |
| fi | |
| zig build -Doptimize=ReleaseFast ${target} ${cpu} | |
| - name: Collect artifacts | |
| shell: bash | |
| run: | | |
| mkdir -p artifacts/win-${{ matrix.arch }} | |
| find external/ghostty/zig-out \( -name "ghostty-vt.dll" -o -name "libghostty-vt.dll" \) -exec cp -L {} artifacts/win-${{ matrix.arch }}/ \; | |
| find native/ghostty-renderer-capi/zig-out \( -name "ghostty-renderer-capi.dll" -o -name "libghostty-renderer-capi.dll" \) -exec cp -L {} artifacts/win-${{ matrix.arch }}/ \; || true | |
| for base in ghostty-vt ghostty-renderer-capi; do | |
| if [ ! -f "artifacts/win-${{ matrix.arch }}/${base}.dll" ] && [ -f "artifacts/win-${{ matrix.arch }}/lib${base}.dll" ]; then | |
| cp -f "artifacts/win-${{ matrix.arch }}/lib${base}.dll" "artifacts/win-${{ matrix.arch }}/${base}.dll" | |
| fi | |
| done | |
| ls -la artifacts/win-${{ matrix.arch }}/ | |
| - name: Verify required native artifacts (Windows) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| required=( | |
| "ghostty-vt.dll" | |
| "ghostty-renderer-capi.dll" | |
| ) | |
| for file in "${required[@]}"; do | |
| if [ ! -f "artifacts/win-${{ matrix.arch }}/${file}" ]; then | |
| echo "::error::Missing required Windows native artifact: ${file}" | |
| exit 1 | |
| fi | |
| done | |
| - name: Verify Windows x64 native artifacts avoid AVX | |
| if: matrix.arch == 'x64' | |
| shell: pwsh | |
| run: | | |
| ./scripts/verify-windows-x64-no-avx.ps1 ` | |
| -Path "artifacts/win-x64/ghostty-vt.dll", "artifacts/win-x64/ghostty-renderer-capi.dll" | |
| - name: Upload | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: native-win-${{ matrix.arch }} | |
| path: artifacts/win-${{ matrix.arch }}/ | |
| # ───────────────────────────────────────────── | |
| # Build, test, pack, and publish | |
| # ───────────────────────────────────────────── | |
| test: | |
| name: Test | |
| runs-on: macos-latest | |
| needs: [native-macos] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| submodules: recursive | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Download native (macOS arm64) | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: native-osx-arm64 | |
| path: src/RoyalTerminal.GhosttySharp.Native.OSX/runtimes/osx-arm64/native/ | |
| - name: Download native (macOS x64) | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: native-osx-x64 | |
| path: src/RoyalTerminal.GhosttySharp.Native.OSX/runtimes/osx-x64/native/ | |
| - name: Stage native artifacts for managed interop (macOS) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| for rid in osx-arm64 osx-x64; do | |
| src="src/RoyalTerminal.GhosttySharp.Native.OSX/runtimes/${rid}/native" | |
| dst_interop="src/RoyalTerminal.Rendering.Interop.Ghostty/runtimes/${rid}/native" | |
| dst_fixture="native/${rid}" | |
| mkdir -p "${dst_interop}" "${dst_fixture}" | |
| cp -f "${src}"/* "${dst_interop}/" | |
| cp -f "${src}"/* "${dst_fixture}/" | |
| done | |
| ls -la src/RoyalTerminal.Rendering.Interop.Ghostty/runtimes/osx-arm64/native/ | |
| - name: Restore & Build | |
| run: dotnet build -c Release | |
| - name: Unit Tests | |
| shell: bash | |
| env: | |
| ROYALTERMINAL_VALIDATE_TEST_BATCH_COVERAGE: true | |
| ROYALTERMINAL_TEST_BLAME_CRASH: true | |
| ROYALTERMINAL_TEST_BLAME_HANG: true | |
| ROYALTERMINAL_TEST_BLAME_HANG_TIMEOUT: 5m | |
| ROYALTERMINAL_TEST_BLAME_HANG_DUMP_TYPE: mini | |
| run: bash scripts/run-unit-test-batches.sh | |
| - name: Unit Smoke Tests | |
| run: dotnet test tests/RoyalTerminal.Tests/RoyalTerminal.Tests.csproj -c Release --no-build --filter "(FullyQualifiedName~TerminalModeResolverTests)|(FullyQualifiedName~Headless_FallbackParity_AutoAndManaged_PreserveKeyboardMousePasteAndResize_WhenHostedInScrollViewer)" --logger "trx;LogFileName=mode-startup-smoke-results.trx" --results-directory ./test-results | |
| - name: Integration Tests | |
| run: dotnet test tests/RoyalTerminal.IntegrationTests/RoyalTerminal.IntegrationTests.csproj -c Release | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: release-test-results | |
| path: test-results/ | |
| retention-days: 7 | |
| pack-and-publish: | |
| name: Pack & Publish | |
| runs-on: ubuntu-latest | |
| needs: [test, native-macos, native-linux, native-windows] | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Validate release tag | |
| id: version | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| version="${GITHUB_REF_NAME#v}" | |
| if [[ ! "${version}" =~ ^[0-9]+(\.[0-9]+){2}(-[0-9A-Za-z][0-9A-Za-z.-]*)?$ ]]; then | |
| echo "::error::Release tags must use vMAJOR.MINOR.PATCH or vMAJOR.MINOR.PATCH-prerelease, got ${GITHUB_REF_NAME}" | |
| exit 1 | |
| fi | |
| echo "VERSION=${version}" >> "$GITHUB_OUTPUT" | |
| # Download native artifacts into package runtime directories | |
| - name: Download macOS arm64 | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: native-osx-arm64 | |
| path: src/RoyalTerminal.GhosttySharp.Native.OSX/runtimes/osx-arm64/native/ | |
| - name: Download macOS x64 | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: native-osx-x64 | |
| path: src/RoyalTerminal.GhosttySharp.Native.OSX/runtimes/osx-x64/native/ | |
| - name: Download Linux x64 | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: native-linux-x64 | |
| path: src/RoyalTerminal.GhosttySharp.Native.Linux64/runtimes/linux-x64/native/ | |
| - name: Download Linux arm64 | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: native-linux-arm64 | |
| path: src/RoyalTerminal.GhosttySharp.Native.Linux64/runtimes/linux-arm64/native/ | |
| - name: Download Windows x64 | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: native-win-x64 | |
| path: src/RoyalTerminal.GhosttySharp.Native.Win64/runtimes/win-x64/native/ | |
| - name: Download Windows arm64 | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: native-win-arm64 | |
| path: src/RoyalTerminal.GhosttySharp.Native.Win64/runtimes/win-arm64/native/ | |
| - name: Verify downloaded native artifacts | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| check_files() { | |
| local dir="$1" | |
| shift | |
| for file in "$@"; do | |
| if [ ! -f "${dir}/${file}" ]; then | |
| echo "::error::Missing required native artifact ${file} in ${dir}" | |
| exit 1 | |
| fi | |
| done | |
| } | |
| check_files "src/RoyalTerminal.GhosttySharp.Native.OSX/runtimes/osx-arm64/native" \ | |
| "libghostty-vt.dylib" "libghostty-renderer-capi.dylib" | |
| check_files "src/RoyalTerminal.GhosttySharp.Native.OSX/runtimes/osx-x64/native" \ | |
| "libghostty-vt.dylib" "libghostty-renderer-capi.dylib" | |
| check_files "src/RoyalTerminal.GhosttySharp.Native.Linux64/runtimes/linux-x64/native" \ | |
| "libghostty-vt.so" "libghostty-renderer-capi.so" | |
| check_files "src/RoyalTerminal.GhosttySharp.Native.Linux64/runtimes/linux-arm64/native" \ | |
| "libghostty-vt.so" "libghostty-renderer-capi.so" | |
| check_files "src/RoyalTerminal.GhosttySharp.Native.Win64/runtimes/win-x64/native" \ | |
| "ghostty-vt.dll" "ghostty-renderer-capi.dll" | |
| check_files "src/RoyalTerminal.GhosttySharp.Native.Win64/runtimes/win-arm64/native" \ | |
| "ghostty-vt.dll" "ghostty-renderer-capi.dll" | |
| - name: Pack all packable projects | |
| shell: bash | |
| run: bash scripts/pack-nuget.sh --configuration Release --output artifacts --version "${{ steps.version.outputs.VERSION }}" | |
| - name: List packages | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| find artifacts -maxdepth 1 -type f -name '*.nupkg' -print | sort | |
| # Publish to NuGet | |
| - name: Push to NuGet.org | |
| shell: bash | |
| env: | |
| NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} | |
| NUGET_SOURCE: https://api.nuget.org/v3/index.json | |
| run: bash scripts/push-nuget.sh --directory artifacts | |
| - name: Create GitHub Release | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| release_args=() | |
| if [[ "${GITHUB_REF_NAME}" == *-* ]]; then | |
| release_args+=(--prerelease) | |
| fi | |
| if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then | |
| gh release edit "${GITHUB_REF_NAME}" \ | |
| --title "${GITHUB_REF_NAME}" \ | |
| --draft=false \ | |
| "${release_args[@]}" | |
| else | |
| gh release create "${GITHUB_REF_NAME}" \ | |
| --title "${GITHUB_REF_NAME}" \ | |
| --generate-notes \ | |
| --verify-tag \ | |
| "${release_args[@]}" | |
| fi | |
| gh release upload "${GITHUB_REF_NAME}" artifacts/*.nupkg --clobber |