8 Commits

Author SHA1 Message Date
6030d10069 Move packaging logic into scripts and fix release metadata
Some checks failed
Build Mod Package / build (push) Failing after 5s
2026-04-08 00:49:44 +03:00
05259e1f26 Build package from clean staging directory
Some checks failed
Build Mod Package / build (push) Failing after 5s
2026-04-08 00:29:28 +03:00
3476112815 Pack workspace root for BG3 package build
Some checks failed
Build Mod Package / build (push) Failing after 5s
2026-04-08 00:26:40 +03:00
ca2b0ec3a1 Fix Divine pack command and validate package output
Some checks failed
Build Mod Package / build (push) Failing after 5s
2026-04-08 00:24:51 +03:00
68d3f4f9a3 Generate BG3ModManager info.json in release archive
All checks were successful
Build Mod Package / build (push) Successful in 8s
2026-04-08 00:15:37 +03:00
b90488ed6d Publish versioned release archive from Gitea CI
All checks were successful
Build Mod Package / build (push) Successful in 6s
2026-04-08 00:08:03 +03:00
255c839721 Rename mod folder to DnD 5.5e AIO Russian
All checks were successful
Build Mod Package / build (push) Successful in 11s
2026-04-07 23:59:26 +03:00
147d31522e Package build output as release zip
All checks were successful
Build Mod Package / build (push) Successful in 12s
2026-04-07 23:53:59 +03:00
6 changed files with 193 additions and 16 deletions

View File

@@ -10,7 +10,7 @@ on:
workflow_dispatch:
permissions:
contents: read
contents: write
jobs:
build:
@@ -45,7 +45,7 @@ jobs:
git -c "http.extraHeader=Authorization: Basic $authBasic" fetch --depth 1 origin $repoRef
git checkout --force FETCH_HEAD
if (-not (Test-Path -LiteralPath "Mods\\DnD55eRussian\\Localization\\Russian\\russian.xml")) {
if (-not (Test-Path -LiteralPath "Mods\\DnD 5.5e AIO Russian\\Localization\\Russian\\russian.xml")) {
throw "Repository sources are not available in the runner workspace."
}
@@ -68,9 +68,6 @@ jobs:
- name: Build .pak
run: |
$ErrorActionPreference = "Stop"
$workspace = "${{ gitea.workspace }}"
$modsPath = [System.IO.Path]::GetFullPath((Join-Path $workspace "Mods"))
$packagePath = [System.IO.Path]::GetFullPath((Join-Path $workspace "build/DnD55eRussian.pak"))
$divine = Get-ChildItem -Path ".tools/lslib" -Recurse -File |
Where-Object { $_.Name -ieq "Divine.exe" } |
Select-Object -First 1
@@ -79,13 +76,88 @@ jobs:
throw "Divine.exe was not found in the downloaded LSLib release."
}
& $divine.FullName -a create-package -g bg3 -s $modsPath -d $packagePath
if (-not (Test-Path -LiteralPath "build/DnD55eRussian.pak")) {
throw "Package was not created."
}
& ".\\scripts\\build.ps1" -DivinePath $divine.FullName -Workspace "${{ gitea.workspace }}" -VersionTag "${{ gitea.ref_name }}"
- name: Show build result
run: |
$ErrorActionPreference = "Stop"
Get-ChildItem "build/DnD55eRussian.pak" | Select-Object FullName, Length, LastWriteTime
$workspace = "${{ gitea.workspace }}"
$refName = "${{ gitea.ref_name }}"
$archiveBaseName = "DnD 5.5e AIO Russian"
if ($refName -and $refName -like "v*") {
$archiveBaseName = "DnD 5.5e AIO Russian $refName"
}
$zipPath = [System.IO.Path]::GetFullPath((Join-Path $workspace "build/$archiveBaseName.zip"))
Get-ChildItem "build/DnD 5.5e AIO Russian.pak", "build/info.json", $zipPath |
Select-Object FullName, Length, LastWriteTime
- name: Publish archive to release
if: startsWith(gitea.ref, 'refs/tags/v')
run: |
$ErrorActionPreference = "Stop"
$workspace = "${{ gitea.workspace }}"
$serverUrl = "${{ gitea.server_url }}"
$repository = "${{ gitea.repository }}"
$tagName = "${{ gitea.ref_name }}"
$zipPath = [System.IO.Path]::GetFullPath((Join-Path $workspace "build/DnD 5.5e AIO Russian $tagName.zip"))
$assetName = [System.IO.Path]::GetFileName($zipPath)
$repoParts = $repository.Split("/", 2)
if ($repoParts.Length -ne 2) {
throw "Could not parse repository owner and name from '$repository'."
}
if (-not (Test-Path -LiteralPath $zipPath)) {
throw "Release archive was not found at '$zipPath'."
}
$owner = $repoParts[0]
$repo = $repoParts[1]
$apiBase = "$serverUrl/api/v1/repos/$owner/$repo"
$headers = @{
Authorization = "token ${{ secrets.GITEA_TOKEN }}"
Accept = "application/json"
}
$release = $null
try {
$release = Invoke-RestMethod -Method Get -Uri "$apiBase/releases/tags/$tagName" -Headers $headers
} catch {
$statusCode = $null
if ($_.Exception.Response) {
$statusCode = [int]$_.Exception.Response.StatusCode
}
if ($statusCode -ne 404) {
throw
}
}
if (-not $release) {
$releaseBody = @{
tag_name = $tagName
name = $tagName
target_commitish = "${{ gitea.sha }}"
draft = $false
prerelease = $false
} | ConvertTo-Json
$release = Invoke-RestMethod -Method Post -Uri "$apiBase/releases" -Headers $headers -ContentType "application/json" -Body $releaseBody
}
$existingAsset = $null
if ($release.assets) {
$existingAsset = $release.assets | Where-Object { $_.name -eq $assetName } | Select-Object -First 1
}
if ($existingAsset) {
Invoke-RestMethod -Method Delete -Uri "$apiBase/releases/$($release.id)/assets/$($existingAsset.id)" -Headers $headers
}
$uploadHeaders = @{
Authorization = "token ${{ secrets.GITEA_TOKEN }}"
Accept = "application/json"
}
Invoke-WebRequest -Method Post -Uri "$apiBase/releases/$($release.id)/assets?name=$([uri]::EscapeDataString($assetName))" -Headers $uploadHeaders -ContentType "application/octet-stream" -InFile $zipPath

