LANCommander/.github/workflows/LANCommander.Server.yml
2026-06-17 02:45:29 -05:00

241 lines
No EOL
8.4 KiB
YAML

name: LANCommander Server Build
on:
workflow_dispatch:
workflow_call:
inputs:
version_semver:
description: "Semantic Version"
required: true
type: string
version_tag:
description: 'Version Tag'
required: true
type: string
build_dotnet_version:
description: 'Build .NET Version'
required: true
type: string
build_runtime:
description: 'Build Runtime'
required: false
type: string
default: 'win-x64'
build_arch:
description: 'Build Architecture'
required: false
type: string
default: 'x64'
build_platform:
description: 'Build Platform'
required: false
type: string
default: 'Windows'
build_configuration:
description: 'Build Configuration (Debug/Release)'
required: false
type: string
default: 'Release'
permissions:
contents: write
env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/package
jobs:
build:
runs-on: ${{ inputs.build_platform == 'Linux' && inputs.build_arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: frabert/replace-string-action@v2
name: Swap Path Backslashes
id: swap_path_backslashes
with:
string: '${{ github.workspace }}'
pattern: '\\'
replace-with: '/'
flags: g
# Checkout code
- uses: actions/checkout@v3
with:
submodules: true
# .NET Setup and Caching
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ inputs.build_dotnet_version }}
- name: Restore dependencies
run: dotnet restore --locked-mode
# Node.js Setup and Caching
- name: Setup Node.js
uses: actions/setup-node@v3.8.1
with:
node-version: '20'
- name: Install Node Packages
run: |
npm install --prefix ./LANCommander.UI
npm install --prefix ./LANCommander.Server
- name: Generate PowerShell Completions
run: dotnet run --project ./LANCommander.CompletionGenerator/LANCommander.CompletionGenerator.csproj -- ./LANCommander.UI/Components/MonacoCodeEditor/PowerShellCompletions.g.ts
- name: Package Frontend
run: |
npm run package --prefix ./LANCommander.UI
npm run package --prefix ./LANCommander.Server
# .NET builds
- name: Publish Updater and Server
run: |
# Strip leading 'v' if present
RAW_VERSION="${{ inputs.version_tag }}" # e.g. v2.0.0-rc1
SEMVER="${RAW_VERSION#v}" # 2.0.0-rc1
# Numeric part only for Assembly/FileVersion
NUMERIC="${SEMVER%%-*}" # 2.0.0
ASSEMBLY_VERSION="${NUMERIC}.0" # 2.0.0.0
echo "SEMVER=$SEMVER"
echo "ASSEMBLY_VERSION=$ASSEMBLY_VERSION"
dotnet publish "./LANCommander.AutoUpdater/LANCommander.AutoUpdater.csproj" \
-c "${{ inputs.build_configuration }}" \
--self-contained \
--runtime "${{ inputs.build_runtime }}" \
-p:Version="$SEMVER" \
-p:AssemblyVersion="$ASSEMBLY_VERSION" \
-p:FileVersion="$ASSEMBLY_VERSION" \
-p:InformationalVersion="$SEMVER"
# Disable NetBeauty on ARM64 runners — nbeauty2 only ships x64 native binaries
DISABLE_BEAUTY="False"
if [ "${{ inputs.build_arch }}" = "arm64" ] && [ "${{ inputs.build_platform }}" = "Linux" ]; then
DISABLE_BEAUTY="True"
fi
dotnet publish "./LANCommander.Server/LANCommander.Server.csproj" \
-c "${{ inputs.build_configuration }}" \
--self-contained \
--runtime "${{ inputs.build_runtime }}" \
-p:Version="$SEMVER" \
-p:AssemblyVersion="$ASSEMBLY_VERSION" \
-p:FileVersion="$ASSEMBLY_VERSION" \
-p:InformationalVersion="$SEMVER" \
-p:DisableBeauty="$DISABLE_BEAUTY"
- name: Bundle and Clean
shell: pwsh
run: |
Copy-Item -Force -Recurse -Verbose LANCommander.AutoUpdater/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish/* LANCommander.Server/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish/
# Remove unnecessary files in a single operation
$PathsToRemove = @(
'wwwroot/_content/BootstrapBlazor.PdfReader/compat',
'wwwroot/_content/BootstrapBlazor.PdfReader/2.*',
'wwwroot/_content/BootstrapBlazor.PdfReader/build/pdf.sandbox.js',
'wwwroot/_content/BootstrapBlazor.PdfReader/build/*.map',
'wwwroot/_content/BootstrapBlazor.PdfReader/web/*.map',
'wwwroot/_content/AntDesign/less',
'wwwroot/_content/BlazorMonaco/lib/monaco-editor/min-maps',
'wwwroot/Identity/lib/bootstrap',
'LANCommander.ico',
'LANCommanderDark.ico',
'package-lock.json',
'package.json',
'*.pdb',
'hostfxr.dll.bak',
'Libraries/locales'
)
$BasePath = "LANCommander.Server/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish"
foreach ($path in $PathsToRemove) {
Remove-Item -Recurse -Force -ErrorAction Continue "$BasePath/$path"
}
- name: Bundle macOS .app
if: inputs.build_platform == 'macOS'
shell: bash
run: |
set -euo pipefail
# Strip leading 'v' and reduce to numeric x.y.z for the bundle version keys.
RAW_VERSION="${{ inputs.version_tag }}"
SEMVER="${RAW_VERSION#v}"
NUMERIC="${SEMVER%%-*}"
APP_NAME="LANCommander Server"
EXECUTABLE="LANCommander.Server"
BUNDLE_ID="app.lancommander.server"
ICON_SRC="LANCommander.Server/icon.icns"
PUBLISH_DIR="LANCommander.Server/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish"
APP_DIR="${EXECUTABLE}.app"
# Lay out the bundle skeleton.
mkdir -p "$APP_DIR/Contents/MacOS" "$APP_DIR/Contents/Resources"
cp -a "$PUBLISH_DIR/." "$APP_DIR/Contents/MacOS/"
cp "$ICON_SRC" "$APP_DIR/Contents/Resources/AppIcon.icns"
# Write Info.plist.
cat > "$APP_DIR/Contents/Info.plist" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>${APP_NAME}</string>
<key>CFBundleDisplayName</key>
<string>${APP_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${BUNDLE_ID}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE}</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleShortVersionString</key>
<string>${NUMERIC}</string>
<key>CFBundleVersion</key>
<string>${SEMVER}</string>
<key>LSMinimumSystemVersion</key>
<string>11.0</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
PLIST
# Ensure the entrypoint is executable, then zip while preserving the
# permission bits (Compress-Archive drops the exec bit).
chmod +x "$APP_DIR/Contents/MacOS/${EXECUTABLE}"
zip -ry "LANCommander.Server-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip" "$APP_DIR"
- name: Compress Build Output
if: inputs.build_platform != 'macOS'
shell: pwsh
run: |
$compress = @{
Path = "LANCommander.Server/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish/*"
DestinationPath = "LANCommander.Server-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip"
CompressionLevel = "Fastest"
}
Compress-Archive @compress
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
path: LANCommander.Server-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip
name: LANCommander.Server-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip