Compare commits
No commits in common. "main" and "client" have entirely different histories.
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[Bug]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Logs**
|
||||
Put relevant logs here in a code block
|
||||
|
||||
**Versions:**
|
||||
- LANCommander.Server version: [e.g. 1.1.4]
|
||||
- LANCommander.Launcher version: [e.g. 1.1.4]
|
||||
|
||||
**Additional Info**
|
||||
- Running in Docker: [e.g. yes/no]
|
||||
- Behind a reverse proxy: [e.g. none, traefik, nginx]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
84
.github/actions/LANCommander.Launcher/action.yml
vendored
|
|
@ -1,84 +0,0 @@
|
|||
name: 'Build LANCommander.Launcher'
|
||||
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'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Publish Components
|
||||
run: |
|
||||
dotnet publish "./LANCommander.AutoUpdater/LANCommander.AutoUpdater.csproj" -c ${{ inputs.build_configuration }} --self-contained --runtime ${{ inputs.build_runtime }} -p:Version="${{ inputs.version_tag }}" -p:AssemblyVersion="${{ inputs.version_semver }}"
|
||||
dotnet publish "./LANCommander.Launcher/LANCommander.Launcher.csproj" -c ${{ inputs.build_configuration }} --self-contained --runtime ${{ inputs.build_runtime }} -p:Version="${{ inputs.version_tag }}" -p:AssemblyVersion="${{ inputs.version_semver }}"
|
||||
dotnet publish "./LANCommander.Launcher.CLI/LANCommander.Launcher.CLI.csproj" -c ${{ inputs.build_configuration }} --self-contained --runtime ${{ inputs.build_runtime }} -p:Version="${{ inputs.version_tag }}" -p:AssemblyVersion="${{ inputs.version_semver }}"
|
||||
|
||||
- name: Bundle and Clean
|
||||
run: |
|
||||
Copy-Item -Force -Recurse -Verbose LANCommander.AutoUpdater/bin/${{ inputs.build_configuration }}/net9.0/${{ inputs.build_runtime }}/publish/* LANCommander.Launcher/bin/${{ inputs.build_configuration }}/net9.0/${{ inputs.build_runtime }}/publish/
|
||||
Copy-Item -Force -Recurse -Verbose LANCommander.Launcher.CLI/bin/${{ inputs.build_configuration }}/net9.0/${{ inputs.build_runtime }}/publish/* LANCommander.Launcher/bin/${{ inputs.build_configuration }}/net9.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.Launcher/bin/${{ inputs.build_configuration }}/net9.0/${{ inputs.build_runtime }}/publish"
|
||||
foreach ($path in $PathsToRemove) {
|
||||
Remove-Item -Recurse -Force -ErrorAction Continue "$BasePath/$path"
|
||||
}
|
||||
|
||||
- name: Compress Build Output
|
||||
run: |
|
||||
$compress = @{
|
||||
Path = "LANCommander.Launcher/bin/${{ inputs.build_configuration }}/net9.0/${{ inputs.build_runtime }}/publish/*"
|
||||
DestinationPath = "LANCommander.Launcher-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip"
|
||||
CompressionLevel = "Fastest"
|
||||
}
|
||||
Compress-Archive @compress
|
||||
|
||||
- name: Output artifact path
|
||||
run: echo "artifact=LANCommander.Launcher-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip >> $GITHUB_OUTPUT"
|
||||
86
.github/actions/LANCommander.Server/action.yml
vendored
|
|
@ -1,86 +0,0 @@
|
|||
name: 'Build LANCommander.Server'
|
||||
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'
|
||||
|
||||
outputs:
|
||||
artifact:
|
||||
description: "Output artifact"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Publish Updater and Server
|
||||
run: |
|
||||
dotnet publish "./LANCommander.AutoUpdater/LANCommander.AutoUpdater.csproj" -c ${{ inputs.build_configuration }} --self-contained --runtime ${{ inputs.build_runtime }} -p:Version="${{ inputs.version_tag }}" -p:AssemblyVersion="${{ inputs.version_semver }}"
|
||||
dotnet publish "./LANCommander.Server/LANCommander.Server.csproj" -c ${{ inputs.build_configuration }} --self-contained --runtime ${{ inputs.build_runtime }} -p:Version="${{ inputs.version_tag }}" -p:AssemblyVersion="${{ inputs.version_semver }}"
|
||||
|
||||
- name: Bundle and Clean
|
||||
run: |
|
||||
Copy-Item -Force -Recurse -Verbose LANCommander.AutoUpdater/bin/${{ inputs.build_configuration }}/net9.0/${{ inputs.build_runtime }}/publish/* LANCommander.Server/bin/${{ inputs.build_configuration }}/net9.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 }}/net9.0/${{ inputs.build_runtime }}/publish"
|
||||
foreach ($path in $PathsToRemove) {
|
||||
Remove-Item -Recurse -Force -ErrorAction Continue "$BasePath/$path"
|
||||
}
|
||||
|
||||
- name: Compress Build Output
|
||||
run: |
|
||||
$compress = @{
|
||||
Path = "LANCommander.Server/bin/${{ inputs.build_configuration }}/net9.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: Output artifact path
|
||||
run: echo "artifact=LANCommander.Server-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip >> $GITHUB_OUTPUT"
|
||||
100
.github/workflows/LANCommander.Cache.yml
vendored
|
|
@ -1,100 +0,0 @@
|
|||
name: LANCommander Server Restore
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build_dotnet_version:
|
||||
description: 'Build .NET Version'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/package
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
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
|
||||
|
||||
- name: NuGet Cache
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ${{ env.NUGET_PACKAGES }}
|
||||
key: ${{ runner.os }}-dotnet-${{ hashFiles('**/*.csproj') }}
|
||||
|
||||
# Node.js Setup and Caching
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3.8.1
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Generate PowerShell Completions
|
||||
run: dotnet run --project ./LANCommander.CompletionGenerator/LANCommander.CompletionGenerator.csproj -- ./LANCommander.UI/Components/MonacoCodeEditor/PowerShellCompletions.g.ts
|
||||
|
||||
# Parallel UI builds
|
||||
- name: Build UI Components
|
||||
run: |
|
||||
cd ./LANCommander.UI
|
||||
npm install
|
||||
npm run package
|
||||
|
||||
- name: Cache UI npm packages
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ./LANCommander.UI/node_modules
|
||||
key: LANCommander.UI-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Cache UI build
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ./LANCommander.UI/wwwroot
|
||||
key: LANCommander.UI-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Install Server Node Dependencies
|
||||
run: |
|
||||
cd ./LANCommander.Server
|
||||
npm install
|
||||
|
||||
- name: Cache Server npm packages
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ./LANCommander.Server/node_modules
|
||||
key: LANCommander.Server-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Install Launcher Node Dependencies
|
||||
run: |
|
||||
cd ./LANCommander.Launcher
|
||||
npm install
|
||||
|
||||
- name: Cache Launcher npm packages
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ./LANCommander.Launcher/node_modules
|
||||
key: LANCommander.Launcher-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
88
.github/workflows/LANCommander.Debug.yml
vendored
|
|
@ -1,88 +0,0 @@
|
|||
name: LANCommander Debug Build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*-debug'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy_server_win-x64:
|
||||
runs-on: [self-hosted, LANCommander Server]
|
||||
env:
|
||||
DOTNET_VERSION: '9.0.x' # Define the .NET version here
|
||||
PUBLISH_DIR: 'C:\LANCommander' # Define the output directory
|
||||
RUNTIME: 'win-x64' # Define the runtime platform
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Extract Version from Tag
|
||||
id: extract_version
|
||||
run: |
|
||||
$tag = "${{ github.ref }}".Replace("refs/tags/v", "")
|
||||
$version = $tag -replace "-debug", ""
|
||||
echo "version=$version" >> $env:GITHUB_ENV
|
||||
shell: pwsh
|
||||
|
||||
- name: Generate Build Number and Timestamp
|
||||
id: build_info
|
||||
run: |
|
||||
$buildNumber = "${{ github.run_number }}"
|
||||
$timestamp = Get-Date -Format "yyyyMMddHHmm"
|
||||
echo "build_number=$buildNumber" >> $env:GITHUB_ENV
|
||||
echo "timestamp=$timestamp" >> $env:GITHUB_ENV
|
||||
shell: pwsh
|
||||
|
||||
- name: Stop LANCommander Server Service
|
||||
run: |
|
||||
$serviceName = "LANCommander"
|
||||
if (Get-Service -Name $serviceName -ErrorAction SilentlyContinue) {
|
||||
Stop-Service -Name $serviceName -Force -ErrorAction SilentlyContinue
|
||||
Start-Sleep -Seconds 5
|
||||
}
|
||||
shell: pwsh
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
|
||||
# Node.js
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v3.8.1
|
||||
|
||||
# UI
|
||||
- name: Generate PowerShell Completions
|
||||
run: dotnet run --project ./LANCommander.CompletionGenerator/LANCommander.CompletionGenerator.csproj -- ./LANCommander.UI/Components/MonacoCodeEditor/PowerShellCompletions.g.ts
|
||||
- run: cd ./LANCommander.UI; npm install; npm run package
|
||||
- run: cd ./LANCommander.Server; npm install
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Publish LANCommander.Server
|
||||
run: |
|
||||
dotnet publish LANCommander.Server/LANCommander.Server.csproj `
|
||||
-c Release `
|
||||
-r ${{ env.RUNTIME }} `
|
||||
--self-contained `
|
||||
-p:Version=${{ env.version }} `
|
||||
-p:FileVersion=${{ env.version }}.${{ env.build_number }} `
|
||||
-p:InformationalVersion=${{ env.version }}+${{ env.timestamp }} `
|
||||
-o "${{ env.PUBLISH_DIR }}"
|
||||
shell: pwsh
|
||||
|
||||
- name: Start LANCommander Server Service
|
||||
run: |
|
||||
$serviceName = "LANCommander"
|
||||
if (Get-Service -Name $serviceName -ErrorAction SilentlyContinue) {
|
||||
Start-Service -Name $serviceName
|
||||
}
|
||||
shell: pwsh
|
||||
|
||||
- name: Verify build output
|
||||
run: dir "${{ env.PUBLISH_DIR }}"
|
||||
254
.github/workflows/LANCommander.Development.yml
vendored
|
|
@ -1,254 +0,0 @@
|
|||
name: LANCommander Development
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- development
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: lancommander/lancommander
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
jobs:
|
||||
# --------------------------------------------------------------------------
|
||||
# 1) PREP JOB: figure out the latest semver, build development version,
|
||||
# check if there are commits since the last development tag. If none,
|
||||
# skip the rest of the workflow.
|
||||
# --------------------------------------------------------------------------
|
||||
prep:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version_semver: ${{ steps.set_version.outputs.VERSION_SEMVER }}
|
||||
version_tag: ${{ steps.set_version.outputs.VERSION_TAG }}
|
||||
changed: ${{ steps.check_diff.outputs.changed }}
|
||||
build_dotnet_version: 9.0.102
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Ensure we get all tags so we can find the latest
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine last semver and build development version
|
||||
id: set_version
|
||||
shell: bash
|
||||
run: |
|
||||
# Fetch all tags
|
||||
git fetch --tags
|
||||
|
||||
# Grab the last semver-ish tag (e.g., "v1.2.3", "v1.2.3-debug", or "1.2.3-development")
|
||||
LAST_SEMVER_TAG="$(git tag --list --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+' | head -n1)"
|
||||
|
||||
if [ -z "$LAST_SEMVER_TAG" ]; then
|
||||
echo "No semver tag found; defaulting to 0.0.0"
|
||||
LAST_SEMVER_TAG="0.0.0"
|
||||
fi
|
||||
|
||||
# Remove prefix 'v' and any suffix like "-debug", "-development", etc.
|
||||
CLEAN_TAG="$(echo "${LAST_SEMVER_TAG#v}" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+')"
|
||||
|
||||
# Build a development version string, e.g., "1.2.3-development.20250127"
|
||||
DATE=$(date +'%Y%m%d')
|
||||
FINAL_VERSION="${CLEAN_TAG}-development.${DATE}"
|
||||
|
||||
echo "Last semver tag: $LAST_SEMVER_TAG"
|
||||
echo "Clean semver tag: $CLEAN_TAG"
|
||||
echo "Development version: $FINAL_VERSION"
|
||||
|
||||
# Set output variables for GitHub Actions
|
||||
echo "VERSION_SEMVER=$CLEAN_TAG" >> $GITHUB_ENV
|
||||
echo "VERSION_TAG=$FINAL_VERSION" >> $GITHUB_ENV
|
||||
echo "::set-output name=VERSION_SEMVER::$CLEAN_TAG"
|
||||
echo "::set-output name=VERSION_TAG::$FINAL_VERSION"
|
||||
|
||||
- name: Check if commits since last development tag
|
||||
id: check_diff
|
||||
shell: bash
|
||||
run: |
|
||||
# Fetch the last development tag
|
||||
LAST_DEVELOPMENT_TAG="$(git tag --list --sort=-v:refname | grep -E 'development\.20[0-9]+' | head -n1 || true)"
|
||||
|
||||
if [ -z "$LAST_DEVELOPMENT_TAG" ]; then
|
||||
echo "No previous development tag found. Marking as changed."
|
||||
echo "::set-output name=changed::true"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check for commits since that tag
|
||||
set +e # Disable exit on error temporarily
|
||||
COMMITS=$(git log "${LAST_DEVELOPMENT_TAG}"..HEAD --oneline 2>/dev/null || true)
|
||||
set -e # Re-enable exit on error
|
||||
|
||||
if [ -z "$COMMITS" ]; then
|
||||
echo "No commits since last development tag: $LAST_DEVELOPMENT_TAG"
|
||||
echo "::set-output name=changed::false"
|
||||
else
|
||||
echo "Found commits since $LAST_DEVELOPMENT_TAG"
|
||||
echo "::set-output name=changed::true"
|
||||
fi
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 2) BUILD JOBS (Server/Launcher) - only run if changes == 'true'
|
||||
# Each calls your local workflow YAML with correct indentation
|
||||
# --------------------------------------------------------------------------
|
||||
build_server_linux_x64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true'
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-x64
|
||||
build_arch: x64
|
||||
build_platform: Linux
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_win_x64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true'
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-x64
|
||||
build_arch: x64
|
||||
build_platform: Windows
|
||||
build_configuration: Debug
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 3) FINALIZE: if changes == 'true', gather artifacts + push Docker:development
|
||||
# --------------------------------------------------------------------------
|
||||
publish_docker_image:
|
||||
needs:
|
||||
- prep
|
||||
- build_server_linux_x64
|
||||
- build_server_win_x64
|
||||
if: needs.prep.outputs.changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# 3c) Build and push Docker image with tag "development"
|
||||
- name: Checkout Repo for Docker build
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=development
|
||||
type=raw,value=${{ needs.prep.outputs.version_tag }}
|
||||
|
||||
- name: Download Server x64 Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: ./
|
||||
|
||||
- name: Extract Server Artifacts
|
||||
run: |
|
||||
mkdir -p ./LANCommander.Server/published
|
||||
unzip ./LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip -d ./LANCommander.Server/published
|
||||
|
||||
# - name: Download Server arm64 Artifacts
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: LANCommander.Server-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
# path: ./published
|
||||
|
||||
# - name: Set up QEMU
|
||||
# uses: docker/setup-qemu-action@v2
|
||||
- name: Setup buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
platforms: linux/amd64
|
||||
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./LANCommander.Server
|
||||
file: ./LANCommander.Server/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}:development
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
VERSION=${{ needs.prep.outputs.version_tag }}
|
||||
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
provenance: true
|
||||
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
|
||||
- name: Save version to artifact
|
||||
run: echo "${{ needs.prep.outputs.version_tag }}" > version.txt
|
||||
|
||||
- name: Upload version artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: version.${{ needs.prep.outputs.version_tag }}
|
||||
path: version.txt
|
||||
publish_development_release:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prep
|
||||
- publish_docker_image
|
||||
steps:
|
||||
- name: Create Temp Directory
|
||||
run: mkdir -p artifacts
|
||||
|
||||
- name: Download Server Linux x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Server Windows x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Windows-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Delete existing release assets
|
||||
uses: dev-drprasad/delete-tag-and-release@v1.1
|
||||
with:
|
||||
tag_name: development
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create development release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: development
|
||||
name: Development Build v${{ needs.prep.outputs.version_tag }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
generate_release_notes: true
|
||||
body: This is the latest development build. These builds are generated automatically and should be considered unstable.
|
||||
files: |
|
||||
artifacts/LANCommander.Server-Windows-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
37
.github/workflows/LANCommander.DockerHub.yml
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
name: Publish Docker Image
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
push_to_registry:
|
||||
name: Push Docker image to Docker Hub
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: lancommander/lancommander
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
|
||||
with:
|
||||
context: ./Docker
|
||||
file: ./Docker/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
VERSION=${{github.ref_name}}
|
||||
28
.github/workflows/LANCommander.Documentation.yml
vendored
|
|
@ -1,28 +0,0 @@
|
|||
name: Publish Documentation Updates
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "LANCommander.Documentation/**"
|
||||
|
||||
jobs:
|
||||
dispatch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dispatch to Docusaurus repo
|
||||
env:
|
||||
DISPATCH_TOKEN: ${{ secrets.DOCUMENTATION_DISPATCH_TOKEN }}
|
||||
run: |
|
||||
curl -sS -X POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${DISPATCH_TOKEN}" \
|
||||
https://api.github.com/repos/LANCommander/LANCommander.Documentation/dispatches \
|
||||
-d '{
|
||||
"event_type": "docs-sources-updated",
|
||||
"client_payload": {
|
||||
"repo": "'"${GITHUB_REPOSITORY}"'",
|
||||
"sha": "'"${GITHUB_SHA}"'",
|
||||
"ref": "'"${GITHUB_REF}"'"
|
||||
}
|
||||
}'
|
||||
125
.github/workflows/LANCommander.Launcher.Legacy.yml
vendored
|
|
@ -1,125 +0,0 @@
|
|||
name: LANCommander.Launcher.Legacy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, feature/legacy-launcher]
|
||||
paths:
|
||||
- 'LANCommander.Launcher.Legacy/**'
|
||||
- 'LANCommander.SDK.Cpp/**'
|
||||
- '.github/workflows/LANCommander.Launcher.Legacy.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'LANCommander.Launcher.Legacy/**'
|
||||
- 'LANCommander.SDK.Cpp/**'
|
||||
- '.github/workflows/LANCommander.Launcher.Legacy.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-win9x:
|
||||
name: Build (Win9x / MinGW-w64 i686)
|
||||
runs-on: windows-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# MSYS2 with MinGW32 (i686) toolchain
|
||||
# ---------------------------------------------------------------
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: MINGW32
|
||||
update: false
|
||||
install: >-
|
||||
mingw-w64-i686-gcc
|
||||
mingw-w64-i686-cmake
|
||||
mingw-w64-i686-make
|
||||
make
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Vendor dependencies (cJSON, miniz, Allegro 4 source)
|
||||
# ---------------------------------------------------------------
|
||||
- name: Download vendor dependencies
|
||||
shell: pwsh
|
||||
run: ./setup-vendor.ps1
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Build Allegro 4 from source (static, no addons)
|
||||
# ---------------------------------------------------------------
|
||||
- name: Build Allegro 4
|
||||
run: |
|
||||
ALLEGRO_SRC="LANCommander.Launcher.Legacy/vendor/allegro4/allegro5-4.4.3.1"
|
||||
ALLEGRO_BUILD="LANCommander.Launcher.Legacy/build-allegro-win9x"
|
||||
ALLEGRO_PREFIX="$(pwd)/LANCommander.Launcher.Legacy/allegro4-win9x"
|
||||
|
||||
cmake -S "$ALLEGRO_SRC" -B "$ALLEGRO_BUILD" \
|
||||
-G "MinGW Makefiles" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="$ALLEGRO_PREFIX" \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
-DSHARED=OFF \
|
||||
-DWANT_EXAMPLES=OFF \
|
||||
-DWANT_TOOLS=OFF \
|
||||
-DWANT_TESTS=OFF \
|
||||
-DWANT_ALLEGROGL=OFF \
|
||||
-DWANT_LOADPNG=OFF \
|
||||
-DWANT_LOGG=OFF \
|
||||
-DWANT_JPGALLEG=OFF \
|
||||
-DWANT_FRAMEWORKS=OFF
|
||||
|
||||
mingw32-make -C "$ALLEGRO_BUILD" -j$(nproc)
|
||||
mingw32-make -C "$ALLEGRO_BUILD" install
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Build the launcher
|
||||
# ---------------------------------------------------------------
|
||||
- name: Build launcher
|
||||
run: |
|
||||
LAUNCHER_DIR="LANCommander.Launcher.Legacy"
|
||||
LAUNCHER_BUILD="$LAUNCHER_DIR/build-win9x"
|
||||
ALLEGRO_PREFIX="$(pwd)/$LAUNCHER_DIR/allegro4-win9x"
|
||||
|
||||
cmake -S "$LAUNCHER_DIR" -B "$LAUNCHER_BUILD" \
|
||||
-G "MinGW Makefiles" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DALLEGRO_STATIC=ON \
|
||||
-DTARGET_WIN9X=ON \
|
||||
-DALLEGRO_ROOT="$ALLEGRO_PREFIX"
|
||||
|
||||
mingw32-make -C "$LAUNCHER_BUILD" -j$(nproc)
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Package
|
||||
# ---------------------------------------------------------------
|
||||
- name: Package artifacts
|
||||
run: |
|
||||
mkdir -p out-win9x
|
||||
|
||||
LAUNCHER_EXE=$(find LANCommander.Launcher.Legacy/build-win9x -name "launcher.exe" | head -1)
|
||||
cp "$LAUNCHER_EXE" out-win9x/LANCommander.exe
|
||||
strip out-win9x/LANCommander.exe
|
||||
|
||||
# Bundle GDI+ redistributable (MinGW CRT is statically linked)
|
||||
if [ -f "$MINGW_PREFIX/bin/gdiplus.dll" ]; then
|
||||
cp "$MINGW_PREFIX/bin/gdiplus.dll" out-win9x/
|
||||
echo "Bundled: gdiplus.dll"
|
||||
fi
|
||||
|
||||
# Show PE info for verification
|
||||
objdump -p out-win9x/LANCommander.exe | grep -i "Version\|Subsystem" || true
|
||||
|
||||
echo ""
|
||||
ls -lh out-win9x/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: LANCommander-Legacy-Win9x
|
||||
path: out-win9x/
|
||||
if-no-files-found: error
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
name: LANCommander Launcher Tests — PR Visual Diff Comment
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: 'Pull request number to comment on'
|
||||
required: true
|
||||
type: string
|
||||
artifact_run_id:
|
||||
description: 'Workflow run ID that produced the launcher-visual-artifacts artifact'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write # push diff PNGs to the gh-visual-diffs branch
|
||||
pull-requests: write # post / update the comment
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout for branch push
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download visual artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: launcher-visual-artifacts
|
||||
path: visual
|
||||
run-id: ${{ inputs.artifact_run_id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Read regression manifest
|
||||
id: manifest
|
||||
run: |
|
||||
if [ ! -f visual/regressions.json ]; then
|
||||
echo "no manifest — assuming no visual run"
|
||||
echo "count=0" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
count=$(jq '.regressed_count' visual/regressions.json)
|
||||
echo "count=$count" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Skip when no regressions
|
||||
if: steps.manifest.outputs.count == '0'
|
||||
run: echo "No visual regressions; nothing to comment."
|
||||
|
||||
# Push diff/actual/baseline PNGs to an orphan branch so raw.githubusercontent.com
|
||||
# URLs render inline in the PR comment. One folder per (PR, run).
|
||||
- name: Push diffs to gh-visual-diffs branch
|
||||
if: steps.manifest.outputs.count != '0'
|
||||
env:
|
||||
PR: ${{ inputs.pr_number }}
|
||||
RUN: ${{ inputs.artifact_run_id }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Worktree off an orphan branch so we never touch the source tree.
|
||||
if git ls-remote --exit-code --heads origin gh-visual-diffs >/dev/null; then
|
||||
git fetch origin gh-visual-diffs
|
||||
git worktree add /tmp/visual gh-visual-diffs
|
||||
else
|
||||
git worktree add --detach /tmp/visual
|
||||
cd /tmp/visual
|
||||
git checkout --orphan gh-visual-diffs
|
||||
git rm -rf . 2>/dev/null || true
|
||||
cd -
|
||||
fi
|
||||
|
||||
DEST="/tmp/visual/pr-${PR}/run-${RUN}"
|
||||
mkdir -p "$DEST"
|
||||
cp -r visual/diffs "$DEST/" 2>/dev/null || true
|
||||
cp -r visual/screenshots "$DEST/" 2>/dev/null || true
|
||||
cp -r visual/baselines "$DEST/" 2>/dev/null || true
|
||||
|
||||
cd /tmp/visual
|
||||
git add -A
|
||||
git -c user.name=github-actions -c user.email=github-actions@github.com \
|
||||
commit -m "Visual diffs for PR #${PR} run ${RUN}"
|
||||
git push origin gh-visual-diffs
|
||||
|
||||
- name: Post / update PR comment
|
||||
if: steps.manifest.outputs.count != '0'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR: ${{ inputs.pr_number }}
|
||||
RUN: ${{ inputs.artifact_run_id }}
|
||||
REPO: ${{ github.repository }}
|
||||
MARKER: '<!-- launcher-visual-diff-comment -->'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
base="https://raw.githubusercontent.com/${REPO}/gh-visual-diffs/pr-${PR}/run-${RUN}"
|
||||
|
||||
body=$(mktemp)
|
||||
{
|
||||
echo "$MARKER"
|
||||
echo "## :art: Launcher visual regressions"
|
||||
echo
|
||||
echo "$(jq '.regressed_count' visual/regressions.json) baseline(s) drifted in [run ${RUN}](https://github.com/${REPO}/actions/runs/${RUN})."
|
||||
echo
|
||||
jq -r '.regressions[] | .name' visual/regressions.json | while read -r name; do
|
||||
echo "<details><summary><strong>${name}</strong></summary>"
|
||||
echo
|
||||
echo "| Baseline | Actual | Diff |"
|
||||
echo "| --- | --- | --- |"
|
||||
echo "|  |  |  |"
|
||||
echo
|
||||
echo "</details>"
|
||||
echo
|
||||
done
|
||||
echo "_If these changes are intentional, run the **Update Visual Baselines** workflow to refresh._"
|
||||
} >> "$body"
|
||||
|
||||
# Find an existing comment with our marker; update it if present.
|
||||
existing=$(gh api repos/${REPO}/issues/${PR}/comments --paginate \
|
||||
--jq ".[] | select(.body | startswith(\"${MARKER}\")) | .id" | head -1)
|
||||
|
||||
if [ -n "$existing" ]; then
|
||||
gh api -X PATCH "repos/${REPO}/issues/comments/${existing}" --field "body=@${body}"
|
||||
else
|
||||
gh api -X POST "repos/${REPO}/issues/${PR}/comments" --field "body=@${body}"
|
||||
fi
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
name: LANCommander Launcher Tests — Update Visual Baselines
|
||||
|
||||
# Operator-triggered: re-renders every visual test on the CI host and commits the
|
||||
# new screenshots over the committed Baselines/. Only runs when a human dispatches
|
||||
# it from the Actions tab — never on push or PR — so accidental drift can't slip in.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: 'Branch to commit refreshed baselines to'
|
||||
required: true
|
||||
type: string
|
||||
default: 'main'
|
||||
build_dotnet_version:
|
||||
description: 'Build .NET Version'
|
||||
required: false
|
||||
type: string
|
||||
default: '9.0.102'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
refresh:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
submodules: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ inputs.build_dotnet_version }}
|
||||
|
||||
- name: Install rendering prereqs
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
libfontconfig1 libfreetype6 libice6 libsm6 libx11-6 libxcb1 libxext6
|
||||
|
||||
- name: Restore + build visual test project
|
||||
run: |
|
||||
dotnet restore LANCommander.Launcher.Tests/LANCommander.Launcher.Tests.csproj
|
||||
dotnet build LANCommander.Launcher.Tests/LANCommander.Launcher.Tests.csproj -c Debug --no-restore
|
||||
|
||||
# Run visual tests, ignore failures (regressions are expected here — that's
|
||||
# the whole point of refreshing). Then promote every captured screenshot
|
||||
# to be the new baseline.
|
||||
- name: Capture fresh screenshots
|
||||
continue-on-error: true
|
||||
run: |
|
||||
dotnet test LANCommander.Launcher.Tests/LANCommander.Launcher.Tests.csproj \
|
||||
-c Debug --no-build --no-restore \
|
||||
--logger "console;verbosity=normal"
|
||||
|
||||
- name: Promote captures to baselines
|
||||
run: |
|
||||
set -euo pipefail
|
||||
src=LANCommander.Launcher.Tests/bin/Debug/net10.0/Screenshots
|
||||
dst=LANCommander.Launcher.Tests/Baselines
|
||||
|
||||
if [ ! -d "$src" ]; then
|
||||
echo "::error::No screenshots captured at $src — visual tests didn't run."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$dst"
|
||||
cp -v "$src"/*.png "$dst"/
|
||||
|
||||
echo "## Updated baselines" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "" >> "$GITHUB_STEP_SUMMARY"
|
||||
ls -1 "$dst"/*.png | xargs -n1 basename | sed 's/^/- /' >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Commit + push refreshed baselines
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
if git diff --quiet -- LANCommander.Launcher.Tests/Baselines; then
|
||||
echo "Baselines unchanged — nothing to commit."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git add LANCommander.Launcher.Tests/Baselines
|
||||
git commit -m "Refresh launcher visual baselines from CI run ${GITHUB_RUN_ID}"
|
||||
git push origin HEAD:${{ inputs.branch }}
|
||||
170
.github/workflows/LANCommander.Launcher.Tests.yml
vendored
|
|
@ -1,170 +0,0 @@
|
|||
name: LANCommander Launcher Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build_dotnet_version:
|
||||
description: 'Build .NET Version'
|
||||
required: true
|
||||
type: string
|
||||
outputs:
|
||||
visual_diff_count:
|
||||
description: 'Number of visual baselines that regressed in this run'
|
||||
value: ${{ jobs.test.outputs.visual_diff_count }}
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_dotnet_version:
|
||||
description: 'Build .NET Version'
|
||||
required: false
|
||||
type: string
|
||||
default: '9.0.102'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Run Launcher Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
outputs:
|
||||
visual_diff_count: ${{ steps.summarize.outputs.visual_diff_count }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ inputs.build_dotnet_version }}
|
||||
|
||||
# Avalonia headless rendering uses Skia + the Inter font. Install
|
||||
# font + GPU prereqs so screenshots render consistently.
|
||||
- name: Install rendering prereqs
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
libfontconfig1 libfreetype6 libice6 libsm6 libx11-6 libxcb1 libxext6
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore
|
||||
|
||||
# ---- Unit + integration test projects ---------------------------------
|
||||
# Services.Tests and IntegrationTests build cleanly without the
|
||||
# Server/UI npm+pwsh chain. Launcher.Tests likewise just needs Skia.
|
||||
|
||||
- name: Build test projects
|
||||
run: |
|
||||
dotnet build LANCommander.Launcher.Services.Tests/LANCommander.Launcher.Services.Tests.csproj -c Debug --no-restore
|
||||
dotnet build LANCommander.Launcher.IntegrationTests/LANCommander.Launcher.IntegrationTests.csproj -c Debug --no-restore
|
||||
dotnet build LANCommander.Launcher.Tests/LANCommander.Launcher.Tests.csproj -c Debug --no-restore
|
||||
|
||||
- name: Run Services unit tests
|
||||
run: |
|
||||
dotnet test LANCommander.Launcher.Services.Tests/LANCommander.Launcher.Services.Tests.csproj \
|
||||
-c Debug --no-build --no-restore \
|
||||
--logger "trx;LogFileName=services.trx" \
|
||||
--logger "console;verbosity=normal" \
|
||||
--results-directory test-results \
|
||||
--collect:"XPlat Code Coverage"
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
dotnet test LANCommander.Launcher.IntegrationTests/LANCommander.Launcher.IntegrationTests.csproj \
|
||||
-c Debug --no-build --no-restore \
|
||||
--logger "trx;LogFileName=integration.trx" \
|
||||
--logger "console;verbosity=normal" \
|
||||
--results-directory test-results \
|
||||
--collect:"XPlat Code Coverage"
|
||||
|
||||
# Visual tests are continued-on-error so a baseline regression doesn't
|
||||
# mask any earlier failure and so we always reach the artifact-upload
|
||||
# + summary steps below. The summary step re-asserts the failure for CI.
|
||||
- name: Run visual tests
|
||||
id: visual_tests
|
||||
continue-on-error: true
|
||||
run: |
|
||||
dotnet test LANCommander.Launcher.Tests/LANCommander.Launcher.Tests.csproj \
|
||||
-c Debug --no-build --no-restore \
|
||||
--logger "trx;LogFileName=visual.trx" \
|
||||
--logger "console;verbosity=normal" \
|
||||
--results-directory test-results
|
||||
|
||||
# ---- Visual artifact collection --------------------------------------
|
||||
# Aggregate every screenshot + diff PNG into top-level folders so the
|
||||
# PR-comment job downstream can find them by predictable name.
|
||||
|
||||
- name: Collect visual artifacts
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p visual/screenshots visual/diffs visual/baselines
|
||||
cp -r LANCommander.Launcher.Tests/bin/Debug/net10.0/Screenshots/. visual/screenshots/ 2>/dev/null || true
|
||||
cp -r LANCommander.Launcher.Tests/bin/Debug/net10.0/Diffs/. visual/diffs/ 2>/dev/null || true
|
||||
cp -r LANCommander.Launcher.Tests/Baselines/. visual/baselines/ 2>/dev/null || true
|
||||
|
||||
- name: Summarize visual diffs
|
||||
id: summarize
|
||||
if: always()
|
||||
run: |
|
||||
shopt -s nullglob
|
||||
diffs=(visual/diffs/*.diff.png)
|
||||
count=${#diffs[@]}
|
||||
|
||||
echo "visual_diff_count=$count" >> "$GITHUB_OUTPUT"
|
||||
echo "## Visual test summary" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "$count baseline(s) regressed." >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
# JSON manifest the PR-comment job consumes
|
||||
python3 - "$count" <<'PY' > visual/regressions.json
|
||||
import json, os, sys
|
||||
count = int(sys.argv[1])
|
||||
diffs = sorted(os.listdir("visual/diffs")) if os.path.isdir("visual/diffs") else []
|
||||
data = {
|
||||
"regressed_count": count,
|
||||
"regressions": [
|
||||
{
|
||||
"name": d.replace(".diff.png", ""),
|
||||
"diff": f"visual/diffs/{d}",
|
||||
"actual": f"visual/screenshots/{d.replace('.diff.png', '.png')}",
|
||||
"baseline": f"visual/baselines/{d.replace('.diff.png', '.png')}",
|
||||
}
|
||||
for d in diffs
|
||||
],
|
||||
}
|
||||
print(json.dumps(data, indent=2))
|
||||
PY
|
||||
|
||||
cat visual/regressions.json
|
||||
|
||||
- name: Upload visual artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: launcher-visual-artifacts
|
||||
path: |
|
||||
visual/screenshots/**
|
||||
visual/diffs/**
|
||||
visual/baselines/**
|
||||
visual/regressions.json
|
||||
if-no-files-found: warn
|
||||
retention-days: 14
|
||||
|
||||
- name: Upload TRX + coverage
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: launcher-test-results
|
||||
path: test-results/**
|
||||
if-no-files-found: warn
|
||||
retention-days: 14
|
||||
|
||||
# Re-assert the visual test outcome so CI fails when baselines diverge,
|
||||
# after artifacts are guaranteed uploaded.
|
||||
- name: Fail if visual tests regressed
|
||||
if: always() && steps.visual_tests.outcome == 'failure'
|
||||
run: |
|
||||
echo "::error::Visual tests reported regressions. See the launcher-visual-artifacts artifact."
|
||||
exit 1
|
||||
314
.github/workflows/LANCommander.Launcher.yml
vendored
|
|
@ -1,314 +0,0 @@
|
|||
name: LANCommander Launcher 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:
|
||||
# Checkout code
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
# .NET Setup
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ inputs.build_dotnet_version }}
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore --locked-mode
|
||||
|
||||
- name: Publish Launcher
|
||||
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.Launcher/LANCommander.Launcher.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:PublishSingleFile=true \
|
||||
-p:IncludeNativeLibrariesForSelfExtract=true \
|
||||
-p:IncludeAllContentForSelfExtract=true \
|
||||
-p:EnableCompressionInSingleFile=true \
|
||||
-p:DebugType=embedded
|
||||
|
||||
- name: Bundle libvlc (Linux)
|
||||
if: inputs.build_platform == 'Linux'
|
||||
shell: bash
|
||||
run: |
|
||||
PUBLISH_DIR="LANCommander.Launcher/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish"
|
||||
VLC_DIR="$PUBLISH_DIR/libvlc/${{ inputs.build_runtime }}"
|
||||
mkdir -p "$VLC_DIR"
|
||||
|
||||
if [ "${{ inputs.build_arch }}" = "arm64" ]; then
|
||||
# Enable arm64 multiarch and add Ubuntu Ports repository so apt can
|
||||
# download arm64 packages on this x64 runner.
|
||||
sudo dpkg --add-architecture arm64
|
||||
CODENAME=$(lsb_release -cs)
|
||||
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports ${CODENAME} main restricted universe" \
|
||||
| sudo tee /etc/apt/sources.list.d/ubuntu-ports-arm64.list > /dev/null
|
||||
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports ${CODENAME}-updates main restricted universe" \
|
||||
| sudo tee -a /etc/apt/sources.list.d/ubuntu-ports-arm64.list > /dev/null
|
||||
sudo apt-get update -qq
|
||||
|
||||
sudo apt-get download libvlc5:arm64 libvlccore9:arm64 vlc-plugin-base:arm64
|
||||
|
||||
mkdir -p vlc-extracted
|
||||
for deb in libvlc5_*arm64.deb libvlccore9_*arm64.deb vlc-plugin-base_*arm64.deb; do
|
||||
dpkg -x "$deb" vlc-extracted/
|
||||
done
|
||||
|
||||
LIB_DIR="vlc-extracted/usr/lib/aarch64-linux-gnu"
|
||||
PLUGINS_SRC="$LIB_DIR/vlc/plugins"
|
||||
else
|
||||
sudo apt-get install -y --no-install-recommends libvlc5 libvlccore9 vlc-plugin-base
|
||||
LIB_DIR="/usr/lib/x86_64-linux-gnu"
|
||||
PLUGINS_SRC="$LIB_DIR/vlc/plugins"
|
||||
fi
|
||||
|
||||
# Copy the two core shared libraries, dereferencing symlinks so their
|
||||
# content is preserved correctly when zipped.
|
||||
for lib in libvlc.so.5 libvlccore.so.9; do
|
||||
src=$(find "$LIB_DIR" -maxdepth 1 -name "${lib}*" | sort | head -1)
|
||||
if [ -n "$src" ]; then
|
||||
cp -L "$src" "$VLC_DIR/$lib"
|
||||
echo "Bundled: $lib"
|
||||
else
|
||||
echo "WARNING: $lib not found in $LIB_DIR" >&2
|
||||
fi
|
||||
done
|
||||
|
||||
# Copy VLC plugins (vlc-plugin-base covers common codecs and demuxers)
|
||||
if [ -d "$PLUGINS_SRC" ]; then
|
||||
mkdir -p "$VLC_DIR/plugins"
|
||||
cp -rL "$PLUGINS_SRC/." "$VLC_DIR/plugins/"
|
||||
echo "Bundled $(find "$VLC_DIR/plugins" -name "*.so" | wc -l) plugin(s)"
|
||||
fi
|
||||
|
||||
- name: Bundle and Clean
|
||||
shell: pwsh
|
||||
run: |
|
||||
$BasePath = "LANCommander.Launcher/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish"
|
||||
|
||||
# Remove unnecessary files
|
||||
$PathsToRemove = @(
|
||||
'*.pdb'
|
||||
)
|
||||
|
||||
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 Launcher"
|
||||
EXECUTABLE="LANCommander.Launcher"
|
||||
BUNDLE_ID="app.lancommander.launcher"
|
||||
ICON_SRC="LANCommander.Launcher/Assets/icon.icns"
|
||||
|
||||
PUBLISH_DIR="LANCommander.Launcher/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.Launcher-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip" "$APP_DIR"
|
||||
|
||||
- name: Build AppImage (Linux)
|
||||
if: inputs.build_platform == 'Linux'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
PUBLISH_DIR="LANCommander.Launcher/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish"
|
||||
APP_NAME="LANCommander.Launcher"
|
||||
APPDIR="AppDir"
|
||||
|
||||
# appimagetool / runtime architecture identifiers
|
||||
if [ "${{ inputs.build_arch }}" = "arm64" ]; then
|
||||
AI_ARCH="aarch64"
|
||||
else
|
||||
AI_ARCH="x86_64"
|
||||
fi
|
||||
export ARCH="$AI_ARCH"
|
||||
|
||||
# --- Assemble the AppDir ---------------------------------------------
|
||||
rm -rf "$APPDIR"
|
||||
mkdir -p "$APPDIR/usr/bin" "$APPDIR/usr/share/applications" \
|
||||
"$APPDIR/usr/share/icons/hicolor/scalable/apps"
|
||||
|
||||
cp -r "$PUBLISH_DIR/." "$APPDIR/usr/bin/"
|
||||
chmod +x "$APPDIR/usr/bin/$APP_NAME"
|
||||
|
||||
# Icon (use the prebuilt 256x256 project icon)
|
||||
ICON_SRC="LANCommander.Launcher/Assets/icon.png"
|
||||
ICON_DIR="$APPDIR/usr/share/icons/hicolor/256x256/apps"
|
||||
mkdir -p "$ICON_DIR"
|
||||
cp "$ICON_SRC" "$ICON_DIR/lancommander.png"
|
||||
|
||||
cp "$ICON_DIR/lancommander.png" "$APPDIR/lancommander.png"
|
||||
ln -sf lancommander.png "$APPDIR/.DirIcon"
|
||||
|
||||
# Desktop entry
|
||||
cat > "$APPDIR/usr/share/applications/lancommander.desktop" <<'EOF'
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=LANCommander Launcher
|
||||
Comment=LANCommander Launcher
|
||||
Exec=LANCommander.Launcher
|
||||
Icon=lancommander
|
||||
Categories=Game;
|
||||
Terminal=false
|
||||
EOF
|
||||
cp "$APPDIR/usr/share/applications/lancommander.desktop" "$APPDIR/lancommander.desktop"
|
||||
|
||||
# AppRun entry point
|
||||
cat > "$APPDIR/AppRun" <<'EOF'
|
||||
#!/bin/bash
|
||||
HERE="$(dirname "$(readlink -f "${0}")")"
|
||||
export PATH="${HERE}/usr/bin:${PATH}"
|
||||
export LD_LIBRARY_PATH="${HERE}/usr/bin:${LD_LIBRARY_PATH:-}"
|
||||
exec "${HERE}/usr/bin/LANCommander.Launcher" "$@"
|
||||
EOF
|
||||
chmod +x "$APPDIR/AppRun"
|
||||
|
||||
# --- Fetch appimagetool ----------------------------------------------
|
||||
TOOL_URL="https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${AI_ARCH}.AppImage"
|
||||
curl -L -o appimagetool "$TOOL_URL"
|
||||
chmod +x appimagetool
|
||||
|
||||
# --- Build the AppImage ----------------------------------------------
|
||||
OUT="LANCommander.Launcher-Linux-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.AppImage"
|
||||
./appimagetool --appimage-extract-and-run "$APPDIR" "$OUT"
|
||||
|
||||
echo "Produced $OUT"
|
||||
|
||||
- name: Upload AppImage Artifact (Linux)
|
||||
if: inputs.build_platform == 'Linux'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: LANCommander.Launcher-Linux-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.AppImage
|
||||
name: LANCommander.Launcher-Linux-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.AppImage
|
||||
|
||||
- name: Compress Build Output
|
||||
if: inputs.build_platform != 'macOS'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$compress = @{
|
||||
Path = "LANCommander.Launcher/bin/${{ inputs.build_configuration }}/net10.0/${{ inputs.build_runtime }}/publish/*"
|
||||
DestinationPath = "LANCommander.Launcher-${{ 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.Launcher-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip
|
||||
name: LANCommander.Launcher-${{ inputs.build_platform }}-${{ inputs.build_arch }}-v${{ inputs.version_tag }}.zip
|
||||
482
.github/workflows/LANCommander.Nightly.yml
vendored
|
|
@ -1,482 +0,0 @@
|
|||
name: LANCommander Nightly
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Runs every day at 3AM CST
|
||||
# CST is UTC-6, so midnight CST = 09:00 UTC
|
||||
- cron: '0 9 * * *'
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: lancommander/lancommander
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
jobs:
|
||||
# --------------------------------------------------------------------------
|
||||
# 1) PREP JOB: figure out the latest semver, build nightly version,
|
||||
# check if there are commits since the last nightly tag. If none,
|
||||
# skip the rest of the workflow.
|
||||
# --------------------------------------------------------------------------
|
||||
prep:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version_semver: ${{ steps.set_version.outputs.VERSION_SEMVER }}
|
||||
version_tag: ${{ steps.set_version.outputs.VERSION_TAG }}
|
||||
changed: ${{ steps.check_diff.outputs.changed }}
|
||||
build_dotnet_version: 10.0.100
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Ensure we get all tags so we can find the latest
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine last semver and build nightly version
|
||||
id: set_version
|
||||
shell: bash
|
||||
run: |
|
||||
# Fetch all tags
|
||||
git fetch --tags
|
||||
|
||||
# Grab the last semver-ish tag (e.g., "v1.2.3", "v1.2.3-debug", or "1.2.3-nightly")
|
||||
LAST_SEMVER_TAG="$(git tag --list --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+' | head -n1)"
|
||||
|
||||
if [ -z "$LAST_SEMVER_TAG" ]; then
|
||||
echo "No semver tag found; defaulting to 0.0.0"
|
||||
LAST_SEMVER_TAG="0.0.0"
|
||||
fi
|
||||
|
||||
# Remove prefix 'v' and any suffix like "-debug", "-nightly", etc.
|
||||
CLEAN_TAG="$(echo "${LAST_SEMVER_TAG#v}" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+')"
|
||||
|
||||
# Build a nightly version string, e.g., "1.2.3-nightly.20250127"
|
||||
DATE=$(date +'%Y%m%d')
|
||||
FINAL_VERSION="${CLEAN_TAG}-nightly.${DATE}"
|
||||
|
||||
echo "Last semver tag: $LAST_SEMVER_TAG"
|
||||
echo "Clean semver tag: $CLEAN_TAG"
|
||||
echo "Nightly version: $FINAL_VERSION"
|
||||
|
||||
# Set output variables for GitHub Actions
|
||||
echo "VERSION_SEMVER=$CLEAN_TAG" >> $GITHUB_ENV
|
||||
echo "VERSION_TAG=$FINAL_VERSION" >> $GITHUB_ENV
|
||||
echo "::set-output name=VERSION_SEMVER::$CLEAN_TAG"
|
||||
echo "::set-output name=VERSION_TAG::$FINAL_VERSION"
|
||||
|
||||
- name: Check if commits since last nightly tag
|
||||
id: check_diff
|
||||
shell: bash
|
||||
run: |
|
||||
# Fetch the last nightly tag
|
||||
LAST_NIGHTLY_TAG="$(git tag --list --sort=-v:refname | grep -E 'nightly\.20[0-9]+' | head -n1 || true)"
|
||||
|
||||
if [ -z "$LAST_NIGHTLY_TAG" ]; then
|
||||
echo "No previous nightly tag found. Marking as changed."
|
||||
echo "::set-output name=changed::true"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check for commits since that tag
|
||||
set +e # Disable exit on error temporarily
|
||||
COMMITS=$(git log "${LAST_NIGHTLY_TAG}"..HEAD --oneline 2>/dev/null || true)
|
||||
set -e # Re-enable exit on error
|
||||
|
||||
if [ -z "$COMMITS" ]; then
|
||||
echo "No commits since last nightly tag: $LAST_NIGHTLY_TAG"
|
||||
echo "::set-output name=changed::false"
|
||||
else
|
||||
echo "Found commits since $LAST_NIGHTLY_TAG"
|
||||
echo "::set-output name=changed::true"
|
||||
fi
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 2) BUILD JOBS (Server/Launcher) - only run if changes == 'true'
|
||||
# Each calls your local workflow YAML with correct indentation
|
||||
# --------------------------------------------------------------------------
|
||||
build_server_linux_arm64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Linux
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_linux_x64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-x64
|
||||
build_arch: x64
|
||||
build_platform: Linux
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_osx_arm64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-arm64
|
||||
build_arch: arm64
|
||||
build_platform: macOS
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_osx_x64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-x64
|
||||
build_arch: x64
|
||||
build_platform: macOS
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_win_arm64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Windows
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_win_x64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-x64
|
||||
build_arch: x64
|
||||
build_platform: Windows
|
||||
build_configuration: Debug
|
||||
|
||||
build_launcher_linux_arm64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Linux
|
||||
build_configuration: Debug
|
||||
|
||||
build_launcher_linux_x64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-x64
|
||||
build_arch: x64
|
||||
build_platform: Linux
|
||||
build_configuration: Debug
|
||||
|
||||
build_launcher_osx_arm64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-arm64
|
||||
build_arch: arm64
|
||||
build_platform: macOS
|
||||
build_configuration: Debug
|
||||
|
||||
build_launcher_osx_x64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-x64
|
||||
build_arch: x64
|
||||
build_platform: macOS
|
||||
build_configuration: Debug
|
||||
|
||||
build_launcher_win_arm64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Windows
|
||||
build_configuration: Debug
|
||||
|
||||
build_launcher_win_x64:
|
||||
needs: [prep]
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-x64
|
||||
build_arch: x64
|
||||
build_platform: Windows
|
||||
build_configuration: Debug
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 3) FINALIZE: if changes == 'true', gather artifacts + push Docker:nightly
|
||||
# --------------------------------------------------------------------------
|
||||
publish_docker_image:
|
||||
needs:
|
||||
- prep
|
||||
- build_server_linux_arm64
|
||||
- build_server_linux_x64
|
||||
- build_server_osx_arm64
|
||||
- build_server_osx_x64
|
||||
- build_server_win_arm64
|
||||
- build_server_win_x64
|
||||
if: needs.prep.outputs.changed == 'true' && github.repository_owner == 'LANCommander'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# 3c) Build and push Docker image with tag "nightly"
|
||||
- name: Checkout Repo for Docker build
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=nightly
|
||||
type=raw,value=${{ needs.prep.outputs.version_tag }}
|
||||
|
||||
- name: Download Server x64 Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: ./
|
||||
|
||||
- name: Download Server arm64 Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: ./
|
||||
|
||||
- name: Extract Server Artifacts x64
|
||||
run: |
|
||||
mkdir -p ./LANCommander.Server/published-amd64
|
||||
unzip ./LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip -d ./LANCommander.Server/published-amd64
|
||||
|
||||
- name: Extract Server Artifacts arm64
|
||||
run: |
|
||||
mkdir -p ./LANCommander.Server/published-arm64
|
||||
unzip ./LANCommander.Server-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip -d ./LANCommander.Server/published-arm64
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Setup buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./LANCommander.Server
|
||||
file: ./LANCommander.Server/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}:nightly
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}:v${{ needs.prep.outputs.version_tag }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
VERSION=${{ needs.prep.outputs.version_tag }}
|
||||
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
provenance: true
|
||||
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
|
||||
- name: Save version to artifact
|
||||
run: echo "${{ needs.prep.outputs.version_tag }}" > version.txt
|
||||
|
||||
- name: Upload version artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: version.${{ needs.prep.outputs.version_tag }}
|
||||
path: version.txt
|
||||
publish_nightly_release:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prep
|
||||
- publish_docker_image
|
||||
- build_launcher_linux_arm64
|
||||
- build_launcher_linux_x64
|
||||
- build_launcher_osx_arm64
|
||||
- build_launcher_osx_x64
|
||||
- build_launcher_win_arm64
|
||||
- build_launcher_win_x64
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create Temp Directory
|
||||
run: mkdir -p artifacts
|
||||
|
||||
- name: Download Server Linux ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Server Linux x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Server macOS ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-macOS-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Server macOS x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-macOS-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Server Windows ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Windows-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Server Windows x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Windows-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Linux ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Linux x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher macOS ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-macOS-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher macOS x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-macOS-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Windows ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Windows-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Windows x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Windows-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Linux ARM64 AppImage
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.AppImage
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Linux x64 AppImage
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Linux-x64-v${{ needs.prep.outputs.version_tag }}.AppImage
|
||||
path: artifacts
|
||||
|
||||
- name: Create or update nightly release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Create the release if it doesn't exist, otherwise update its metadata
|
||||
if gh release view nightly > /dev/null 2>&1; then
|
||||
# Remove all existing assets so only this nightly's files remain
|
||||
gh release view nightly --json assets -q '.assets[].name' | while read -r asset; do
|
||||
gh release delete-asset nightly "$asset" -y
|
||||
done
|
||||
|
||||
gh release edit nightly \
|
||||
--prerelease \
|
||||
--title "Nightly Build v${{ needs.prep.outputs.version_tag }}" \
|
||||
--notes "This is the latest nightly build. These builds are generated automatically and should be considered unstable."
|
||||
else
|
||||
gh release create nightly \
|
||||
--prerelease \
|
||||
--title "Nightly Build v${{ needs.prep.outputs.version_tag }}" \
|
||||
--notes "This is the latest nightly build. These builds are generated automatically and should be considered unstable."
|
||||
fi
|
||||
|
||||
# Upload new artifacts
|
||||
gh release upload nightly artifacts/*
|
||||
229
.github/workflows/LANCommander.PR.yml
vendored
|
|
@ -1,229 +0,0 @@
|
|||
name: LANCommander Pull Request
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
- ready_for_review
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: read
|
||||
checks: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
prep:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version_semver: ${{ steps.set_version.outputs.version_semver }}
|
||||
version_tag: ${{ steps.set_version.outputs.version_tag }}
|
||||
build_dotnet_version: 9.0.102
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine build metadata
|
||||
id: set_version
|
||||
shell: bash
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
RUN_NUMBER: ${{ github.run_number }}
|
||||
run: |
|
||||
TIMESTAMP=$(date -u +"%Y%m%d%H%M")
|
||||
TIME_COMPONENT=$(date -u +"%H%M")
|
||||
TIME_COMPONENT=$((10#$TIME_COMPONENT))
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
BUILD_COMPONENT=$((PR_NUMBER % 65535))
|
||||
if [ "$BUILD_COMPONENT" -eq 0 ]; then
|
||||
BUILD_COMPONENT=1
|
||||
fi
|
||||
VERSION_SEMVER="0.0.${BUILD_COMPONENT}.${TIME_COMPONENT}"
|
||||
VERSION_TAG="0.0.${BUILD_COMPONENT}-pr.${PR_NUMBER}.${TIMESTAMP}"
|
||||
else
|
||||
BUILD_COMPONENT=$((RUN_NUMBER % 65535))
|
||||
if [ "$BUILD_COMPONENT" -eq 0 ]; then
|
||||
BUILD_COMPONENT=1
|
||||
fi
|
||||
VERSION_SEMVER="0.0.${BUILD_COMPONENT}.${TIME_COMPONENT}"
|
||||
VERSION_TAG="0.0.${BUILD_COMPONENT}-ci.${RUN_NUMBER}.${TIMESTAMP}"
|
||||
fi
|
||||
|
||||
echo "version_semver=$VERSION_SEMVER" >> $GITHUB_OUTPUT
|
||||
echo "version_tag=$VERSION_TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
ui_tests:
|
||||
needs: [prep]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install Node packages
|
||||
run: |
|
||||
npm install --prefix ./LANCommander.UI
|
||||
npm install --prefix ./LANCommander.Server
|
||||
|
||||
# The Monaco editor's PowerShell completions are generated (gitignored) and
|
||||
# required by the frontend webpack build. The in-build MSBuild target uses
|
||||
# Windows-style paths, so generate explicitly here for the Linux runner.
|
||||
- name: Generate PowerShell Completions
|
||||
run: dotnet run --project ./LANCommander.CompletionGenerator/LANCommander.CompletionGenerator.csproj -- ./LANCommander.UI/Components/MonacoCodeEditor/PowerShellCompletions.g.ts
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore LANCommander.Server.UI.Tests
|
||||
|
||||
- name: Build test project
|
||||
run: dotnet build LANCommander.Server.UI.Tests --no-restore --configuration Release
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: pwsh LANCommander.Server.UI.Tests/bin/Release/net10.0/playwright.ps1 install --with-deps chromium
|
||||
|
||||
- name: Run UI tests
|
||||
run: dotnet test LANCommander.Server.UI.Tests --no-build --configuration Release --logger "trx;LogFileName=ui-test-results.trx" --results-directory ./TestResults
|
||||
env:
|
||||
SCREENSHOT_DIR: ${{ github.workspace }}/TestResults/Screenshots
|
||||
|
||||
- name: Test report
|
||||
if: always()
|
||||
uses: dorny/test-reporter@v1
|
||||
with:
|
||||
name: UI Test Results
|
||||
path: ./TestResults/ui-test-results.trx
|
||||
reporter: dotnet-trx
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ui-test-results
|
||||
path: ./TestResults
|
||||
retention-days: 7
|
||||
|
||||
build_server_linux_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Linux
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_linux_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-x64
|
||||
build_arch: x64
|
||||
build_platform: Linux
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_osx_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-arm64
|
||||
build_arch: arm64
|
||||
build_platform: macOS
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_osx_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-x64
|
||||
build_arch: x64
|
||||
build_platform: macOS
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_win_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Windows
|
||||
build_configuration: Debug
|
||||
|
||||
build_server_win_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-x64
|
||||
build_arch: x64
|
||||
build_platform: Windows
|
||||
build_configuration: Debug
|
||||
|
||||
build_launcher_linux_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-x64
|
||||
build_arch: x64
|
||||
build_platform: Linux
|
||||
build_configuration: Debug
|
||||
|
||||
build_launcher_win_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-x64
|
||||
build_arch: x64
|
||||
build_platform: Windows
|
||||
build_configuration: Debug
|
||||
|
||||
launcher_tests:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.Tests.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
|
||||
launcher_tests_pr_comment:
|
||||
# Always run after the test job — even on failure — so visual regressions
|
||||
# show up as a PR comment instead of being buried in the artifact.
|
||||
needs: [launcher_tests]
|
||||
if: always() && needs.launcher_tests.result != 'cancelled' && github.event.pull_request.number != null
|
||||
uses: ./.github/workflows/LANCommander.Launcher.Tests.PRComment.yml
|
||||
with:
|
||||
pr_number: ${{ github.event.pull_request.number }}
|
||||
artifact_run_id: ${{ github.run_id }}
|
||||
100
.github/workflows/LANCommander.Packager.yml
vendored
|
|
@ -1,100 +0,0 @@
|
|||
name: LANCommander Packager 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: false
|
||||
type: string
|
||||
default: '10.0.x'
|
||||
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: windows-latest
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ inputs.build_dotnet_version }}
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Publish Packager
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Strip leading 'v' if present
|
||||
$RawVersion = "${{ inputs.version_tag }}"
|
||||
$Semver = $RawVersion -replace '^v', ''
|
||||
|
||||
# Numeric part only for Assembly/FileVersion
|
||||
$Numeric = ($Semver -split '-')[0]
|
||||
$AssemblyVersion = "$Numeric.0"
|
||||
|
||||
Write-Host "SEMVER=$Semver"
|
||||
Write-Host "ASSEMBLY_VERSION=$AssemblyVersion"
|
||||
|
||||
dotnet publish "./LANCommander.Packager/LANCommander.Packager.csproj" `
|
||||
-c "${{ inputs.build_configuration }}" `
|
||||
--self-contained `
|
||||
--runtime win-x86 `
|
||||
-p:Version="$Semver" `
|
||||
-p:AssemblyVersion="$AssemblyVersion" `
|
||||
-p:FileVersion="$AssemblyVersion" `
|
||||
-p:InformationalVersion="$Semver" `
|
||||
-p:PublishSingleFile=true `
|
||||
-p:IncludeNativeLibrariesForSelfExtract=true `
|
||||
-p:IncludeAllContentForSelfExtract=true `
|
||||
-p:EnableCompressionInSingleFile=true `
|
||||
-p:DebugType=embedded
|
||||
|
||||
- name: Clean
|
||||
shell: pwsh
|
||||
run: |
|
||||
$BasePath = "LANCommander.Packager/bin/${{ inputs.build_configuration }}/net10.0/win-x86/publish"
|
||||
Remove-Item -Recurse -Force -ErrorAction Continue "$BasePath/*.pdb"
|
||||
|
||||
- name: Compress Build Output
|
||||
shell: pwsh
|
||||
run: |
|
||||
$compress = @{
|
||||
Path = "LANCommander.Packager/bin/${{ inputs.build_configuration }}/net10.0/win-x86/publish/*"
|
||||
DestinationPath = "LANCommander.Packager-Windows-x86-v${{ inputs.version_tag }}.zip"
|
||||
CompressionLevel = "Fastest"
|
||||
}
|
||||
Compress-Archive @compress
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: LANCommander.Packager-Windows-x86-v${{ inputs.version_tag }}.zip
|
||||
name: LANCommander.Packager-Windows-x86-v${{ inputs.version_tag }}.zip
|
||||
526
.github/workflows/LANCommander.Release.yml
vendored
|
|
@ -3,437 +3,131 @@ name: LANCommander Release
|
|||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
- 'v*.*.*-*'
|
||||
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: lancommander/lancommander
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
jobs:
|
||||
# --------------------------------------------------------------------------
|
||||
# 1) PREP JOB: figure out the latest semver, build nightly version,
|
||||
# check if there are commits since the last nightly tag. If none,
|
||||
# skip the rest of the workflow.
|
||||
# --------------------------------------------------------------------------
|
||||
prep:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version_tag: ${{ steps.trim_tag_ref.outputs.replaced }}
|
||||
version_semver: ${{ steps.trim_tag_ref.outputs.replaced }}
|
||||
is_prerelease: ${{ steps.check_prerelease.outputs.is_prerelease }}
|
||||
build_dotnet_version: 9.0.102
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Ensure we get all tags so we can find the latest
|
||||
fetch-depth: 0
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
- uses: frabert/replace-string-action@v2
|
||||
name: Trim Tag Ref
|
||||
id: trim_tag_ref
|
||||
with:
|
||||
string: '${{ github.ref }}'
|
||||
pattern: 'refs/tags/v'
|
||||
replace-with: ''
|
||||
|
||||
- name: Check if pre-release
|
||||
id: check_prerelease
|
||||
run: |
|
||||
VERSION="${{ steps.trim_tag_ref.outputs.replaced }}"
|
||||
if [[ "$VERSION" == *-* ]]; then
|
||||
echo "is_prerelease=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "is_prerelease=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Server
|
||||
build_server_linux_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Linux
|
||||
build_configuration: Release
|
||||
|
||||
build_server_linux_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-x64
|
||||
build_arch: x64
|
||||
build_platform: Linux
|
||||
build_configuration: Release
|
||||
|
||||
build_server_osx_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-arm64
|
||||
build_arch: arm64
|
||||
build_platform: macOS
|
||||
build_configuration: Release
|
||||
|
||||
build_server_osx_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-x64
|
||||
build_arch: x64
|
||||
build_platform: macOS
|
||||
build_configuration: Release
|
||||
|
||||
build_server_win_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Windows
|
||||
build_configuration: Release
|
||||
|
||||
build_server_win_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Server.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-x64
|
||||
build_arch: x64
|
||||
build_platform: Windows
|
||||
build_configuration: Release
|
||||
|
||||
# Launcher
|
||||
build_launcher_linux_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Linux
|
||||
build_configuration: Release
|
||||
|
||||
build_launcher_linux_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: linux-x64
|
||||
build_arch: x64
|
||||
build_platform: Linux
|
||||
build_configuration: Release
|
||||
|
||||
build_launcher_osx_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-arm64
|
||||
build_arch: arm64
|
||||
build_platform: macOS
|
||||
build_configuration: Release
|
||||
|
||||
build_launcher_osx_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: osx-x64
|
||||
build_arch: x64
|
||||
build_platform: macOS
|
||||
build_configuration: Release
|
||||
|
||||
build_launcher_win_arm64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-arm64
|
||||
build_arch: arm64
|
||||
build_platform: Windows
|
||||
build_configuration: Release
|
||||
|
||||
build_launcher_win_x64:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Launcher.yml
|
||||
with:
|
||||
build_dotnet_version: ${{ needs.prep.outputs.build_dotnet_version }}
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_runtime: win-x64
|
||||
build_arch: x64
|
||||
build_platform: Windows
|
||||
build_configuration: Release
|
||||
|
||||
# Packager (Windows x86 only)
|
||||
build_packager:
|
||||
needs: [prep]
|
||||
uses: ./.github/workflows/LANCommander.Packager.yml
|
||||
with:
|
||||
build_dotnet_version: '10.0.x'
|
||||
version_semver: ${{ needs.prep.outputs.version_semver }}
|
||||
version_tag: ${{ needs.prep.outputs.version_tag }}
|
||||
build_configuration: Release
|
||||
|
||||
build_release:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prep
|
||||
- build_server_linux_arm64
|
||||
- build_server_linux_x64
|
||||
- build_server_osx_arm64
|
||||
- build_server_osx_x64
|
||||
- build_server_win_arm64
|
||||
- build_server_win_x64
|
||||
- build_launcher_linux_arm64
|
||||
- build_launcher_linux_x64
|
||||
- build_launcher_osx_arm64
|
||||
- build_launcher_osx_x64
|
||||
- build_launcher_win_arm64
|
||||
- build_launcher_win_x64
|
||||
- build_packager
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Create Temp Directory
|
||||
run: mkdir -p artifacts
|
||||
- uses: frabert/replace-string-action@v2
|
||||
name: Trim Tag Ref
|
||||
id: trim_tag_ref
|
||||
with:
|
||||
string: '${{ github.ref }}'
|
||||
pattern: 'refs/tags/v'
|
||||
replace-with: ''
|
||||
|
||||
- name: Download Server Linux ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
- uses: frabert/replace-string-action@v2
|
||||
name: Swap Path Backslashes
|
||||
id: swap_path_backslashes
|
||||
with:
|
||||
string: '${{ github.workspace }}'
|
||||
pattern: '\\'
|
||||
replace-with: '/'
|
||||
flags: g
|
||||
|
||||
- name: Download Server Linux x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
# Server
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v3.8.1
|
||||
- run: cd LANCommander/wwwroot/scripts; npm install
|
||||
|
||||
- name: Download Server macOS ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-macOS-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
# Windows
|
||||
- name: Publish Windows
|
||||
run: dotnet publish "./LANCommander/LANCommander.csproj" -c Release -o _Build_Windows --self-contained --os win -p:PublishSingleFile=true -p:Version="${{ steps.trim_tag_ref.outputs.replaced }}" -p:AssemblyVersion="${{ steps.trim_tag_ref.outputs.replaced }}"
|
||||
- name: Publish Windows Updater
|
||||
run: dotnet publish "./LANCommander.AutoUpdater/LANCommander.AutoUpdater.csproj" -c Release -o _Build_Windows --self-contained --os win -p:Version="${{ steps.trim_tag_ref.outputs.replaced }}" -p:AssemblyVersion="${{ steps.trim_tag_ref.outputs.replaced }}"
|
||||
- name: Rename Windows Updater
|
||||
run: mv ./_Build_Windows/LANCommander.AutoUpdater.exe ./_Build_Windows/LANCommander.AutoUpdater.exe.Update
|
||||
- name: Remove Windows Extra Files
|
||||
run: rm -Recurse -Force ./_Build_Windows/wwwroot/_content/AntDesign/less
|
||||
|
||||
- name: Download Server macOS x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-macOS-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
# Sign Windows Binary
|
||||
- name: Sign Windows Binary
|
||||
uses: nadeemjazmawe/Sign-action-signtool.exe@v0.1
|
||||
with:
|
||||
certificate: "${{ secrets.CERTIFICATE }}"
|
||||
cert-password: "${{ secrets.CERTIFICATE_PASSWORD }}"
|
||||
filepath: "./_Build_Windows/LANCommander.exe"
|
||||
|
||||
- name: Download Server Windows ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Windows-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
# Create Windows ZIP file
|
||||
- name: Package Windows Build
|
||||
uses: vimtor/action-zip@v1.2
|
||||
with:
|
||||
files: _Build_Windows/
|
||||
recursive: true
|
||||
dest: LANCommander-Windows-x64-v${{ steps.trim_tag_ref.outputs.replaced }}.zip
|
||||
|
||||
- name: Download Server Windows x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Windows-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
# Linux
|
||||
- name: Publish Linux
|
||||
run: dotnet publish "./LANCommander/LANCommander.csproj" -c Release -o _Build_Linux --self-contained --os linux -p:PublishSingleFile=true -p:Version="${{ steps.trim_tag_ref.outputs.replaced }}" -p:AssemblyVersion="${{ steps.trim_tag_ref.outputs.replaced }}"
|
||||
- name: Remove Linux Extra Files
|
||||
run: rm -Recurse -Force ./_Build_Linux/wwwroot/_content/AntDesign/less
|
||||
|
||||
# Launcher artifacts
|
||||
- name: Download Launcher Linux ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
# Create Linux ZIP file
|
||||
- name: Package Linux Build
|
||||
uses: vimtor/action-zip@v1.2
|
||||
with:
|
||||
files: _Build_Linux/
|
||||
recursive: true
|
||||
dest: LANCommander-Linux-x64-v${{ steps.trim_tag_ref.outputs.replaced }}.zip
|
||||
|
||||
- name: Download Launcher Linux x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
# Client
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v1.3.1
|
||||
- name: Setup NuGet
|
||||
uses: NuGet/setup-nuget@v1.1.1
|
||||
- name: Restore NuGet packages
|
||||
run: nuget restore LANCommander.sln
|
||||
- name: Build and Publish Library
|
||||
run: msbuild LANCommander.Playnite.Extension/LANCommander.PlaynitePlugin.csproj /p:Configuration=Release /p:OutputPath=Build /p:Version="${{ steps.trim_tag_ref.outputs.replaced }}" /p:InformationalVersion="${{ steps.trim_tag_ref.outputs.replaced }}"
|
||||
- name: Sign Windows Binary
|
||||
uses: nadeemjazmawe/Sign-action-signtool.exe@v0.1
|
||||
with:
|
||||
certificate: "${{ secrets.CERTIFICATE }}"
|
||||
cert-password: "${{ secrets.CERTIFICATE_PASSWORD }}"
|
||||
filepath: "./LANCommander.Playnite.Extension/Build/LANCommander.PlaynitePlugin.dll"
|
||||
- name: Download Playnite Release
|
||||
uses: robinraju/release-downloader@v1.7
|
||||
with:
|
||||
repository: JosefNemec/Playnite
|
||||
tag: 10.32
|
||||
fileName: Playnite1032.zip
|
||||
- name: Extract Playnite
|
||||
run: Expand-Archive -Path Playnite1032.zip -DestinationPath Playnite
|
||||
- name: Update Manifest Versioning
|
||||
uses: fjogeleit/yaml-update-action@main
|
||||
with:
|
||||
valueFile: "LANCommander.Playnite.Extension/Build/extension.yaml"
|
||||
propertyPath: "Version"
|
||||
value: "${{ steps.trim_tag_ref.outputs.replaced }}"
|
||||
commitChange: false
|
||||
- name: Run Playnite Toolbox
|
||||
run: Playnite/Toolbox.exe pack LANCommander.Playnite.Extension/Build .
|
||||
|
||||
- name: Download Launcher macOS ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-macOS-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
- name: List contents of workspace
|
||||
run: Get-ChildItem -Path ${{ steps.swap_path_backslashes.outputs.replaced }} -Recurse
|
||||
|
||||
- name: Download Launcher macOS x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-macOS-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Windows ARM64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Windows-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Windows x64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Windows-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Linux ARM64 AppImage
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.AppImage
|
||||
path: artifacts
|
||||
|
||||
- name: Download Launcher Linux x64 AppImage
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Launcher-Linux-x64-v${{ needs.prep.outputs.version_tag }}.AppImage
|
||||
path: artifacts
|
||||
|
||||
- name: Download Packager Windows x86
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Packager-Windows-x86-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: artifacts
|
||||
|
||||
- name: Debug - List Artifact Files
|
||||
run: |
|
||||
echo "Contents of ./artifacts:"
|
||||
ls -la ./artifacts
|
||||
|
||||
- name: Draft Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: v${{ needs.prep.outputs.version_tag }}
|
||||
generate_release_notes: true
|
||||
draft: true
|
||||
prerelease: ${{ needs.prep.outputs.is_prerelease == 'true' }}
|
||||
files: |
|
||||
artifacts/LANCommander.Server-Windows-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Server-Windows-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Server-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Server-macOS-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Server-macOS-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Launcher-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Launcher-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Launcher-macOS-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Launcher-macOS-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Launcher-Windows-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Launcher-Windows-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
artifacts/LANCommander.Launcher-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.AppImage
|
||||
artifacts/LANCommander.Launcher-Linux-x64-v${{ needs.prep.outputs.version_tag }}.AppImage
|
||||
artifacts/LANCommander.Packager-Windows-x86-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
|
||||
- name: Checkout Repo for Docker build
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download Server x64 Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: ./
|
||||
|
||||
- name: Extract Server Artifacts
|
||||
run: |
|
||||
mkdir -p ./LANCommander.Server/published
|
||||
unzip ./LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip -d ./LANCommander.Server/published
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Download Server x64 Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: ./
|
||||
|
||||
- name: Download Server arm64 Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: LANCommander.Server-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip
|
||||
path: ./
|
||||
|
||||
- name: Extract Server Artifacts x64
|
||||
run: |
|
||||
mkdir -p ./LANCommander.Server/published-amd64
|
||||
unzip ./LANCommander.Server-Linux-x64-v${{ needs.prep.outputs.version_tag }}.zip -d ./LANCommander.Server/published-amd64
|
||||
|
||||
- name: Extract Server Artifacts arm64
|
||||
run: |
|
||||
mkdir -p ./LANCommander.Server/published-arm64
|
||||
unzip ./LANCommander.Server-Linux-arm64-v${{ needs.prep.outputs.version_tag }}.zip -d ./LANCommander.Server/published-arm64
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Setup buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./LANCommander.Server
|
||||
file: ./LANCommander.Server/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}:v${{ needs.prep.outputs.version_tag }}
|
||||
${{ needs.prep.outputs.is_prerelease == 'true' && format('{0}/{1}:prerelease', env.REGISTRY, env.IMAGE_NAME) || format('{0}/{1}:latest', env.REGISTRY, env.IMAGE_NAME) }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
VERSION=${{ needs.prep.outputs.version_tag }}
|
||||
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
provenance: true
|
||||
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
- name: Draft Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: v${{ steps.trim_tag_ref.outputs.replaced }}
|
||||
generate_release_notes: true
|
||||
draft: true
|
||||
files: |
|
||||
${{ steps.swap_path_backslashes.outputs.replaced }}/LANCommander-Windows-x64-*.zip
|
||||
${{ steps.swap_path_backslashes.outputs.replaced }}/LANCommander-Linux-x64-*.zip
|
||||
LANCommander.PlaynitePlugin_48e1bac7-e0a0-45d7-ba83-36f5e9e959fc_*.pext
|
||||
|
|
|
|||
56
.github/workflows/LANCommander.SDK.Release.yml
vendored
|
|
@ -1,56 +0,0 @@
|
|||
name: LANCommander SDK Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
prep:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version_tag: ${{ steps.trim_tag_ref.outputs.replaced }}
|
||||
version_semver: ${{ steps.extract_semver.outputs.replaced }}
|
||||
steps:
|
||||
- uses: frabert/replace-string-action@v2
|
||||
name: Trim Tag Ref
|
||||
id: trim_tag_ref
|
||||
with:
|
||||
string: '${{ github.ref }}'
|
||||
pattern: 'refs/tags/v'
|
||||
replace-with: ''
|
||||
|
||||
- uses: frabert/replace-string-action@v2
|
||||
name: Extract SemVer (strip prerelease suffix for AssemblyVersion)
|
||||
id: extract_semver
|
||||
with:
|
||||
string: '${{ steps.trim_tag_ref.outputs.replaced }}'
|
||||
pattern: '-.*$'
|
||||
replace-with: ''
|
||||
|
||||
publish:
|
||||
needs: prep
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '9.0.102'
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore LANCommander.SDK/LANCommander.SDK.csproj
|
||||
|
||||
- name: Build project
|
||||
run: dotnet build --configuration Release LANCommander.SDK/LANCommander.SDK.csproj -p:Version="${{ needs.prep.outputs.version_tag }}" -p:AssemblyVersion="${{ needs.prep.outputs.version_semver }}"
|
||||
|
||||
- name: Pack NuGet package with symbols
|
||||
run: dotnet pack LANCommander.SDK/LANCommander.SDK.csproj --no-build --configuration Release -p:PackageVersion=${{ needs.prep.outputs.version_tag }} -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg -o ./artifacts
|
||||
|
||||
- name: Publish NuGet package
|
||||
run: |
|
||||
dotnet nuget push ./artifacts/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
|
||||
241
.github/workflows/LANCommander.Server.yml
vendored
|
|
@ -1,241 +0,0 @@
|
|||
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
|
||||
121
.github/workflows/LANCommander.WinGet.Release.yml
vendored
|
|
@ -1,121 +0,0 @@
|
|||
name: Publish to WinGet
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
create-installers:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
app: ['Server', 'Launcher']
|
||||
arch: ['x64', 'arm64']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get version
|
||||
id: get_version
|
||||
shell: pwsh
|
||||
run: |
|
||||
$tag = '${{ github.ref_name }}'
|
||||
$version = $tag.TrimStart('v')
|
||||
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
|
||||
- name: Download release artifact
|
||||
shell: pwsh
|
||||
run: |
|
||||
$releaseAsset = "LANCommander.${{ matrix.app }}-Windows-${{ matrix.arch }}-v${{ env.VERSION }}.zip"
|
||||
gh release download ${{ github.ref_name }} -p $releaseAsset
|
||||
Expand-Archive $releaseAsset -DestinationPath ".\extracted"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Install Inno Setup
|
||||
- name: Install Inno Setup
|
||||
run: |
|
||||
curl -L -o innosetup.exe https://github.com/jrsoftware/issrc/releases/download/is-6_7_3/innosetup-6.7.3.exe
|
||||
.\innosetup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
|
||||
shell: cmd
|
||||
|
||||
# Create Inno Setup script
|
||||
- name: Create installer script
|
||||
run: |
|
||||
$appId = if ('${{ matrix.app }}' -eq 'Server') {
|
||||
'2C58E237-1D69-42A0-B702-F995B75B8A5E'
|
||||
} else {
|
||||
'A3D4F8E1-7B2C-4E5D-9F1A-6C8B3D7E2F4A'
|
||||
}
|
||||
|
||||
@"
|
||||
#define MyAppName "LANCommander ${{ matrix.app }}"
|
||||
#define MyAppVersion "${{ env.VERSION }}"
|
||||
#define MyAppPublisher "LANCommander"
|
||||
#define MyAppURL "https://github.com/${{ github.repository }}"
|
||||
#define MyAppExeName "LANCommander.${{ matrix.app }}.exe"
|
||||
#define Architecture "${{ matrix.arch }}"
|
||||
|
||||
[Setup]
|
||||
AppId={{$appId}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={autopf}\LANCommander\{#MyAppName}
|
||||
DisableProgramGroupPage=yes
|
||||
OutputBaseFilename=LANCommander.${{ matrix.app }}-{#MyAppVersion}-{#Architecture}-Setup
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
ArchitecturesAllowed=${{ matrix.arch == 'x64' && 'x64' || 'arm64' }}
|
||||
ArchitecturesInstallIn64BitMode=${{ matrix.arch == 'x64' && 'x64' || 'arm64' }}
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Files]
|
||||
Source: "extracted\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
"@ | Out-File -FilePath "installer.iss" -Encoding UTF8
|
||||
shell: pwsh
|
||||
|
||||
# Build installer
|
||||
- name: Build installer
|
||||
run: |
|
||||
& 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' installer.iss
|
||||
shell: pwsh
|
||||
|
||||
# Upload installer to release
|
||||
- name: Upload installer to release
|
||||
run: |
|
||||
gh release upload ${{ github.ref_name }} "Output/LANCommander.${{ matrix.app }}-${{ env.VERSION }}-${{ matrix.arch }}-Setup.exe"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
publish-winget:
|
||||
needs: create-installers
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
app: ['Server', 'Launcher']
|
||||
steps:
|
||||
- name: Get version
|
||||
shell: pwsh
|
||||
run: |
|
||||
$tag = '${{ github.ref_name }}'
|
||||
$version = $tag.TrimStart('v')
|
||||
echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
|
||||
- name: Install wingetcreate
|
||||
shell: pwsh
|
||||
run: |
|
||||
Invoke-WebRequest -Uri "https://aka.ms/wingetcreate/latest" -OutFile wingetcreate.exe
|
||||
|
||||
- name: Submit package to Windows Package Manager Community Repository
|
||||
run: |
|
||||
$x64Url = "https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/LANCommander.${{ matrix.app }}-${env:VERSION}-x64-Setup.exe"
|
||||
$arm64Url = "https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/LANCommander.${{ matrix.app }}-${env:VERSION}-arm64-Setup.exe"
|
||||
.\wingetcreate.exe update --submit --token "${{ secrets.WINGET_TOKEN }}" --urls $x64Url $arm64Url --version ${env:VERSION} LANCommander.${{ matrix.app }}
|
||||
shell: pwsh
|
||||
35
.gitignore
vendored
|
|
@ -17,6 +17,10 @@
|
|||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
|
|
@ -351,34 +355,3 @@ LANCommander/Saves/
|
|||
LANCommander/Media/
|
||||
LANCommander/Uploads/
|
||||
LANCommander/Updates/
|
||||
LANCommander/Launcher
|
||||
LANCommander/dist
|
||||
LANCommander/wwwroot/scripts/dist
|
||||
LANCommander.Server/Media
|
||||
LANCommander.Server/Uploads
|
||||
LANCommander.Server/Updates
|
||||
LANCommander.Server/Saves
|
||||
LANCommander.Server/Launcher
|
||||
LANCommander.Server/Settings.yml
|
||||
LANCommander.Server/LANCommander.db*
|
||||
LANCommander.Server/wwwroot/css/custom.css
|
||||
LANCommander.Server/wwwroot/css/app.css*
|
||||
LANCommander.Launcher/wwwroot/css/app.css*
|
||||
LANCommander.Launcher/wwwroot/css/main.js
|
||||
LANCommander.Server/wwwroot/css/main.js
|
||||
|
||||
.aspire
|
||||
LANCommander.Server/config/
|
||||
LANCommander.UI/wwwroot/
|
||||
LANCommander.UI/Components/MonacoCodeEditor/PowerShellCompletions.g.ts
|
||||
LANCommander.Server/Data/
|
||||
|
||||
LANCommander.Launcher.Avalonia/Data/
|
||||
|
||||
Data/
|
||||
|
||||
# Visual test output — screenshots & diffs are CI artifacts, not committed.
|
||||
# Baselines/ is committed; everything else is transient.
|
||||
LANCommander.Launcher.Avalonia.Tests/Screenshots/
|
||||
LANCommander.Launcher.Avalonia.Tests/Diffs/
|
||||
visual-test-output/
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
# Contributing to LANCommander
|
||||
|
||||
Thanks for your interest in contributing to LANCommander! This project is primarily developed by a single developer, so community contributions are greatly appreciated.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [.NET 10.0 SDK](https://dotnet.microsoft.com/download/dotnet/10.0)
|
||||
- [Node.js](https://nodejs.org/) (for the server UI's TypeScript/SCSS assets)
|
||||
- A code editor such as [Visual Studio](https://visualstudio.microsoft.com/), [Rider](https://www.jetbrains.com/rider/), or [VS Code](https://code.visualstudio.com/)
|
||||
|
||||
### Building the Project
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/LANCommander/LANCommander.git
|
||||
cd LANCommander
|
||||
```
|
||||
|
||||
2. Restore dependencies:
|
||||
```bash
|
||||
dotnet restore
|
||||
```
|
||||
|
||||
3. Build the server:
|
||||
```bash
|
||||
dotnet build LANCommander.Server
|
||||
```
|
||||
|
||||
4. Build the launcher:
|
||||
```bash
|
||||
dotnet build LANCommander.Launcher
|
||||
```
|
||||
|
||||
### Running Locally
|
||||
|
||||
To run the server in development mode:
|
||||
```bash
|
||||
dotnet run --project LANCommander.Server
|
||||
```
|
||||
|
||||
The server will be available at `http://localhost:1337` by default.
|
||||
|
||||
## How to Contribute
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
Use the [GitHub Issues](https://github.com/LANCommander/LANCommander/issues) page with the bug report template. Include:
|
||||
- Steps to reproduce the issue
|
||||
- Expected vs. actual behavior
|
||||
- Your OS and LANCommander version
|
||||
- Relevant logs or screenshots
|
||||
|
||||
### Submitting Changes
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch from `main` (`git checkout -b my-feature`)
|
||||
3. Make your changes
|
||||
4. Test your changes locally
|
||||
5. Commit with a clear, descriptive message
|
||||
6. Push to your fork and open a Pull Request
|
||||
|
||||
### What to Work On
|
||||
|
||||
- Check [open issues](https://github.com/LANCommander/LANCommander/issues) for bugs or feature requests
|
||||
- Documentation improvements are always welcome at our [documentation site](https://docs.lancommander.app/)
|
||||
- Game packaging scripts and guides for the community
|
||||
|
||||
### Code Guidelines
|
||||
|
||||
- Follow existing code style and conventions in the project
|
||||
- Keep PRs focused, one feature or fix per PR when possible
|
||||
- Include screenshots in your PR if you're changing UI
|
||||
|
||||
## Project Structure
|
||||
|
||||
| Directory | Description |
|
||||
|-----------|-------------|
|
||||
| `LANCommander.Server` | ASP.NET Blazor web application (server/admin) |
|
||||
| `LANCommander.Launcher` | Avalonia desktop client (launcher) |
|
||||
| `LANCommander.Packager` | Game packaging tool |
|
||||
| `LANCommander.SDK` | .NET SDK for building custom clients |
|
||||
| `LANCommander.Server.Data` | Entity Framework data models and migrations |
|
||||
| `LANCommander.Server.Services` | Server business logic |
|
||||
| `LANCommander.Documentation` | Docusaurus documentation site |
|
||||
|
||||
## Community
|
||||
|
||||
- [Discord](https://discord.gg/vDEEWVt8EM): Best place for discussion, help, and sharing game packages
|
||||
|
||||
## License
|
||||
|
||||
By contributing to LANCommander, you agree that your contributions will be licensed under the [MIT License](LICENSE).
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Aspire">
|
||||
<PackageVersion Include="Aspire.Hosting.AppHost" Version="9.5.0" />
|
||||
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.1.1" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
|
||||
<PackageVersion Include="EasyMDE.Blazor" Version="1.0.5" />
|
||||
<PackageVersion Include="HotAvalonia" Version="3.1.0" />
|
||||
<PackageVersion Include="LiveChartsCore" Version="2.0.0-rc5.4" />
|
||||
<PackageVersion Include="LiveChartsCore.SkiaSharpView" Version="2.0.0-rc5.4" />
|
||||
<PackageVersion Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" />
|
||||
<PackageVersion Include="Markdig" Version="0.44.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Configuration" Version="9.0.8" />
|
||||
<PackageVersion Include="Notify.NET" Version="1.1.0" />
|
||||
<PackageVersion Include="Svrooij.PowerShell.DI" Version="1.3.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="AutoMapper">
|
||||
<PackageVersion Include="AutoMapper" Version="14.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="AntDesign">
|
||||
<PackageVersion Include="AntDesign" Version="1.5.0" />
|
||||
<PackageVersion Include="AntDesign.Charts" Version="0.8.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Blazor">
|
||||
<PackageVersion Include="BlazorMonaco" Version="3.4.0" />
|
||||
<PackageVersion Include="BootstrapBlazor.PdfReader" Version="9.0.1" />
|
||||
<PackageVersion Include="PSC.Blazor.Components.MarkdownEditor" Version="8.0.8" />
|
||||
<PackageVersion Include="Razor.Templating.Core" Version="2.1.0" />
|
||||
<PackageVersion Include="XtermBlazor" Version="2.1.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Utility">
|
||||
<PackageVersion Include="ByteSize" Version="2.1.2" />
|
||||
<PackageVersion Include="CaseConverter" Version="2.0.1" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="HtmlAgilityPack" Version="1.11.72" />
|
||||
<PackageVersion Include="Crc32.NET" Version="1.2.0" />
|
||||
<PackageVersion Include="Emzi0767.NtfsDataStreams" Version="1.0.0" />
|
||||
<PackageVersion Include="PeanutButter.INI" Version="3.0.396" />
|
||||
<PackageVersion Include="Superpower" Version="3.1.0" />
|
||||
<PackageVersion Include="RegParserDotNet" Version="1.1.1" />
|
||||
<PackageVersion Include="nulastudio.NetBeauty" Version="2.1.4.6" />
|
||||
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageVersion Include="NetEscapades.Configuration.Yaml" Version="3.1.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="ASP.NET Core">
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client.SourceGenerator" Version="7.0.0-preview.7.22376.6" />
|
||||
<PackageVersion Include="Scalar.AspNetCore" Version="2.0.11" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Code Analysis">
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis" Version="4.12.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.12.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Features" Version="4.12.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Features" Version="4.12.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Scripting.Common" Version="4.12.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.12.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Testing">
|
||||
<PackageVersion Include="bunit" Version="1.40.0" />
|
||||
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageVersion Include="Microsoft.Playwright" Version="1.51.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
||||
<PackageVersion Include="Microsoft.TypeScript.MSBuild" Version="5.7.1" />
|
||||
<PackageVersion Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
|
||||
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
|
||||
<PackageVersion Include="Moq" Version="4.20.72" />
|
||||
<PackageVersion Include="Shouldly" Version="4.3.0" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.11" />
|
||||
<PackageVersion Include="Syncfusion.PdfToImageConverter.Net" Version="28.2.4" />
|
||||
<PackageVersion Include="Xunit.Extensions.TestDependency" Version="1.1.0" />
|
||||
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="External">
|
||||
<PackageVersion Include="CoreRCON" Version="5.0.5" />
|
||||
<PackageVersion Include="LANCommander.HQ.SDK" Version="1.0.1" />
|
||||
<PackageVersion Include="craftersmine.SteamGridDB.Net" Version="1.1.7" />
|
||||
<PackageVersion Include="YoutubeExplode" Version="6.4.3" />
|
||||
<PackageVersion Include="Docker.DotNet.Enhanced" Version="3.129.0" />
|
||||
<PackageVersion Include="Facepunch.Steamworks" Version="2.3.3" />
|
||||
<PackageVersion Include="IGDB" Version="6.1.0" />
|
||||
<PackageVersion Include="IPXRelayDotNet" Version="1.1.3" />
|
||||
<PackageVersion Include="LANCommander.Interposer" Version="1.0.7" />
|
||||
<PackageVersion Include="Octokit" Version="14.0.0" />
|
||||
<PackageVersion Include="RestSharp" Version="112.1.0" />
|
||||
<PackageVersion Include="rix0rrr.BeaconLib" Version="1.0.2" />
|
||||
<PackageVersion Include="Semver" Version="3.0.0" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.50.0" />
|
||||
<PackageVersion Include="SteamWebAPI2" Version="4.4.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Entity Framework Core">
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.9" />
|
||||
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0" />
|
||||
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Hangfire">
|
||||
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.17" />
|
||||
<PackageVersion Include="Hangfire.Core" Version="1.8.17" />
|
||||
<PackageVersion Include="Hangfire.InMemory" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="PowerShell">
|
||||
<PackageVersion Include="Microsoft.PowerShell.Commands.Diagnostics" Version="7.4.7" />
|
||||
<PackageVersion Include="Microsoft.PowerShell.SDK" Version="7.4.7" />
|
||||
<PackageVersion Include="System.Management.Automation" Version="7.4.7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Microsoft Extensions">
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.7.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Localization" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="9.4.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="OpenTelemetry">
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.12.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="LibVLC">
|
||||
<PackageVersion Include="LibVLCSharp" Version="3.8.5" />
|
||||
<PackageVersion Include="LibVLCSharp.Avalonia" Version="3.8.5" />
|
||||
<PackageVersion Include="VideoLAN.LibVLC.Windows" Version="3.0.23.1" />
|
||||
<PackageVersion Include="VideoLAN.LibVLC.Mac" Version="3.1.3.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="SDL">
|
||||
<PackageVersion Include="ppy.SDL3-CS" Version="2026.520.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Photino">
|
||||
<PackageVersion Include="AsyncImageLoader.Avalonia" Version="3.3.0" />
|
||||
<PackageVersion Include="Avalonia" Version="11.2.3" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.2.3" />
|
||||
<PackageVersion Include="Avalonia.Headless" Version="11.2.3" />
|
||||
<PackageVersion Include="Avalonia.Headless.XUnit" Version="11.2.3" />
|
||||
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.2.3" />
|
||||
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.2.3" />
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.3" />
|
||||
<PackageVersion Include="Avalonia.Controls.ItemsRepeater" Version="11.1.5" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.2.0.2" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageVersion Include="PDFtoImage" Version="4.1.1" />
|
||||
<PackageVersion Include="Photino.Blazor" Version="4.0.13" />
|
||||
<PackageVersion Include="Photino.Blazor.CustomWindow" Version="1.3.1" />
|
||||
<PackageVersion Include="Photino.NET" Version="4.0.16" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="System">
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.1" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.3.1" />
|
||||
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Caching">
|
||||
<PackageVersion Include="ZiggyCreatures.FusionCache" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Overlay">
|
||||
<PackageVersion Include="Avalonia.Skia" Version="11.2.3" />
|
||||
<PackageVersion Include="Reloaded.Hooks" Version="4.3.0" />
|
||||
<PackageVersion Include="DNNE" Version="2.1.0" />
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
52
Docker/Dockerfile
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM ghcr.io/linuxserver/baseimage-ubuntu:jammy
|
||||
|
||||
# set version label
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION
|
||||
LABEL build_version="LANCommander version:- ${VERSION} Build-date:- ${BUILD_DATE}, container based on github.com/LinuxServer/baseimage-ubuntu"
|
||||
LABEL maintainer="bashNinja"
|
||||
|
||||
# copy local files
|
||||
COPY root/ /
|
||||
|
||||
# grab app
|
||||
ADD "https://github.com/LANCommander/LANCommander/releases/download/${VERSION}/LANCommander-Linux-x64-${VERSION}.zip" "/tmp"
|
||||
|
||||
# install app
|
||||
RUN \
|
||||
echo "**** install packages ****" && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
jq \
|
||||
libicu70 \
|
||||
sqlite3 \
|
||||
unzip && \
|
||||
echo "**** setup lancommander ****" && \
|
||||
unzip "/tmp/LANCommander-Linux-x64-${VERSION}.zip" -d /app/LANCommander && \
|
||||
chmod +x /app/LANCommander/LANCommander && \
|
||||
ls -alh /app/LANCommander && \
|
||||
echo "**** setup symlinks ****" && \
|
||||
ln -s /config/Uploads/ /app/LANCommander/Uploads && \
|
||||
ln -s /config/Updates/ /app/LANCommander/Updates && \
|
||||
ln -s /config/Saves/ /app/LANCommander/Saves && \
|
||||
ln -s /config/Media/ /app/LANCommander/Media && \
|
||||
ln -s /config/Logs/ /app/LANCommander/Logs && \
|
||||
ln -s /config/Backups/ /app/LANCommander/Backups && \
|
||||
ln -s /config/Settings.yml /app/LANCommander/Settings.yml && \
|
||||
ln -s /config/LANCommander.db /app/LANCommander/LANCommander.db && \
|
||||
ln -s /config/internal.log /app/LANCommander/internal.log && \
|
||||
echo "**** cleanup ****" && \
|
||||
apt-get -y autoremove && \
|
||||
apt-get clean && \
|
||||
rm -rf \
|
||||
/tmp/* \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/tmp/*
|
||||
|
||||
# ports and volumes
|
||||
EXPOSE 1337/tcp
|
||||
EXPOSE 35891/udp
|
||||
|
||||
VOLUME /config
|
||||
32
Docker/root/defaults/Settings.yml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
Port: 1337
|
||||
DatabaseConnectionString: Data Source=LANCommander.db;Cache=Shared
|
||||
IGDBClientId: ''
|
||||
IGDBClientSecret: ''
|
||||
Beacon:
|
||||
Enabled: true
|
||||
Address: ''
|
||||
Authentication:
|
||||
TokenSecret: ''
|
||||
TokenLifetime: 30
|
||||
PasswordRequireDigit: true
|
||||
PasswordRequiredLength: 8
|
||||
Roles: {}
|
||||
UserSaves:
|
||||
StoragePath: /config/Saves
|
||||
MaxSize: 25
|
||||
Archives:
|
||||
StoragePath: /config/Uploads
|
||||
Media:
|
||||
SteamGridDbApiKey: ''
|
||||
StoragePath: /config/Media
|
||||
MaxSize: 25
|
||||
IPXRelay:
|
||||
Host: ''
|
||||
Port: 213
|
||||
Wiki:
|
||||
Username: ''
|
||||
Password: ''
|
||||
Update:
|
||||
StoragePath: /config/Updates
|
||||
Logs:
|
||||
StoragePath: /config/Logs
|
||||
21
Docker/root/etc/s6-overlay/s6-rc.d/init-files-folders-config/run
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
# make our folders for LANCommander
|
||||
mkdir -p \
|
||||
/config/{Uploads,Updates,Saves,Media,Logs,Backups}
|
||||
|
||||
# files needed by LANCommander
|
||||
if [[ ! -f /config/Settings.yml ]]; then
|
||||
cp /defaults/Settings.yml /config/Settings.yml
|
||||
fi
|
||||
if [[ ! -f /config/LANCommander.db ]]; then
|
||||
sqlite3 /config/LANCommander.db "VACUUM;"
|
||||
fi
|
||||
if [[ ! -f /config/internal.log ]]; then
|
||||
touch /config/internal.log
|
||||
fi
|
||||
|
||||
# permissions
|
||||
lsiown -R abc:abc \
|
||||
/config
|
||||
|
|
@ -0,0 +1 @@
|
|||
oneshot
|
||||
|
|
@ -0,0 +1 @@
|
|||
/etc/s6-overlay/s6-rc.d/init-files-folders-config/run
|
||||
9
Docker/root/etc/s6-overlay/s6-rc.d/svc-lancommander/data/check
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
PORT=$(grep '^Port:' /config/Settings.yml | awk '{ print $2 }')
|
||||
|
||||
if [[ $(curl -s -o /dev/null -w '%{http_code}' "http://localhost:${PORT:-1337}/") -eq 200 ]]; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1 @@
|
|||
3
|
||||
6
Docker/root/etc/s6-overlay/s6-rc.d/svc-lancommander/run
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
exec \
|
||||
s6-notifyoncheck -d -n 300 -w 1000 \
|
||||
cd /app/LANCommander s6-setuidgid abc /app/LANCommander/LANCommander
|
||||
1
Docker/root/etc/s6-overlay/s6-rc.d/svc-lancommander/type
Normal file
|
|
@ -0,0 +1 @@
|
|||
longrun
|
||||
BIN
Docs/AddGame.gif
Normal file
|
After Width: | Height: | Size: 2.9 MiB |
BIN
Docs/ArchiveUploading.gif
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
Docs/ChangeKey.png
Normal file
|
After Width: | Height: | Size: 647 KiB |
BIN
Docs/Dashboard.gif
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
Docs/EditingScript.gif
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
Docs/GamesList.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
Docs/InstallingGames.gif
Normal file
|
After Width: | Height: | Size: 12 MiB |
BIN
Docs/KeyManagement.gif
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
Docs/PlayniteAuthentication.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
|
|
@ -1,14 +0,0 @@
|
|||
using Projects;
|
||||
|
||||
var builder = DistributedApplication.CreateBuilder(args);
|
||||
|
||||
var server = builder
|
||||
.AddProject<LANCommander_Server>("Server")
|
||||
.WithExternalHttpEndpoints();
|
||||
|
||||
var launcher = builder
|
||||
.AddProject<LANCommander_Launcher>("Launcher")
|
||||
.WithReference(server)
|
||||
.WaitFor(server);
|
||||
|
||||
builder.Build().Run();
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="9.4.0"/>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<UserSecretsId>0899617b-b319-465d-aaaf-aac7ea333029</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LANCommander.Launcher\LANCommander.Launcher.csproj" />
|
||||
<ProjectReference Include="..\LANCommander.Server\LANCommander.Server.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:17134;http://localhost:15274",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"DOTNET_ENVIRONMENT": "Development",
|
||||
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21013",
|
||||
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22279"
|
||||
}
|
||||
},
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:15274",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"DOTNET_ENVIRONMENT": "Development",
|
||||
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19171",
|
||||
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20001"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Aspire.Hosting.Dcp": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<PublishAot>true</PublishAot>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -16,13 +16,11 @@ Console.WriteLine("Waiting for LANCommander to stop...");
|
|||
int delay = 500;
|
||||
int maxAttempts = 30 * (1000 / delay);
|
||||
|
||||
string processName = Path.GetFileNameWithoutExtension(arguments["Executable"]);
|
||||
|
||||
for (int i = 0; i < maxAttempts; i++)
|
||||
{
|
||||
var stillRunning = Process.GetProcessesByName(processName).Any();
|
||||
var processes = Process.GetProcessesByName("LANCommander");
|
||||
|
||||
if (!stillRunning)
|
||||
if (processes.Length == 0)
|
||||
break;
|
||||
else if (i == maxAttempts - 1)
|
||||
throw new Exception("Cannot update! LANCommander is still running!");
|
||||
|
|
@ -53,12 +51,7 @@ finally
|
|||
{
|
||||
Console.WriteLine("Starting LANCommander...");
|
||||
|
||||
var executable = "LANCommander.exe";
|
||||
|
||||
if (arguments.ContainsKey("Executable"))
|
||||
executable = arguments["Executable"];
|
||||
|
||||
Process.Start(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, executable));
|
||||
Process.Start(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LANCommander.exe"));
|
||||
|
||||
Console.WriteLine("LANCommander has been started! My job here is done");
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
"profiles": {
|
||||
"LANCommander.AutoUpdater": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "-Version \"0.4.1\" -Path \"Updates\" -Executable \"LANCommander.Server.exe\""
|
||||
"commandLineArgs": "-Version \"0.4.1\" -Path \"Updates\""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
function Build-Launcher {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[SemVer] $Version,
|
||||
[String] $Runtime,
|
||||
[String] $Architecture,
|
||||
[String] $Platform,
|
||||
[String] $Configuration
|
||||
)
|
||||
|
||||
$AssemblyVersion = "$($Version.Major).$($Version.Minor).$($Version.Patch)"
|
||||
$RuntimeIdentifier = "$Runtime-$Architecture"
|
||||
|
||||
dotnet restore
|
||||
|
||||
npm install --prefix ./LANCommander.UI
|
||||
npm install --prefix ./LANCommander.Launcher
|
||||
|
||||
dotnet publish ./LANCommander.AutoUpdater/LANCommander.AutoUpdater.csproj -c $Configuration --self-contained --runtime $RuntimeIdentifier -p:Version="$Version" -p:AssemblyVersion="$AssemblyVersion"
|
||||
dotnet publish ./LANCommander.Launcher/LANCommander.Launcher.csproj -c $Configuration --self-contained --runtime $RuntimeIdentifier -p:Version="$Version" -p:AssemblyVersion="$AssemblyVersion"
|
||||
dotnet publish ./LANCommander.Launcher.CLI/LANCommander.Launcher.CLI.csproj -c $Configuration --self-contained --runtime $RuntimeIdentifier -p:Version="$Version" -p:AssemblyVersion="$AssemblyVersion"
|
||||
|
||||
Copy-Item -Force -Recurse -Verbose LANCommander.AutoUpdater/bin/$Configuration/net9.0/$RuntimeIdentifier/publish/* LANCommander.Launcher/bin/$Configuration/net9.0/$RuntimeIdentifier/publish/
|
||||
Copy-Item -Force -Recurse -Verbose LANCommander.Launcher.CLI/bin/$Configuration/net9.0/$RuntimeIdentifier/publish/* LANCommander.Launcher/bin/$Configuration/net9.0/$RuntimeIdentifier/publish/
|
||||
|
||||
$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.Launcher/bin/$Configuration/net9.0/$RuntimeIdentifier/publish"
|
||||
|
||||
foreach ($path in $PathsToRemove) {
|
||||
Remove-Item -Force -Recurse -ErrorAction SilentlyContinue "$BasePath/$path"
|
||||
}
|
||||
|
||||
$Compress = @{
|
||||
Path = "LANCommander.Launcher/bin/$Configuration/net9.0/$RuntimeIdentifier/publish/*"
|
||||
DestinationPath = "LANCommander.Launcher-$Platform-$Architecture-v$Version.zip"
|
||||
CompressionLevel = "Fastest"
|
||||
}
|
||||
|
||||
Compress-Archive @compress
|
||||
|
||||
$Compress.Path
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
function Build-Server {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[SemVer] $Version,
|
||||
[String] $Runtime,
|
||||
[String] $Architecture,
|
||||
[String] $Platform,
|
||||
[String] $Configuration
|
||||
)
|
||||
|
||||
$AssemblyVersion = "$($Version.Major).$($Version.Minor).$($Version.Patch)"
|
||||
$RuntimeIdentifier = "$Runtime-$Architecture"
|
||||
|
||||
dotnet restore
|
||||
|
||||
npm install --prefix ./LANCommander.UI
|
||||
npm install --prefix ./LANCommander.Server
|
||||
|
||||
dotnet publish ./LANCommander.AutoUpdater/LANCommander.AutoUpdater.csproj -c $Configuration --self-contained --runtime $RuntimeIdentifier -p:Version="$Version" -p:AssemblyVersion="$AssemblyVersion"
|
||||
dotnet publish ./LANCommander.Server/LANCommander.Server.csproj -c $Configuration --self-contained --runtime $RuntimeIdentifier -p:Version="$Version" -p:AssemblyVersion="$AssemblyVersion"
|
||||
|
||||
Copy-Item -Force -Recurse -Verbose LANCommander.AutoUpdater/bin/$Configuration/net9.0/$RuntimeIdentifier/publish/* LANCommander.Server/bin/$Configuration/net9.0/$RuntimeIdentifier/publish/
|
||||
|
||||
$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/$Configuration/net9.0/$RuntimeIdentifier/publish"
|
||||
|
||||
foreach ($path in $PathsToRemove) {
|
||||
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$BasePath/$path"
|
||||
}
|
||||
|
||||
$Compress = @{
|
||||
Path = "LANCommander.Server/bin/$Configuration/net9.0/$RuntimeIdentifier/publish/*"
|
||||
DestinationPath = "LANCommander.Server-$Platform-$Architecture-v$Version.zip"
|
||||
CompressionLevel = "Fastest"
|
||||
}
|
||||
|
||||
Compress-Archive @compress
|
||||
|
||||
$Compress.Path
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
function Get-LastSemVerTag {
|
||||
[OutputType([semver])]
|
||||
param()
|
||||
|
||||
git fetch --tags
|
||||
|
||||
$lastTag = git tag --list | Where-Object { $_ -match '^v?\d+\.\d+\.\d+$' } | Sort-Object -Descending | Select-Object -First 1
|
||||
|
||||
return [semver]$lastTag.TrimStart('v')
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
. ./LANCommander.Build/Include/Get-LastSemVerTag.ps1
|
||||
. ./LANCommander.Build/Include/Build-Server.ps1
|
||||
. ./LANCommander.Build/Include/Build-Launcher.ps1
|
||||
|
||||
$Version = Get-LastSemVerTag
|
||||
$Version = [semver]"$($Version.Major).$($Version.Minor).$($Version.Patch)-nightly.$(Get-Date -Format "yyyyMMddHHmm")"
|
||||
|
||||
$BuildTargets =
|
||||
@{ Platform = 'Windows'; Architecture = 'x64'; Runtime = 'win' },
|
||||
@{ Platform = 'Windows'; Architecture = 'arm64'; Runtime = 'win' },
|
||||
@{ Platform = 'Linux'; Architecture = 'x64'; Runtime = 'linux' },
|
||||
@{ Platform = 'Linux'; Architecture = 'arm64'; Runtime = 'linux' },
|
||||
@{ Platform = 'macOS'; Architecture = 'x64'; Runtime = 'osx' },
|
||||
@{ Platform = 'macOS'; Architecture = 'arm64'; Runtime = 'osx' }
|
||||
|
||||
Write-Host "Building Targets"
|
||||
|
||||
foreach ($target in $BuildTargets) {
|
||||
Build-Server -Version $Version -Runtime $target.Runtime -Architecture $target.Architecture -Platform $target.Platform -Configuration 'Debug'
|
||||
Build-Launcher -Version $Version -Runtime $target.Runtime -Architecture $target.Architecture -Platform $target.Platform -Configuration 'Debug'
|
||||
}
|
||||
|
|
@ -1,54 +1,23 @@
|
|||
using LANCommander.Launcher.Data.Interceptors;
|
||||
using LANCommander.Launcher.Data.Models;
|
||||
using LANCommander.SDK;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using LANCommander.Client.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Data
|
||||
namespace LANCommander.Client.Data
|
||||
{
|
||||
public class DatabaseContext : DbContext
|
||||
{
|
||||
private readonly ILoggerFactory LoggerFactory;
|
||||
|
||||
public DatabaseContext() { }
|
||||
|
||||
public DatabaseContext(ILoggerFactory loggerFactory, DbContextOptions options)
|
||||
public DatabaseContext(DbContextOptions options)
|
||||
: base(options)
|
||||
{
|
||||
LoggerFactory = loggerFactory;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
// Skip the SQLite default when the caller has already chosen a provider
|
||||
// (e.g. tests using EF InMemory) — EF errors out if two providers are registered.
|
||||
if (optionsBuilder.IsConfigured)
|
||||
return;
|
||||
var dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LANCommander.db");
|
||||
|
||||
var dbPath = AppPaths.GetConfigPath("LANCommander.db");
|
||||
|
||||
var connectionString = new SqliteConnectionStringBuilder
|
||||
{
|
||||
DataSource = dbPath,
|
||||
Cache = SqliteCacheMode.Shared,
|
||||
}.ToString();
|
||||
|
||||
optionsBuilder.AddInterceptors(new AuditingInterceptor());
|
||||
optionsBuilder.UseLoggerFactory(LoggerFactory);
|
||||
optionsBuilder.UseSqlite(connectionString, options =>
|
||||
{
|
||||
options.CommandTimeout(30);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables WAL mode for concurrent reads during background writes.
|
||||
/// Should be called once after the database is created/migrated.
|
||||
/// </summary>
|
||||
public async Task EnableWalModeAsync()
|
||||
{
|
||||
await Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL;");
|
||||
optionsBuilder.UseSqlite($"Data Source={dbPath};Cache=Shared");
|
||||
optionsBuilder.UseLazyLoadingProxies();
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
|
|
@ -72,33 +41,7 @@ namespace LANCommander.Launcher.Data
|
|||
.HasMany(t => t.Games)
|
||||
.WithMany(g => g.Tags);
|
||||
|
||||
builder.Entity<Platform>()
|
||||
.HasMany(p => p.Games)
|
||||
.WithMany(g => g.Platforms);
|
||||
|
||||
builder.Entity<Library>()
|
||||
.HasOne(l => l.User)
|
||||
.WithOne(u => u.Library)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.Entity<Library>()
|
||||
.HasMany(l => l.Games)
|
||||
.WithMany(l => l.Libraries)
|
||||
.UsingEntity<Dictionary<string, object>>(
|
||||
"LibraryGame",
|
||||
lg => lg.HasOne<Game>().WithMany().HasForeignKey("GameId").OnDelete(DeleteBehavior.Cascade),
|
||||
lg => lg.HasOne<Library>().WithMany().HasForeignKey("LibraryId").OnDelete(DeleteBehavior.Cascade)
|
||||
);
|
||||
|
||||
builder.Entity<User>()
|
||||
.HasOne(u => u.Avatar)
|
||||
.WithOne(a => a.User)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
#region Game Relationships
|
||||
builder.Entity<Game>()
|
||||
.Property(g => g.BaseGameId)
|
||||
.HasConversion(new GuidToNullConverter());
|
||||
|
||||
builder.Entity<Game>()
|
||||
.HasMany(g => g.MultiplayerModes)
|
||||
|
|
@ -139,14 +82,6 @@ namespace LANCommander.Launcher.Data
|
|||
gr => gr.HasOne<Game>().WithMany().HasForeignKey("GameId")
|
||||
);
|
||||
|
||||
builder.Entity<Game>()
|
||||
.HasMany(g => g.Tools)
|
||||
.WithMany(t => t.Games)
|
||||
.UsingEntity<GameTool>(
|
||||
gt => gt.HasOne(x => x.Tool).WithMany(t => t.GameTools).HasForeignKey(x => x.ToolId).OnDelete(DeleteBehavior.Cascade),
|
||||
gt => gt.HasOne(x => x.Game).WithMany(g => g.GameTools).HasForeignKey(x => x.GameId).OnDelete(DeleteBehavior.Cascade),
|
||||
gt => gt.HasKey(x => new { x.GameId, x.ToolId }));
|
||||
|
||||
builder.Entity<Game>()
|
||||
.HasMany(g => g.DependentGames)
|
||||
.WithOne(g => g.BaseGame)
|
||||
|
|
@ -158,12 +93,6 @@ namespace LANCommander.Launcher.Data
|
|||
.WithMany(e => e.Games)
|
||||
.IsRequired(false)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
builder.Entity<Game>()
|
||||
.HasMany(g => g.ExternalIds)
|
||||
.WithOne(e => e.Game)
|
||||
.IsRequired(false)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
#endregion
|
||||
|
||||
#region Collection Relationships
|
||||
|
|
@ -178,7 +107,6 @@ namespace LANCommander.Launcher.Data
|
|||
#endregion
|
||||
}
|
||||
|
||||
public DbSet<Engine>? Engines { get; set; }
|
||||
public DbSet<Game>? Games { get; set; }
|
||||
|
||||
public DbSet<Genre>? Genres { get; set; }
|
||||
|
|
@ -192,7 +120,5 @@ namespace LANCommander.Launcher.Data
|
|||
public DbSet<Redistributable>? Redistributables { get; set; }
|
||||
|
||||
public DbSet<Media>? Media { get; set; }
|
||||
public DbSet<Library>? Libraries { get; set; }
|
||||
public DbSet<User>? Users { get; set; }
|
||||
}
|
||||
}
|
||||
16
LANCommander.Client.Data/Enums/GameType.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LANCommander.Client.Data.Enums
|
||||
{
|
||||
public enum GameType
|
||||
{
|
||||
[Display(Name = "Main Game")]
|
||||
MainGame,
|
||||
Expansion,
|
||||
[Display(Name = "Standalone Expansion")]
|
||||
StandaloneExpansion,
|
||||
Mod,
|
||||
[Display(Name = "Standalone Mod")]
|
||||
StandaloneMod
|
||||
}
|
||||
}
|
||||
10
LANCommander.Client.Data/Enums/MediaType.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
namespace LANCommander.Client.Data.Enums
|
||||
{
|
||||
public enum MediaType
|
||||
{
|
||||
Icon,
|
||||
Cover,
|
||||
Background,
|
||||
Avatar
|
||||
}
|
||||
}
|
||||
23
LANCommander.Client.Data/LANCommander.Client.Data.csproj
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LANCommander.SDK\LANCommander.SDK.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using LANCommander.Launcher.Data;
|
||||
using LANCommander.Client.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
|
@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20240522012114_InitialSeed")]
|
||||
|
|
@ -129,7 +129,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("GameTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -155,7 +155,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Collection", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Collection", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -176,7 +176,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Collections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Company", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Company", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -197,7 +197,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Companies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -218,7 +218,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Engines");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -279,7 +279,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Genre", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Genre", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -300,7 +300,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Genres");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -341,7 +341,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Media");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -382,7 +382,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("MultiplayerModes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Redistributable", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Redistributable", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -409,7 +409,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Redistributables");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Tag", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Tag", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -432,13 +432,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CategoryGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -447,13 +447,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CollectionGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Collection", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Collection", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -462,13 +462,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameDeveloper", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("DeveloperId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -477,13 +477,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameGenre", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Genre", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Genre", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GenresId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -492,13 +492,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GamePublisher", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PublisherId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -507,13 +507,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameRedistributable", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Redistributable", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Redistributable", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RedistributableId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -522,36 +522,36 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameTag", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Tag", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Tag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TagsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", "Parent")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", "Parent")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("ParentId");
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "BaseGame")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "BaseGame")
|
||||
.WithMany("DependentGames")
|
||||
.HasForeignKey("BaseGameId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Engine", "Engine")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Engine", "Engine")
|
||||
.WithMany("Games")
|
||||
.HasForeignKey("EngineId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
|
@ -561,9 +561,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Engine");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("Media")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -571,9 +571,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("MultiplayerModes")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -582,17 +582,17 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Navigation("Children");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Navigation("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Navigation("DependentGames");
|
||||
|
||||
|
|
@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialSeed : Migration
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using LANCommander.Launcher.Data;
|
||||
using LANCommander.Client.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
|
@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20240524000735_MultiplayerModeOptionalGame")]
|
||||
|
|
@ -129,7 +129,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("GameTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -155,7 +155,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Collection", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Collection", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -176,7 +176,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Collections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Company", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Company", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -197,7 +197,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Companies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -218,7 +218,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Engines");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -279,7 +279,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Genre", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Genre", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -300,7 +300,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Genres");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -341,7 +341,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Media");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -381,7 +381,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("MultiplayerModes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Redistributable", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Redistributable", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -408,7 +408,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Redistributables");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Tag", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Tag", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -431,13 +431,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CategoryGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -446,13 +446,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CollectionGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Collection", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Collection", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -461,13 +461,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameDeveloper", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("DeveloperId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -476,13 +476,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameGenre", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Genre", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Genre", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GenresId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -491,13 +491,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GamePublisher", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PublisherId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -506,13 +506,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameRedistributable", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Redistributable", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Redistributable", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RedistributableId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -521,36 +521,36 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameTag", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Tag", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Tag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TagsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", "Parent")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", "Parent")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("ParentId");
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "BaseGame")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "BaseGame")
|
||||
.WithMany("DependentGames")
|
||||
.HasForeignKey("BaseGameId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Engine", "Engine")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Engine", "Engine")
|
||||
.WithMany("Games")
|
||||
.HasForeignKey("EngineId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
|
@ -560,9 +560,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Engine");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("Media")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -570,9 +570,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("MultiplayerModes")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -580,17 +580,17 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Navigation("Children");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Navigation("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Navigation("DependentGames");
|
||||
|
||||
|
|
@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class MultiplayerModeOptionalGame : Migration
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using LANCommander.Launcher.Data;
|
||||
using LANCommander.Client.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
|
@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20240525185852_AddGameLatestVersion")]
|
||||
|
|
@ -129,7 +129,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("GameTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -155,7 +155,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Collection", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Collection", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -176,7 +176,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Collections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Company", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Company", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -197,7 +197,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Companies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -218,7 +218,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Engines");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -282,7 +282,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Genre", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Genre", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -303,7 +303,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Genres");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -344,7 +344,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Media");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -384,7 +384,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("MultiplayerModes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Redistributable", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Redistributable", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -411,7 +411,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Redistributables");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Tag", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Tag", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -434,13 +434,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CategoryGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -449,13 +449,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CollectionGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Collection", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Collection", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -464,13 +464,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameDeveloper", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("DeveloperId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -479,13 +479,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameGenre", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Genre", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Genre", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GenresId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -494,13 +494,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GamePublisher", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PublisherId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -509,13 +509,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameRedistributable", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Redistributable", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Redistributable", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RedistributableId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -524,36 +524,36 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameTag", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Tag", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Tag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TagsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", "Parent")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", "Parent")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("ParentId");
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "BaseGame")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "BaseGame")
|
||||
.WithMany("DependentGames")
|
||||
.HasForeignKey("BaseGameId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Engine", "Engine")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Engine", "Engine")
|
||||
.WithMany("Games")
|
||||
.HasForeignKey("EngineId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
|
@ -563,9 +563,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Engine");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("Media")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -573,9 +573,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("MultiplayerModes")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -583,17 +583,17 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Navigation("Children");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Navigation("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Navigation("DependentGames");
|
||||
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddGameLatestVersion : Migration
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using LANCommander.Launcher.Data;
|
||||
using LANCommander.Client.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
|
@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20240603031059_AddLocalPlaySessions")]
|
||||
|
|
@ -129,7 +129,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("GameTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -155,7 +155,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Collection", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Collection", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -176,7 +176,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Collections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Company", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Company", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -197,7 +197,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Companies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -218,7 +218,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Engines");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -282,7 +282,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Genre", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Genre", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -303,7 +303,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Genres");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -344,7 +344,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Media");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -384,7 +384,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("MultiplayerModes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.PlaySession", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.PlaySession", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -415,7 +415,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("PlaySessions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Redistributable", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Redistributable", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -442,7 +442,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Redistributables");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Tag", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Tag", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -465,13 +465,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CategoryGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -480,13 +480,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CollectionGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Collection", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Collection", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -495,13 +495,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameDeveloper", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("DeveloperId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -510,13 +510,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameGenre", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Genre", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Genre", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GenresId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -525,13 +525,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GamePublisher", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PublisherId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -540,13 +540,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameRedistributable", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Redistributable", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Redistributable", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RedistributableId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -555,36 +555,36 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameTag", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Tag", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Tag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TagsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", "Parent")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", "Parent")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("ParentId");
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "BaseGame")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "BaseGame")
|
||||
.WithMany("DependentGames")
|
||||
.HasForeignKey("BaseGameId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Engine", "Engine")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Engine", "Engine")
|
||||
.WithMany("Games")
|
||||
.HasForeignKey("EngineId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
|
@ -594,9 +594,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Engine");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("Media")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -604,9 +604,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("MultiplayerModes")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -614,26 +614,26 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.PlaySession", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.PlaySession", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("PlaySessions")
|
||||
.HasForeignKey("GameId");
|
||||
|
||||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Navigation("Children");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Navigation("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Navigation("DependentGames");
|
||||
|
||||
|
|
@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddLocalPlaySessions : Migration
|
||||
|
|
@ -1,21 +1,18 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using LANCommander.Launcher.Data;
|
||||
using LANCommander.Client.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
namespace LANCommander.Client.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20240620051957_AddMediaName")]
|
||||
partial class AddMediaName
|
||||
partial class DatabaseContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
|
|
@ -129,7 +126,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("GameTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -155,7 +152,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Collection", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Collection", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -176,7 +173,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Collections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Company", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Company", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -197,7 +194,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Companies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -218,7 +215,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Engines");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -282,7 +279,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Genre", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Genre", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -303,7 +300,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Genres");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -327,10 +324,6 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
.HasMaxLength(255)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SourceUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -348,7 +341,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Media");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -388,7 +381,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("MultiplayerModes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.PlaySession", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.PlaySession", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -419,7 +412,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("PlaySessions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Redistributable", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Redistributable", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -446,7 +439,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.ToTable("Redistributables");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Tag", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Tag", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
|
@ -469,13 +462,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CategoryGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -484,13 +477,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("CollectionGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Collection", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Collection", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -499,13 +492,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameDeveloper", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("DeveloperId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -514,13 +507,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameGenre", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Genre", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Genre", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GenresId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -529,13 +522,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GamePublisher", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PublisherId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -544,13 +537,13 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameRedistributable", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Redistributable", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Redistributable", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RedistributableId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
|
|
@ -559,36 +552,36 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
|
||||
modelBuilder.Entity("GameTag", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Tag", null)
|
||||
b.HasOne("LANCommander.Client.Data.Models.Tag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TagsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", "Parent")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Category", "Parent")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("ParentId");
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "BaseGame")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "BaseGame")
|
||||
.WithMany("DependentGames")
|
||||
.HasForeignKey("BaseGameId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Engine", "Engine")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Engine", "Engine")
|
||||
.WithMany("Games")
|
||||
.HasForeignKey("EngineId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
|
@ -598,9 +591,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Engine");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Media", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("Media")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -608,9 +601,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("MultiplayerModes")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
|
@ -618,26 +611,26 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.PlaySession", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.PlaySession", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
b.HasOne("LANCommander.Client.Data.Models.Game", "Game")
|
||||
.WithMany("PlaySessions")
|
||||
.HasForeignKey("GameId");
|
||||
|
||||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Category", b =>
|
||||
{
|
||||
b.Navigation("Children");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Navigation("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
modelBuilder.Entity("LANCommander.Client.Data.Models.Game", b =>
|
||||
{
|
||||
b.Navigation("DependentGames");
|
||||
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
using LANCommander.SDK.Models;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LANCommander.Launcher.Data.Models
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
public abstract class BaseModel : IKeyedModel
|
||||
public abstract class BaseModel
|
||||
{
|
||||
[Key]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Display(Name = "Imported On")]
|
||||
public DateTime ImportedOn { get; set; }
|
||||
|
||||
[Display(Name = "Created On")]
|
||||
public DateTime CreatedOn { get; set; }
|
||||
13
LANCommander.Client.Data/Models/Category.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("Categories")]
|
||||
public class Category : BaseModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public virtual Category Parent { get; set; }
|
||||
public virtual ICollection<Category> Children { get; set; }
|
||||
public virtual ICollection<Game> Games { get; set; }
|
||||
}
|
||||
}
|
||||
13
LANCommander.Client.Data/Models/Collection.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("Collections")]
|
||||
public class Collection : BaseModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
[JsonIgnore]
|
||||
public virtual ICollection<Game> Games { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LANCommander.Launcher.Data.Models
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
public class Company : BaseModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public virtual ICollection<Game> PublishedGames { get; set; } = new List<Game>();
|
||||
public virtual ICollection<Game> PublishedGames { get; set; }
|
||||
[JsonIgnore]
|
||||
public virtual ICollection<Game> DevelopedGames { get; set; } = new List<Game>();
|
||||
public virtual ICollection<Game> DevelopedGames { get; set; }
|
||||
}
|
||||
}
|
||||
11
LANCommander.Client.Data/Models/Engine.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("Engines")]
|
||||
public class Engine : BaseModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public virtual ICollection<Game> Games { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using LANCommander.Client.Data.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LANCommander.SDK.Enums;
|
||||
|
||||
namespace LANCommander.Launcher.Data.Models
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("Games")]
|
||||
public class Game : BaseModel
|
||||
{
|
||||
public virtual ICollection<GameExternalId>? ExternalIds { get; set; } = new List<GameExternalId>();
|
||||
public long? IGDBId { get; set; }
|
||||
public string Title { get; set; }
|
||||
[Display(Name = "Sort Title")]
|
||||
public string? SortTitle { get; set; }
|
||||
|
|
@ -18,7 +18,6 @@ namespace LANCommander.Launcher.Data.Models
|
|||
public bool Installed { get; set; }
|
||||
public string? InstallDirectory { get; set; }
|
||||
public string? InstalledVersion { get; set; }
|
||||
public DateTime? InstalledOn { get; set; }
|
||||
public string? LatestVersion { get; set; }
|
||||
|
||||
[Display(Name = "Released On")]
|
||||
|
|
@ -41,14 +40,10 @@ namespace LANCommander.Launcher.Data.Models
|
|||
public virtual ICollection<Category>? Categories { get; set; } = new List<Category>();
|
||||
public virtual ICollection<Company>? Publishers { get; set; } = new List<Company>();
|
||||
public virtual ICollection<Company>? Developers { get; set; } = new List<Company>();
|
||||
public virtual ICollection<Platform>? Platforms { get; set; } = new List<Platform>();
|
||||
public virtual ICollection<Redistributable>? Redistributables { get; set; } = new List<Redistributable>();
|
||||
public virtual ICollection<Tool>? Tools { get; set; } = new List<Tool>();
|
||||
public virtual ICollection<GameTool> GameTools { get; set; } = new List<GameTool>();
|
||||
public virtual ICollection<Media>? Media { get; set; } = new List<Media>();
|
||||
public virtual ICollection<Collection> Collections { get; set; } = new List<Collection>();
|
||||
public virtual ICollection<Game> DependentGames { get; set; } = new List<Game>();
|
||||
public virtual ICollection<PlaySession> PlaySessions { get; set; } = new List<PlaySession>();
|
||||
public virtual ICollection<Library> Libraries { get; set; } = new List<Library>();
|
||||
}
|
||||
}
|
||||
13
LANCommander.Client.Data/Models/Genre.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("Genres")]
|
||||
public class Genre : BaseModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
[JsonIgnore]
|
||||
public virtual ICollection<Game> Games { get; set; }
|
||||
}
|
||||
}
|
||||
29
LANCommander.Client.Data/Models/Media.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
using LANCommander.Client.Data.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("Media")]
|
||||
public class Media : BaseModel
|
||||
{
|
||||
public Guid FileId { get; set; }
|
||||
public MediaType Type { get; set; }
|
||||
|
||||
[MaxLength(2048)]
|
||||
public string? SourceUrl { get; set; }
|
||||
|
||||
[MaxLength(255)]
|
||||
public string? MimeType { get; set; }
|
||||
|
||||
[MaxLength(8)]
|
||||
public string Crc32 { get; set; }
|
||||
|
||||
public Guid? GameId { get; set; }
|
||||
[JsonIgnore]
|
||||
[ForeignKey(nameof(GameId))]
|
||||
[InverseProperty("Media")]
|
||||
public virtual Game? Game { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
using LANCommander.SDK.Enums;
|
||||
using LANCommander.Client.Data.Enums;
|
||||
using LANCommander.SDK.Enums;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LANCommander.Server.Data.Models
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("MultiplayerModes")]
|
||||
public class MultiplayerMode : BaseModel
|
||||
|
|
@ -17,6 +18,6 @@ namespace LANCommander.Server.Data.Models
|
|||
[JsonIgnore]
|
||||
[ForeignKey(nameof(GameId))]
|
||||
[InverseProperty("MultiplayerModes")]
|
||||
public Game? Game { get; set; }
|
||||
public virtual Game? Game { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LANCommander.Launcher.Data.Models
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("PlaySessions")]
|
||||
public class PlaySession : BaseModel
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LANCommander.Launcher.Data.Models
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("Redistributables")]
|
||||
public class Redistributable : BaseModel
|
||||
|
|
@ -8,6 +8,6 @@ namespace LANCommander.Launcher.Data.Models
|
|||
public string Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public virtual ICollection<Game>? Games { get; set; } = new List<Game>();
|
||||
public virtual ICollection<Game>? Games { get; set; }
|
||||
}
|
||||
}
|
||||
15
LANCommander.Client.Data/Models/Tag.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LANCommander.Client.Data.Models
|
||||
{
|
||||
[Table("Tags")]
|
||||
public class Tag : BaseModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public virtual List<Game> Games { get; set; }
|
||||
}
|
||||
}
|
||||
70
LANCommander.Client.Data/Repository.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
using LANCommander.Client.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace LANCommander.Client.Data
|
||||
{
|
||||
public class Repository<T> : IDisposable where T : BaseModel
|
||||
{
|
||||
private DbContext Context;
|
||||
|
||||
public Repository(DatabaseContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
private DbSet<T> DbSet
|
||||
{
|
||||
get { return Context.Set<T>(); }
|
||||
}
|
||||
|
||||
public IQueryable<T> Get(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
return DbSet.AsQueryable().Where(predicate);
|
||||
}
|
||||
|
||||
public async Task<T> Find(Guid id)
|
||||
{
|
||||
return await DbSet.FindAsync(id);
|
||||
}
|
||||
|
||||
public T FirstOrDefault(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
return Get(predicate).FirstOrDefault();
|
||||
}
|
||||
|
||||
public async Task<T> Add(T entity)
|
||||
{
|
||||
entity.CreatedOn = DateTime.Now;
|
||||
entity.UpdatedOn = DateTime.Now;
|
||||
|
||||
await Context.AddAsync(entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public T Update(T entity)
|
||||
{
|
||||
entity.UpdatedOn = DateTime.Now;
|
||||
|
||||
Context.Update(entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void Delete(T entity)
|
||||
{
|
||||
Context.Remove(entity);
|
||||
}
|
||||
|
||||
public async Task SaveChanges()
|
||||
{
|
||||
await Context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
LANCommander.Client/App.razor
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<Router AppAssembly="@typeof(Program).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(UI.MainLayout)" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(UI.MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
22
LANCommander.Client/Enums/DownloadStatus.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Enums
|
||||
{
|
||||
public enum DownloadStatus
|
||||
{
|
||||
Idle,
|
||||
Downloading,
|
||||
InstallingRedistributables,
|
||||
InstallingMods,
|
||||
InstallingExpansions,
|
||||
RunningScripts,
|
||||
DownloadingSaves,
|
||||
Canceled,
|
||||
Failed,
|
||||
Complete
|
||||
}
|
||||
}
|
||||
24
LANCommander.Client/Extensions/DateTimeExtensions.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Extensions
|
||||
{
|
||||
public static class DateTimeExtensions
|
||||
{
|
||||
public static string ToRelativeDate(this DateTime dateTime)
|
||||
{
|
||||
var today = DateTime.Today;
|
||||
var yesterday = today.AddDays(-1);
|
||||
|
||||
if (dateTime.Day == today.Day && dateTime.Month == today.Month && dateTime.Year == today.Year)
|
||||
return "Today";
|
||||
else if (dateTime.Day == yesterday.Day && dateTime.Month == yesterday.Month && dateTime.Year == yesterday.Year)
|
||||
return "Yesterday";
|
||||
else
|
||||
return dateTime.ToString("MMMM d");
|
||||
}
|
||||
}
|
||||
}
|
||||
24
LANCommander.Client/Extensions/IEnumerableExtensions.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Extensions
|
||||
{
|
||||
internal static class IEnumerableExtensions
|
||||
{
|
||||
static Regex TitleComparisonExpression = new Regex(@"^(?:a|the|an)\s*", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
|
||||
internal static IOrderedEnumerable<T> OrderByTitle<T>(this IEnumerable<T> items, Func<T, string> keySelector)
|
||||
{
|
||||
return items.OrderBy(i =>
|
||||
{
|
||||
var key = keySelector.Invoke(i);
|
||||
|
||||
return TitleComparisonExpression.Replace(key, "");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
19
LANCommander.Client/Extensions/TimeSpanExtensions.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Extensions
|
||||
{
|
||||
public static class TimeSpanExtensions
|
||||
{
|
||||
public static string ToShortTime(this TimeSpan timeSpan)
|
||||
{
|
||||
if (timeSpan.TotalHours >= 1)
|
||||
return timeSpan.ToString("hh\\:mm\\:ss");
|
||||
else
|
||||
return timeSpan.ToString("mm\\:ss");
|
||||
}
|
||||
}
|
||||
}
|
||||
3316
LANCommander.Client/LANCommander.Client.csproj
Normal file
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
|
|
@ -1,15 +1,15 @@
|
|||
using LANCommander.Launcher.Data.Models;
|
||||
using LANCommander.Client.Data.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Launcher.Models
|
||||
namespace LANCommander.Client.Models
|
||||
{
|
||||
public class ActionSelectorDialogOptions
|
||||
{
|
||||
public IEnumerable<SDK.Models.Manifest.Action> Actions { get; set; }
|
||||
public IEnumerable<SDK.Models.Action> Actions { get; set; }
|
||||
public string Title { get; set; }
|
||||
public Game Game { get; set; }
|
||||
}
|
||||
71
LANCommander.Client/Models/DownloadQueueGame.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
using LANCommander.Client.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Models
|
||||
{
|
||||
internal class DownloadQueueGame : IDownloadQueueItem
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Version { get; set; }
|
||||
public Guid CoverId { get; set; }
|
||||
public Guid IconId { get; set; }
|
||||
public DateTime QueuedOn { get; set; }
|
||||
public DateTime? CompletedOn { get; set; }
|
||||
public bool IsUpdate { get; set; }
|
||||
public bool State {
|
||||
get
|
||||
{
|
||||
switch (Status)
|
||||
{
|
||||
case DownloadStatus.Downloading:
|
||||
case DownloadStatus.InstallingRedistributables:
|
||||
case DownloadStatus.InstallingMods:
|
||||
case DownloadStatus.InstallingExpansions:
|
||||
case DownloadStatus.RunningScripts:
|
||||
case DownloadStatus.DownloadingSaves:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public DownloadStatus Status { get; set; }
|
||||
public SDK.Models.Game Game { get; set; }
|
||||
public float Progress {
|
||||
get
|
||||
{
|
||||
return BytesDownloaded / (float)TotalBytes;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
public double TransferSpeed { get; set; }
|
||||
public long BytesDownloaded { get; set; }
|
||||
public long TotalBytes { get; set; }
|
||||
|
||||
public DownloadQueueGame(SDK.Models.Game game)
|
||||
{
|
||||
Game = game;
|
||||
Id = game.Id;
|
||||
Title = game.Title;
|
||||
Version = game.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault()?.Version;
|
||||
QueuedOn = DateTime.Now;
|
||||
Status = DownloadStatus.Idle;
|
||||
|
||||
var cover = game.Media.FirstOrDefault(m => m.Type == SDK.Enums.MediaType.Cover);
|
||||
|
||||
if (cover != null)
|
||||
CoverId = cover.Id;
|
||||
|
||||
var icon = game.Media.FirstOrDefault(m => m.Type == SDK.Enums.MediaType.Icon);
|
||||
|
||||
if (icon != null)
|
||||
IconId = icon.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
LANCommander.Client/Models/DownloadQueueRedistributable.cs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
using LANCommander.Client.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Models
|
||||
{
|
||||
public class DownloadQueueRedistributable : IDownloadQueueItem
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Version { get; set; }
|
||||
public Guid CoverId { get; set; }
|
||||
public Guid IconId { get; set; }
|
||||
public DateTime QueuedOn { get; set; }
|
||||
public DateTime? CompletedOn { get; set; }
|
||||
public bool IsUpdate { get; set; }
|
||||
public bool State
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Status)
|
||||
{
|
||||
case DownloadStatus.Downloading:
|
||||
case DownloadStatus.InstallingRedistributables:
|
||||
case DownloadStatus.InstallingMods:
|
||||
case DownloadStatus.InstallingExpansions:
|
||||
case DownloadStatus.RunningScripts:
|
||||
case DownloadStatus.DownloadingSaves:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public DownloadStatus Status { get; set; }
|
||||
public SDK.Models.Redistributable Redistributable { get; set; }
|
||||
public float Progress { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
public double TransferSpeed { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
public long BytesDownloaded { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
public long TotalBytes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public DownloadQueueRedistributable(SDK.Models.Redistributable redistributable)
|
||||
{
|
||||
Redistributable = redistributable;
|
||||
Id = redistributable.Id;
|
||||
Title = redistributable.Name;
|
||||
Version = redistributable.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault()?.Version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using LANCommander.Launcher.Data.Models;
|
||||
using LANCommander.Client.Data.Models;
|
||||
|
||||
namespace LANCommander.Launcher.Models
|
||||
namespace LANCommander.Client.Models
|
||||
{
|
||||
public class ExistingEntityResult<T> where T : BaseModel
|
||||
{
|
||||
|
|
@ -1,29 +1,27 @@
|
|||
using LANCommander.SDK.Enums;
|
||||
using LANCommander.SDK.Models;
|
||||
using LANCommander.Client.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Launcher.Models
|
||||
namespace LANCommander.Client.Models
|
||||
{
|
||||
public interface IInstallQueueItem
|
||||
public interface IDownloadQueueItem
|
||||
{
|
||||
Guid Id { get; set; }
|
||||
string Title { get; set; }
|
||||
string Version { get; set; }
|
||||
string InstallDirectory { get; set; }
|
||||
Guid CoverId { get; set; }
|
||||
Guid IconId { get; set; }
|
||||
DateTime QueuedOn { get; set; }
|
||||
DateTime? CompletedOn { get; set; }
|
||||
bool IsUpdate { get; set; }
|
||||
bool State { get; }
|
||||
InstallStatus Status { get; set; }
|
||||
DownloadStatus Status { get; set; }
|
||||
float Progress { get; set; }
|
||||
double TransferSpeed { get; set; }
|
||||
long BytesDownloaded { get; set; }
|
||||
long TotalBytes { get; set; }
|
||||
CancellationTokenSource CancellationToken { get; set; }
|
||||
InstallPlanItemType ItemType { get; }
|
||||
Guid? DependsOnId { get; set; }
|
||||
List<InstallTaskDefinition> Tasks { get; set; }
|
||||
Guid? CurrentTaskId { get; set; }
|
||||
}
|
||||
}
|
||||
76
LANCommander.Client/Models/LibraryItem.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
using LANCommander.Client.Data.Models;
|
||||
using LANCommander.Client.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Models
|
||||
{
|
||||
public enum LibraryItemState
|
||||
{
|
||||
NotInstalled,
|
||||
Installed,
|
||||
Queued,
|
||||
Installing,
|
||||
UpdateAvailable
|
||||
}
|
||||
|
||||
public enum LibraryItemType
|
||||
{
|
||||
Game,
|
||||
Redistributable
|
||||
}
|
||||
|
||||
public class LibraryItem
|
||||
{
|
||||
public Guid Key { get; set; }
|
||||
public Guid IconId { get; set; }
|
||||
public LibraryItemType Type { get; set; }
|
||||
public LibraryItemState State { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string SortName { get; set; }
|
||||
public object DataItem { get; set; }
|
||||
public ObservableCollection<LibraryItem> Children { get; set; }
|
||||
|
||||
public LibraryItem(Collection collection)
|
||||
{
|
||||
Key = collection.Id;
|
||||
Type = LibraryItemType.Game;
|
||||
Name = collection.Name;
|
||||
DataItem = collection;
|
||||
Children = new ObservableCollection<LibraryItem>(collection.Games.Select(g => new LibraryItem(g)).OrderByTitle(g => g.SortName ?? g.Name).ToList());
|
||||
}
|
||||
|
||||
public LibraryItem(Game game)
|
||||
{
|
||||
Key = game.Id;
|
||||
Type = LibraryItemType.Game;
|
||||
Name = game.Title;
|
||||
SortName = game.SortTitle;
|
||||
DataItem = game;
|
||||
|
||||
if (game.Installed && !String.IsNullOrWhiteSpace(game.LatestVersion) && game.InstalledVersion != game.LatestVersion)
|
||||
State = LibraryItemState.UpdateAvailable;
|
||||
else if (game.Installed)
|
||||
State = LibraryItemState.Installed;
|
||||
else
|
||||
State = LibraryItemState.NotInstalled;
|
||||
|
||||
var icon = game.Media.FirstOrDefault(m => m.Type == Data.Enums.MediaType.Icon);
|
||||
|
||||
if (icon != null)
|
||||
IconId = icon.Id;
|
||||
}
|
||||
|
||||
public LibraryItem(Redistributable redistributable)
|
||||
{
|
||||
Key = redistributable.Id;
|
||||
Type = LibraryItemType.Redistributable;
|
||||
Name = redistributable.Name;
|
||||
DataItem = redistributable;
|
||||
}
|
||||
}
|
||||
}
|
||||
55
LANCommander.Client/Models/Settings.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Models
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
public DatabaseSettings Database { get; set; } = new DatabaseSettings();
|
||||
public AuthenticationSettings Authentication { get; set; } = new AuthenticationSettings();
|
||||
public GameSettings Games { get; set; } = new GameSettings();
|
||||
public MediaSettings Media { get; set; } = new MediaSettings();
|
||||
public ProfileSettings Profile { get; set; } = new ProfileSettings();
|
||||
public DebugSettings Debug { get; set; } = new DebugSettings();
|
||||
}
|
||||
|
||||
public class DatabaseSettings
|
||||
{
|
||||
public string ConnectionString { get; set; } = "Data Source=LANCommander.db;Cache=Shared";
|
||||
}
|
||||
|
||||
public class AuthenticationSettings
|
||||
{
|
||||
public string ServerAddress { get; set; } = "";
|
||||
public string AccessToken { get; set; } = "";
|
||||
public string RefreshToken { get; set; } = "";
|
||||
}
|
||||
|
||||
public class GameSettings
|
||||
{
|
||||
public string DefaultInstallDirectory { get; set; } = "C:\\Games";
|
||||
}
|
||||
|
||||
public class MediaSettings
|
||||
{
|
||||
public string StoragePath { get; set; } = "Media";
|
||||
}
|
||||
|
||||
public class ProfileSettings
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Alias { get; set; }
|
||||
public string Avatar { get; set; }
|
||||
}
|
||||
|
||||
public class DebugSettings
|
||||
{
|
||||
public bool EnableScriptDebugging { get; set; } = false;
|
||||
public LogLevel LoggingLevel { get; set; } = LogLevel.Warning;
|
||||
public string LoggingPath { get; set; } = "Logs";
|
||||
}
|
||||
}
|
||||
151
LANCommander.Client/Program.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
using LANCommander.Client.Data;
|
||||
using LANCommander.Client.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog.Extensions.Logging;
|
||||
using Photino.Blazor;
|
||||
using Photino.Blazor.CustomWindow.Extensions;
|
||||
using Photino.NET;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
namespace LANCommander.Client
|
||||
{
|
||||
class Program
|
||||
{
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var settings = SettingService.GetSettings();
|
||||
var builder = PhotinoBlazorAppBuilder.CreateDefault(args);
|
||||
|
||||
builder.RootComponents.Add<App>("app");
|
||||
|
||||
builder.Services.AddLogging();
|
||||
builder.Services.AddCustomWindow();
|
||||
builder.Services.AddAntDesign();
|
||||
builder.Services.AddDbContext<DbContext, DatabaseContext>();
|
||||
|
||||
NLog.GlobalDiagnosticsContext.Set("StoragePath", settings.Debug.LoggingPath);
|
||||
|
||||
builder.Services.AddLogging(loggingBuilder =>
|
||||
{
|
||||
loggingBuilder.ClearProviders();
|
||||
loggingBuilder.SetMinimumLevel(settings.Debug.LoggingLevel);
|
||||
loggingBuilder.AddNLog();
|
||||
});
|
||||
|
||||
#region Register Client
|
||||
var client = new SDK.Client(settings.Authentication.ServerAddress, settings.Games.DefaultInstallDirectory);
|
||||
|
||||
client.UseToken(new SDK.Models.AuthToken
|
||||
{
|
||||
AccessToken = settings.Authentication.AccessToken,
|
||||
RefreshToken = settings.Authentication.RefreshToken,
|
||||
});
|
||||
|
||||
builder.Services.AddSingleton(client);
|
||||
#endregion
|
||||
|
||||
#region Register Services
|
||||
builder.Services.AddScoped<CollectionService>();
|
||||
builder.Services.AddScoped<CompanyService>();
|
||||
builder.Services.AddScoped<EngineService>();
|
||||
builder.Services.AddScoped<GameService>();
|
||||
builder.Services.AddScoped<GenreService>();
|
||||
builder.Services.AddScoped<MultiplayerModeService>();
|
||||
builder.Services.AddScoped<TagService>();
|
||||
builder.Services.AddScoped<MediaService>();
|
||||
builder.Services.AddScoped<ProfileService>();
|
||||
builder.Services.AddScoped<PlaySessionService>();
|
||||
builder.Services.AddScoped<RedistributableService>();
|
||||
builder.Services.AddScoped<SaveService>();
|
||||
builder.Services.AddScoped<ImportService>();
|
||||
builder.Services.AddScoped<LibraryService>();
|
||||
builder.Services.AddScoped<DownloadService>();
|
||||
#endregion
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MainWindow
|
||||
.SetTitle("LANCommander")
|
||||
.SetUseOsDefaultLocation(true)
|
||||
.SetChromeless(true)
|
||||
.SetResizable(true)
|
||||
.RegisterCustomSchemeHandler("media", (object sender, string scheme, string url, out string contentType) =>
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
var query = HttpUtility.ParseQueryString(uri.Query);
|
||||
|
||||
var filePath = Path.Combine(MediaService.GetStoragePath(), uri.Host);
|
||||
|
||||
contentType = query["mime"];
|
||||
|
||||
return new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
||||
})
|
||||
.RegisterWebMessageReceivedHandler(async (object sender, string message) =>
|
||||
{
|
||||
using var scope = app.Services.CreateScope();
|
||||
|
||||
var importService = scope.ServiceProvider.GetService<ImportService>();
|
||||
|
||||
var window = (PhotinoWindow)sender;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case "import":
|
||||
await importService.ImportAsync();
|
||||
|
||||
window.SendWebMessage("importComplete");
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
|
||||
{
|
||||
app.MainWindow.ShowMessage("Fatal exception", error.ExceptionObject.ToString());
|
||||
};
|
||||
|
||||
#region Scaffold Required Directories
|
||||
string[] requiredDirectories = new string[]
|
||||
{
|
||||
"Backups",
|
||||
"Media"
|
||||
};
|
||||
|
||||
foreach (var directory in requiredDirectories)
|
||||
{
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, directory);
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Migrate Database
|
||||
using var scope = app.Services.CreateScope();
|
||||
|
||||
using var db = scope.ServiceProvider.GetService<DatabaseContext>();
|
||||
|
||||
if (db.Database.GetPendingMigrations().Any())
|
||||
{
|
||||
var backupPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Backups");
|
||||
var dataSource = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LANCommander.db");
|
||||
var backupName = Path.Combine(backupPath, $"LANCommander.db.{DateTime.Now.ToString("dd-MM-yyyy-HH.mm.ss.bak")}");
|
||||
|
||||
if (File.Exists(dataSource))
|
||||
{
|
||||
File.Copy(dataSource, backupName);
|
||||
}
|
||||
|
||||
db.Database.Migrate();
|
||||
}
|
||||
#endregion
|
||||
|
||||
app.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
7
LANCommander.Client/Properties/launchSettings.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"profiles": {
|
||||
"HelloPhotinoApp": {
|
||||
"commandName": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
17
LANCommander.Client/Services/CollectionService.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using LANCommander.Client.Data;
|
||||
using LANCommander.Client.Data.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Services
|
||||
{
|
||||
public class CollectionService : BaseDatabaseService<Collection>
|
||||
{
|
||||
public CollectionService(DatabaseContext dbContext) : base(dbContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
17
LANCommander.Client/Services/CompanyService.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using LANCommander.Client.Data;
|
||||
using LANCommander.Client.Data.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LANCommander.Client.Services
|
||||
{
|
||||
public class CompanyService : BaseDatabaseService<Company>
|
||||
{
|
||||
public CompanyService(DatabaseContext dbContext) : base(dbContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||