From 816f791eeb03d1c6acc99fb52c319de1ea57d3dd Mon Sep 17 00:00:00 2001 From: Refringe Date: Mon, 26 Feb 2024 11:15:58 -0500 Subject: [PATCH] Changes: - Removes git directory from container - Changes all projects to build within a `build` directory - Adds a combine_builds script that takes the individual project builds and merges them into an `output` directory - Adds placeholder tag_validate script - Validates MODULE_DOMAIN env variable - Updates the Launcher project build to use the `dotnet build` command - Pins the `dotnet build` command to one thread to prevent Avalonia file access errors on build: https://github.com/AvaloniaUI/Avalonia/pull/13840 - Bleeding edge builds are now built as such. TODO: - Add additional static project files - Compress output directory - Upload release to public folder - Adapt to work within Drone env - Adapt build script to work with a dynamic tag value - Only run project builds when the tag exists in all three projects --- .dockerignore | 1 + .gitignore | 5 +- Dockerfile | 6 +- README.md | 4 +- project/build.ps1 | 35 ++++----- project/build_launcher.ps1 | 152 +++++++++++++++++-------------------- project/build_modules.ps1 | 58 ++++++-------- project/build_server.ps1 | 36 +++++---- project/combine_builds.ps1 | 58 ++++++++++++++ project/tag_validate.ps1 | 8 ++ 10 files changed, 209 insertions(+), 154 deletions(-) create mode 100644 .dockerignore create mode 100644 project/combine_builds.ps1 create mode 100644 project/tag_validate.ps1 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..072d6f8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.git/ diff --git a/.gitignore b/.gitignore index 0944e11..c3f4253 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -Launcher/ -Modules/ -Server/ +builds/ +output/ diff --git a/Dockerfile b/Dockerfile index 70c3973..320e7dd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,9 +23,11 @@ RUN git --version # Copy build scripts into the container COPY project/build.ps1 /Code/project/ -COPY project/build_server.ps1 /Code/project/ -COPY project/build_modules.ps1 /Code/project/ COPY project/build_launcher.ps1 /Code/project/ +COPY project/build_modules.ps1 /Code/project/ +COPY project/build_server.ps1 /Code/project/ +COPY project/combine_builds.ps1 /Code/project/ +COPY project/tag_validate.ps1 /Code/project/ # Set the working directory to /Code WORKDIR /Code diff --git a/README.md b/README.md index c958459..ff45f70 100644 --- a/README.md +++ b/README.md @@ -78,9 +78,9 @@ To test the build process, the following commands can be used to build the Docke git clone https://dev.sp-tarkov.com/SPT-AKI/Build.git C:\Code\Build cd C:\Code\Build -# Build the Docker image +# Build the Docker container docker build -t spt-build-environment . -# Test the build process +# Run the build script docker run --rm -v "C:\Code\Build:C:\Code" -e MODULE_DOMAIN="https://example.com" spt-build-environment powershell -File C:\Code\project\build.ps1 ``` diff --git a/project/build.ps1 b/project/build.ps1 index f9608ce..a1911a5 100644 --- a/project/build.ps1 +++ b/project/build.ps1 @@ -1,27 +1,28 @@ +## Orchestrate the build process for the SPT project + Write-Output " » Beginning SPT Build Process" -# Check for required environment variables -if ([string]::IsNullOrWhiteSpace($env:MODULE_DOMAIN)) { - Write-Output " » FAIL: The MODULE_DOMAIN environment variable can not be empty." +# Check for the required MODULE_DOMAIN environment variable +$MODULE_DOMAIN = $env:MODULE_DOMAIN +$MODULE_DOMAIN_REGEX = '^(https?:\/\/)?([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(\/)?$' +if ([string]::IsNullOrWhiteSpace($MODULE_DOMAIN) -or -not $MODULE_DOMAIN -match $MODULE_DOMAIN_REGEX -or $MODULE_DOMAIN.EndsWith("/")) { + Write-Output " » FAIL: The MODULE_DOMAIN environment variable is invalid." exit 1 # Fail the build } -$MODULE_DOMAIN = $env:MODULE_DOMAIN -# TODO: This is dynamic, based on the incoming commit information. +# TODO: Make dynamic, based on the commit information $RELEASE_TAG = "3.8.0-BE" +# Get the current directory +$DIR_ABS = (Get-Location).Path + # TODO: Validate that the tag exists in all three repositories before continuing the build. - -#$BEPINEX_RELEASE = "https://github.com/BepInEx/BepInEx/releases/download/v5.4.21/BepInEx_x64_5.4.21.0.zip" - -$OUTPUT_DIR = ".\output" - -if (Test-Path -Path $OUTPUT_DIR) { - Write-Output " » Removing Previous Output Directory" - Remove-Item -Recurse -Force $OUTPUT_DIR -} +pwsh $DIR_ABS\project\validate_tag.ps1 $RELEASE_TAG # Build the projects -pwsh .\project\build_server.ps1 $RELEASE_TAG -pwsh .\project\build_modules.ps1 $RELEASE_TAG $MODULE_DOMAIN -pwsh .\project\build_launcher.ps1 $RELEASE_TAG +pwsh $DIR_ABS\project\build_server.ps1 $RELEASE_TAG +pwsh $DIR_ABS\project\build_modules.ps1 $RELEASE_TAG $MODULE_DOMAIN +pwsh $DIR_ABS\project\build_launcher.ps1 $RELEASE_TAG + +# Combine the built files into the output directory +pwsh $DIR_ABS\project\combine_builds.ps1 diff --git a/project/build_launcher.ps1 b/project/build_launcher.ps1 index 8a55759..a560cd5 100644 --- a/project/build_launcher.ps1 +++ b/project/build_launcher.ps1 @@ -1,82 +1,70 @@ -Param( - [Parameter(Mandatory = $true)] - [string] $RELEASE_TAG -) - -Write-Output " » Building Launcher" - -# Set directories -$DIR_ABS = (Get-Location).Path -$DIR = "$DIR_ABS\Launcher" -$DIR_PROJECT = "$DIR\project" -$DIR_BUILD = "$DIR_PROJECT\build" - -# Remove the output folder if it already exists -if (Test-Path -Path $DIR) { - Write-Output " » Removing Previous Build Directory" - Remove-Item -Recurse -Force $DIR -} - -# Pull down the server project, at the tag, with no history -Write-Output " » Cloning Launcher Project" -$REPO = "https://dev.sp-tarkov.com/SPT-AKI/Launcher.git" -try { - $processInfo = New-Object System.Diagnostics.ProcessStartInfo - $processInfo.FileName = "git" - $processInfo.Arguments = "clone $REPO --branch $RELEASE_TAG --depth 1 `"$DIR`"" - $processInfo.RedirectStandardError = $true - $processInfo.RedirectStandardOutput = $true - $processInfo.UseShellExecute = $false - $processInfo.CreateNoWindow = $true - - $process = New-Object System.Diagnostics.Process - $process.StartInfo = $processInfo - $process.Start() | Out-Null - $process.WaitForExit() - - $stdout = $process.StandardOutput.ReadToEnd() - $stderr = $process.StandardError.ReadToEnd() - - Write-Output $stdout - if ($process.ExitCode -ne 0) { - throw "git clone command failed with exit code $($process.ExitCode). Output: $stderr" - } -} -catch { - $errorMessage = " » FAIL: Error Executing git clone: $_" - Write-Error $errorMessage - exit 1 # Fail the build -} - -# Create the any necessary subdirectories -New-Item -Path $DIR_BUILD -ItemType Directory -Force - -Set-Location $DIR_PROJECT - -Write-Output " » Installing .NET Dependencies" -try { - $RESTORE_RESULT = dotnet restore - if ($LASTEXITCODE -ne 0) { - throw "dotnet restore failed with exit code $LASTEXITCODE" - } - Write-Output $RESTORE_RESULT -} -catch { - Write-Error " » FAIL: Error executing dotnet restore: $_" - exit 1 # Fail the build -} - -Write-Output " » Running Build Task" -try { - $BUILD_RESULT = dotnet publish "$DIR_PROJECT\Aki.Launcher\Aki.Launcher.csproj" -c Release -f net6.0 -r win-x64 /p:IncludeNativeLibrariesForSelfExtract=true -p:PublishSingleFile=true --self-contained false - if ($LASTEXITCODE -ne 0) { - throw "dotnet publish failed with exit code $LASTEXITCODE" - } - Write-Output $BUILD_RESULT -} -catch { - Write-Error " » FAIL: Error executing dotnet restore: $_" - exit 1 # Fail the build -} - -Write-Output "⚡ Launcher Built ⚡" +# Build the Launcher project. + +Param( + [Parameter(Mandatory = $true)] + [string] $RELEASE_TAG +) + +Write-Output " » Building Launcher Project" + +# Set directories +$DIR_ABS = (Get-Location).Path +$DIR = "$DIR_ABS\builds\Launcher" +$DIR_PROJECT = "$DIR\project" + +# Remove the build directory if it already exists +if (Test-Path -Path $DIR) { + Write-Output " » Removing Previous Launcher Project Build Directory" + Remove-Item -Recurse -Force $DIR +} + +# Pull down the launcher project, at the tag, with no history +Write-Output " » Cloning Launcher Project" +$REPO = "https://dev.sp-tarkov.com/SPT-AKI/Launcher.git" +try { + $processInfo = New-Object System.Diagnostics.ProcessStartInfo + $processInfo.FileName = "git" + $processInfo.Arguments = "clone $REPO --branch $RELEASE_TAG --depth 1 `"$DIR`"" + $processInfo.RedirectStandardError = $true + $processInfo.RedirectStandardOutput = $true + $processInfo.UseShellExecute = $false + $processInfo.CreateNoWindow = $true + + $process = New-Object System.Diagnostics.Process + $process.StartInfo = $processInfo + $process.Start() | Out-Null + $process.WaitForExit() + + $stdout = $process.StandardOutput.ReadToEnd() + $stderr = $process.StandardError.ReadToEnd() + + Write-Output $stdout + if ($process.ExitCode -ne 0) { + throw "git clone command failed with exit code $($process.ExitCode). Output: $stderr" + } +} +catch { + $errorMessage = " » FAIL: Error Executing git clone: $_" + Write-Error $errorMessage + exit 1 # Fail the build +} + +# Create any necessary sub-directories +New-Item -Path $DIR_PROJECT -ItemType Directory -Force + +Set-Location $DIR_PROJECT + +try { + $BUILD_RESULT = dotnet build --configuration release -m:1 *>&1 + if ($LASTEXITCODE -ne 0) { + Write-Output "Build output: $BUILD_RESULT" + throw "dotnet build failed with exit code $LASTEXITCODE" + } + Write-Output $BUILD_RESULT +} +catch { + Write-Error " » FAIL: Error executing dotnet build: $_" + exit 1 # Fail the build +} + +Write-Output "⚡ Launcher Project Built ⚡" diff --git a/project/build_modules.ps1 b/project/build_modules.ps1 index e30e621..e026224 100644 --- a/project/build_modules.ps1 +++ b/project/build_modules.ps1 @@ -1,3 +1,5 @@ +# Build the Modules project. + Param( [Parameter(Mandatory = $true)] [string] $RELEASE_TAG, @@ -6,22 +8,22 @@ Param( [string] $MODULE_DOMAIN ) -Write-Output " » Building Modules" +Write-Output " » Building Modules Project" -# Set directorys +# Set directories $DIR_ABS = (Get-Location).Path -$DIR = "$DIR_ABS\Modules" +$DIR = "$DIR_ABS\builds\Modules" $DIR_PROJECT = "$DIR\project" $DIR_BUILD = "$DIR_PROJECT\build" $DIR_MANAGED = "$DIR_PROJECT\Shared\Managed" -# Remove the output folder if it already exists +# Remove the build directory if it already exists if (Test-Path -Path $DIR) { - Write-Output " » Removing Previous Build Directory" + Write-Output " » Removing Previous Modules Project Build Directory" Remove-Item -Recurse -Force $DIR } -# Pull down the server project, at the tag, with no history +# Pull down the modules project, at the tag, with no history Write-Output " » Cloning Modules Project" $REPO = "https://dev.sp-tarkov.com/SPT-AKI/Modules.git" try { @@ -47,12 +49,12 @@ try { } } catch { - $errorMessage = " » FAIL: Error Executing git clone: $_" + $errorMessage = " » FAIL: Error executing git clone: $_" Write-Error $errorMessage exit 1 # Fail the build } -# Create the any necessary subdirectories +# Create any necessary sub-directories New-Item -Path $DIR_BUILD -ItemType Directory -Force New-Item -Path $DIR_MANAGED -ItemType Directory -Force @@ -79,64 +81,52 @@ catch { Write-Error " » FAIL: Error fetching or parsing core.json: $_" exit 1 # Fail the build } -Write-Output " » Client Version: $CLIENT_VERSION fetched successfully." +Write-Output " » Client Version $CLIENT_VERSION Fetched Successfully." # Download the module files -Write-Output " » Downloading Client Modules" +Write-Output " » Downloading Client Module Package" $DOWNLOAD_PATH = "$DIR_MANAGED\$CLIENT_VERSION.zip" $DOWNLOAD_URL = "$MODULE_DOMAIN/$CLIENT_VERSION.zip" try { Invoke-WebRequest -Uri $DOWNLOAD_URL -OutFile $DOWNLOAD_PATH -UseBasicParsing -ErrorAction Stop if (-not (Test-Path -Path $DOWNLOAD_PATH) -or (Get-Item -Path $DOWNLOAD_PATH).Length -eq 0) { - throw "The module download does not exist or is empty." + throw "The module package does not exist or is empty." } } catch { Write-Error " » FAIL: Unable to download the module. Error: $_" exit 1 # Fail the build } -Write-Output " » Download successful: $DOWNLOAD_PATH" +Write-Output " » Download Successful: $DOWNLOAD_PATH" -Write-Output " » Extracting Client Modules" +Write-Output " » Extracting Client Module Package" try { Expand-Archive -Path $DOWNLOAD_PATH -DestinationPath $DIR_MANAGED -Force -ErrorAction Stop - Write-Output " » Client Modules extracted to $DIR_MANAGED" + Write-Output " » Client Module Package Extracted: $DIR_MANAGED" } catch { - Write-Error " » FAIL: Error extracting client modules: $_" + Write-Error " » FAIL: Error Extracting Client Module Package: $_" exit 1 # Fail the build } # Delete the modules archive now that it's been uncompressed try { Remove-Item -Path $DOWNLOAD_PATH -Force -ErrorAction Stop - Write-Output " » Client Modules Archive Deleted" + Write-Output " » Client Module Package Deleted" } catch { - Write-Warning " » Failed to delete ZIP file: $_" + Write-Warning " » Failed to Delete ZIP File: $_" exit 1 # Fail the build } Set-Location $DIR_PROJECT -Write-Output " » Installing .NET Dependencies" +Write-Output " » Running Modules Project Build Task" try { - $RESTORE_RESULT = dotnet restore + $BUILD_RESULT = dotnet build *>&1 if ($LASTEXITCODE -ne 0) { - throw "dotnet restore failed with exit code $LASTEXITCODE" - } - Write-Output $RESTORE_RESULT -} -catch { - Write-Error " » FAIL: Error executing dotnet restore: $_" - exit 1 # Fail the build -} - -Write-Output " » Running Build Task" -try { - $BUILD_RESULT = dotnet build - if ($LASTEXITCODE -ne 0) { - throw "dotnet build failed with exit code $LASTEXITCODE" + Write-Output "Build output: $BUILD_RESULT" + throw "dotnet build failed with exit code $LASTEXITCODE" } Write-Output $BUILD_RESULT } @@ -145,4 +135,4 @@ catch { exit 1 # Fail the build } -Write-Output "⚡ Modules Built ⚡" +Write-Output "⚡ Modules Project Built ⚡" diff --git a/project/build_server.ps1 b/project/build_server.ps1 index 0736320..6f3db89 100644 --- a/project/build_server.ps1 +++ b/project/build_server.ps1 @@ -1,19 +1,21 @@ +# Build the Server project. + Param( [Parameter(Mandatory = $true)] [string] $RELEASE_TAG ) -Write-Output " » Building Server" +Write-Output " » Building Server Project" -# Set directorys +# Set directories $DIR_ABS = (Get-Location).Path -$DIR = "$DIR_ABS\Server" +$DIR = "$DIR_ABS\builds\Server" $DIR_PROJECT = "$DIR\project" $DIR_BUILD = "$DIR_PROJECT\build" -# Remove the output folder if it already exists +# Remove the build directory if it already exists if (Test-Path -Path $DIR) { - Write-Output " » Removing Previous Build Directory" + Write-Output " » Removing Previous Server Project Build Directory" Remove-Item -Recurse -Force $DIR } @@ -43,12 +45,12 @@ try { } } catch { - $errorMessage = " » FAIL: Error Executing git clone: $_" + $errorMessage = " » FAIL: Error executing git clone: $_" Write-Error $errorMessage exit 1 # Fail the build } -# Create the any necessary subdirectories +# Create any necessary sub-directories New-Item -Path $DIR_BUILD -ItemType Directory -Force # Ensure we are in the correct directory @@ -58,12 +60,18 @@ Set-Location $DIR git lfs fetch git lfs pull -# Set the build type based on whether the tag matches the release regex or not. -# A tag in the format of `1.2.3` will be considered a release build, while anything else will be considered debug. -$BUILD_TYPE_REGEX = '^(v?\d+\.\d+\.\d+)$' -if ($RELEASE_TAG -match $BUILD_TYPE_REGEX) { +# Determine the build type based on the tag. +# The 'release' pattern matches tags like '1.2.3' or 'v1.2.3'. +# The 'bleeding' pattern matches tags like '1.2.3-BE' or 'v1.2.3-BE', case-insensitively. +# The 'debug' pattern will be used for any tag not matching these patterns. +$RELEASE_BUILD_REGEX = '^(v?\d+\.\d+\.\d+)$' +$BLEEDING_BUILD_REGEX = '^(v?\d+\.\d+\.\d+-BE)$' +if ($RELEASE_TAG -match $RELEASE_BUILD_REGEX) { $BUILD_TYPE = "release" } +elseif ($RELEASE_TAG -match $BLEEDING_BUILD_REGEX) { + $BUILD_TYPE = "bleeding" +} else { $BUILD_TYPE = "debug" } @@ -71,7 +79,7 @@ Write-Output " » Build Type: $BUILD_TYPE" Set-Location $DIR_PROJECT -Write-Output " » Installing NPM Dependencies" +Write-Output " » Installing Server Project Dependencies" try { npm install } catch { @@ -79,7 +87,7 @@ try { exit 1 } -Write-Output " » Running Build Task" +Write-Output " » Running Server Project Build Task" try { npm run build:$BUILD_TYPE } catch { @@ -87,4 +95,4 @@ try { exit 1 } -Write-Output "⚡ Server Built ⚡" +Write-Output "⚡ Server Project Built ⚡" diff --git a/project/combine_builds.ps1 b/project/combine_builds.ps1 new file mode 100644 index 0000000..cd6feda --- /dev/null +++ b/project/combine_builds.ps1 @@ -0,0 +1,58 @@ +## Take the built project files and combines them into a release folder. + +Write-Output " » Combining Project Build Files" + +# Set directories +$DIR_ABS = (Get-Location).Path +$DIR_OUTPUT = "$DIR_ABS\release\" +$ProjectPaths = @( + "$DIR_ABS\builds\Server\project\build\", + "$DIR_ABS\builds\Modules\project\build\", + "$DIR_ABS\builds\Launcher\project\Build\" +) + +# Remove the release directory if it already exists +if (Test-Path -Path $DIR_OUTPUT) { + Write-Output " » Removing Previous release Directory" + Remove-Item -Recurse -Force $DIR_OUTPUT +} + +# Create new directory +New-Item -Path $DIR_OUTPUT -ItemType Directory -Force + +# Function to copy project build files +function Copy-ProjectFiles { + param ( + [string]$sourceDir + ) + Get-ChildItem -Path $sourceDir -Recurse | ForEach-Object { + $relativePath = $_.FullName.Substring($sourceDir.Length) + $targetPath = Join-Path -Path $DIR_OUTPUT -ChildPath $relativePath + + if (-not $_.PSIsContainer) { + $targetDir = Split-Path -Path $targetPath -Parent + if (-not (Test-Path -Path $targetDir)) { + New-Item -Path $targetDir -ItemType Directory -Force | Out-Null + } + if ($_.FullName -ne $targetPath) { + Copy-Item -Path $_.FullName -Destination $targetPath -Force + } + } + } +} + +try { + foreach ($path in $ProjectPaths) { + Copy-ProjectFiles -sourceDir $path + } +} catch { + Write-Error "An error occurred: $_" +} + +# Missing +#BepInEx\core\ +#BepInEx\config\ +#doorstop_config.ini +#winhttp.dll +#LICENCE-BEPINEX.txt +#LICENCE-ConfigurationManager.txt \ No newline at end of file diff --git a/project/tag_validate.ps1 b/project/tag_validate.ps1 new file mode 100644 index 0000000..b81095f --- /dev/null +++ b/project/tag_validate.ps1 @@ -0,0 +1,8 @@ +## Validate that the tag exists in each project repository, or fail silent. + +Param( + [Parameter(Mandatory = $true)] + [string] $RELEASE_TAG +) + +Write-Output " » TODO: Checking for existence of tag: $RELEASE_TAG" \ No newline at end of file