2
.gitignore vendored
View File

@@ -1,4 +1,6 @@
build/
build-stage*
.tools/
*.pak
*.tmp
*.temp

View File

@@ -21,7 +21,7 @@
<attribute id="CharacterCreationLevelName" type="FixedString" value=""/>
<attribute id="Description" type="LSString" value="Русская локализация мода, который добавляет и обновляет контент в соответствии с правилами DnD 5.5e и другими источниками, включая предыстории, классы, таланты, расы, заклинания и многое другое. Это отдельный мод локализации и он требует установленный оригинальный мод."/>
<attribute id="FileSize" type="uint64" value="0"/>
<attribute id="Folder" type="LSString" value="DnD55eRussian"/>
<attribute id="Folder" type="LSString" value="DnD 5.5e AIO Russian"/>
<attribute id="LobbyLevelName" type="FixedString" value=""/>
<attribute id="MD5" type="LSString" value=""/>
<attribute id="MenuLevelName" type="FixedString" value=""/>

View File

@@ -1,7 +1,110 @@
param(
[string]$DivinePath = "Divine",
[string]$Workspace = (Get-Location).Path,
[string]$VersionTag = "",
[string]$ModFolder = "DnD 5.5e AIO Russian",
[string]$PackageName = "DnD 5.5e AIO Russian.pak",
[string]$ArchiveBaseName = "DnD 5.5e AIO Russian",
[string]$ModName = "DnD 5.5e All-in-One BEYOND Russian Localization",
[string]$ModUuid = "6401e84d-daf2-416d-adeb-99c03a2487a6",
[string]$ModAuthor = "MikhailRaw",
[string]$ModDescription = "Russian Localization",
[string]$ModVersion64 = "36028797018963968",
[string]$ModGroup = "6401e84d-daf2-416d-adeb-99c03a2487a6",
[string]$DependencyUuid = "897914ef-5c96-053c-44af-0be823f895fe",
[string]$DependencyVersion64 = "36028797018963968"
)
$ErrorActionPreference = "Stop"
if (-not (Test-Path -LiteralPath "build")) {
New-Item -ItemType Directory -Path "build" | Out-Null
$workspacePath = [System.IO.Path]::GetFullPath($Workspace)
$modsPath = Join-Path $workspacePath "Mods"
$modPath = Join-Path $modsPath $ModFolder
$buildPath = Join-Path $workspacePath "build"
$stagingPath = Join-Path $workspacePath "build-stage"
$packagePath = Join-Path $buildPath $PackageName
$tempPackagePath = Join-Path $env:TEMP $PackageName
$archiveName = $ArchiveBaseName
if ($VersionTag) {
$archiveName = "$ArchiveBaseName $VersionTag"
}
$zipPath = Join-Path $buildPath "$archiveName.zip"
$infoJsonPath = Join-Path $buildPath "info.json"
if (-not (Test-Path -LiteralPath $DivinePath)) {
$resolvedCommand = Get-Command $DivinePath -ErrorAction SilentlyContinue
if (-not $resolvedCommand) {
throw "Divine executable was not found: '$DivinePath'."
}
$DivinePath = $resolvedCommand.Source
}
Divine -a pack -s Mods -d build/DnD55eRussian.pak
if (-not (Test-Path -LiteralPath $modPath)) {
throw "Mod folder was not found: '$modPath'."
}
if (-not (Test-Path -LiteralPath (Join-Path $modPath "Localization\\Russian\\russian.xml"))) {
throw "Localization file was not found under '$modPath'."
}
New-Item -ItemType Directory -Path $buildPath -Force | Out-Null
foreach ($path in @($stagingPath, $tempPackagePath, $packagePath, $zipPath, $infoJsonPath)) {
if (Test-Path -LiteralPath $path) {
if ((Get-Item -LiteralPath $path).PSIsContainer) {
Remove-Item -LiteralPath $path -Recurse -Force
} else {
Remove-Item -LiteralPath $path -Force
}
}
}
New-Item -ItemType Directory -Path $stagingPath | Out-Null
Copy-Item -LiteralPath $modsPath -Destination $stagingPath -Recurse
& $DivinePath -a create-package -g bg3 -s $stagingPath -d $tempPackagePath
if (-not (Test-Path -LiteralPath $tempPackagePath)) {
throw "Temporary package was not created."
}
Move-Item -LiteralPath $tempPackagePath -Destination $packagePath
if (-not (Test-Path -LiteralPath $packagePath)) {
throw "Package was not created."
}
$packageFile = Get-Item -LiteralPath $packagePath
if ($packageFile.Length -lt 1024) {
throw "Package looks invalid: '$packagePath' is only $($packageFile.Length) bytes."
}
$packageMd5 = (Get-FileHash -LiteralPath $packagePath -Algorithm MD5).Hash.ToLowerInvariant()
$createdAt = (Get-Date).ToString("o")
$infoJson = [ordered]@{
Mods = @(
[ordered]@{
Author = $ModAuthor
Name = $ModName
Folder = $ModFolder
Version = $ModVersion64
Description = $ModDescription
UUID = $ModUuid
Created = $createdAt
Dependencies = @($DependencyUuid)
Group = $ModGroup
}
)
MD5 = $packageMd5
} | ConvertTo-Json -Depth 4
Set-Content -LiteralPath $infoJsonPath -Value $infoJson -Encoding utf8
Compress-Archive -LiteralPath @($packagePath, $infoJsonPath) -DestinationPath $zipPath -CompressionLevel Optimal
if (-not (Test-Path -LiteralPath $zipPath)) {
throw "ZIP archive was not created."
}
Get-ChildItem -LiteralPath $packagePath, $infoJsonPath, $zipPath |
Select-Object FullName, Length, LastWriteTime

View File

@@ -2,4 +2,4 @@
set -euo pipefail
mkdir -p build
Divine -a pack -s Mods -d build/DnD55eRussian.pak
Divine -a create-package -g bg3 -s Mods -d "build/DnD 5.5e AIO Russian.pak"