Skip to content

Fix Roslyn version mismatch causing CS8795 build failures (#970), harden PR CI #713

Fix Roslyn version mismatch causing CS8795 build failures (#970), harden PR CI

Fix Roslyn version mismatch causing CS8795 build failures (#970), harden PR CI #713

Workflow file for this run

# Based on workflow from https://github.com/krafs/LevelUp
name: Validate Pull Request
env:
SLN_PATH: Source/
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
permissions:
contents: read
on:
pull_request
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-test:
name: Build, Test (${{ matrix.os }}, .NET ${{ matrix.sdk }}, ${{ matrix.configuration }})
runs-on: ${{ matrix.os }}
timeout-minutes: 15
# '11' is preview-only right now, so let it fail without blocking the PR -
# this leg exists to catch upcoming breaks early, not to gate on
# preview-SDK bugs unrelated to this repo's code.
continue-on-error: ${{ matrix.sdk == '11' }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
configuration: [Debug, Release]
# Add another major version (e.g. '12', '8') to test more SDKs.
sdk: [global.json, '10', '11']
fail-fast: false
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# The committed global.json pins a specific major version, which would
# otherwise force every "dotnet" invocation on this leg (including
# setup-dotnet's own internal calls) back to that version regardless of
# which SDK we install below.
- name: Remove committed global.json for SDK override leg
if: matrix.sdk != 'global.json'
run: rm global.json
- name: Set up .NET (pinned)
if: matrix.sdk == 'global.json'
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: global.json
cache: true
cache-dependency-path: '**/*.csproj'
- name: Set up .NET (override)
if: matrix.sdk != 'global.json'
id: setup_dotnet_override
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
dotnet-version: ${{ matrix.sdk }}.0.x
cache: true
cache-dependency-path: '**/*.csproj'
# A generic "major.0.100" anchor + rollForward doesn't reliably match a
# preview-only install (dotnet/sdk#12335, reproduced here for the "11"
# leg) - pin the exact resolved version instead, per
# https://github.com/actions/setup-dotnet#matrix-testing.
- name: Pin global.json to resolved override SDK
if: matrix.sdk != 'global.json'
run: echo '{"sdk":{"version":"${{ steps.setup_dotnet_override.outputs.dotnet-version }}","rollForward":"latestPatch"}}' > ./global.json
- name: Display SDK version
run: dotnet --version
# Catches a silent wrong-SDK regression: dotnet --version could report
# the global.json-pinned major instead of this leg's intended one
# without anything failing until the logs were read by hand.
- name: Verify resolved SDK matches this leg's expected major version
shell: bash
run: |
ACTUAL_MAJOR=$(dotnet --version | cut -d. -f1)
if [ "${{ matrix.sdk }}" = "global.json" ]; then
EXPECTED_MAJOR=$(grep -oE '"version": *"[0-9]+' global.json | grep -oE '[0-9]+$')
else
EXPECTED_MAJOR="${{ matrix.sdk }}"
fi
echo "Resolved SDK major: $ACTUAL_MAJOR, expected: $EXPECTED_MAJOR"
if [ "$ACTUAL_MAJOR" != "$EXPECTED_MAJOR" ]; then
echo "::error::Resolved .NET SDK major ($ACTUAL_MAJOR) does not match this leg's expected major ($EXPECTED_MAJOR)"
exit 1
fi
- name: Restore dependencies
run: dotnet restore ${{ env.SLN_PATH }}
- name: Build solution
run: dotnet build ${{ env.SLN_PATH }} --configuration ${{ matrix.configuration }} --no-restore
- name: Run tests
run: dotnet test ${{ env.SLN_PATH }} --configuration ${{ matrix.configuration }} --no-restore --logger "trx;logfilename=TestResults.trx"
- name: Upload test results
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: test-results-${{ matrix.os }}-${{ matrix.sdk }}-${{ matrix.configuration }}
path: '**/TestResults/**'
retention-days: 7
if-no-files-found: error
format-check:
name: Code formatting (non-blocking)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: global.json
cache: true
cache-dependency-path: '**/*.csproj'
- name: Restore dependencies
run: dotnet restore ${{ env.SLN_PATH }}
# continue-on-error keeps this from failing the PR: the repo has existing
# formatting debt, so this reports issues in the log without blocking
# merges until that debt is cleaned up.
- name: Check code formatting
continue-on-error: true
run: dotnet format ${{ env.SLN_PATH }} --verify-no-changes
package-artifacts:
name: Package mod, server artifacts
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
# submodules: recursive is required here (unlike the other jobs) because
# Languages/ is a submodule and gets bundled directly into the mod
# artifact.
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
submodules: recursive
# GitHub Actions expressions have no substring function, so the short
# SHA used to name artifacts below is computed here instead.
- name: Compute short commit SHA
id: vars
run: echo "short_sha=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
- name: Set up .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: global.json
cache: true
cache-dependency-path: '**/*.csproj'
- name: Restore dependencies
run: dotnet restore ${{ env.SLN_PATH }}
# Multiplayer.csproj copies its build output into Assemblies/ and
# AssembliesCustom/ as a post-build step, alongside the static About/,
# Defs/, Languages/, and Textures/ content - together these are the
# complete mod folder.
- name: Build mod (Release)
run: dotnet build ${{ env.SLN_PATH }} --configuration Release --no-restore
# Server.csproj publish restores runtime-specific assets itself, so no
# --no-restore here.
- name: Publish server (Windows)
run: dotnet publish ${{ env.SLN_PATH }}Server/Server.csproj --configuration Release --runtime win-x64 --self-contained false -p:UseAppHost=true -o artifacts/server/Server/Windows
- name: Publish server (Linux)
run: dotnet publish ${{ env.SLN_PATH }}Server/Server.csproj --configuration Release --runtime linux-x64 --self-contained false -p:UseAppHost=true -o artifacts/server/Server/Linux
- name: Add server launcher script
run: |
cat > artifacts/server/Server/Linux/Server.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
exec dotnet "$SCRIPT_DIR/Server.dll" "$@"
EOF
chmod +x artifacts/server/Server/Linux/Server.sh
- name: Package mod files
run: |
mkdir -p artifacts/mod/Multiplayer
mv About/ Assemblies/ AssembliesCustom/ Defs/ Languages/ Textures/ artifacts/mod/Multiplayer/
# upload-artifact strips exactly the given "path" and keeps everything
# below it, so pointing at the parent of Multiplayer/ and Server/ (rather
# than at those folders directly) is what makes them the zip's root.
- name: Upload mod artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: Multiplayer-mod-pr${{ github.event.pull_request.number }}-${{ steps.vars.outputs.short_sha }}
path: artifacts/mod/
retention-days: 7
if-no-files-found: error
- name: Upload server artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: Multiplayer-server-pr${{ github.event.pull_request.number }}-${{ steps.vars.outputs.short_sha }}
path: artifacts/server/
retention-days: 7
if-no-files-found: error