First pass release tools for Itch and Steam

This commit is contained in:
Steve Streeting 2020-10-07 17:15:18 +01:00
parent ba6aa4dc13
commit 9b4bfd40e3
7 changed files with 317 additions and 3 deletions

View File

@ -29,3 +29,41 @@ function Find-Files {
}
}
# Get the root package output dir for a version / variant
function Get-Package-Dir {
param (
[PackageConfig]$config,
[string]$versionNumber,
[string]$variantName
)
return Join-Path $config.OutputDir "$versionNumber/$variantName"
}
# Get the dir where the client build is for a packaged version / variant
# This is as Get-Package-Dir except with one extra level e.g. WindowsNoEditor
function Get-Package-Client-Dir {
param (
[PackageConfig]$config,
[string]$versionNumber,
[string]$variantName
)
$root = Get-Package-Dir -config:$config -versionNumber:$versionNumber -variantName:$variantName
$variant = $config.Variants | Where-Object { $_.Name -eq $variantName } | Select-Object -First 1
if (-not $variant) {
throw "Unknown variant $variantName"
}
# Note, currently only supporting "Game" platform type, not separate client / server
$subfolder = switch ($variant.Platform) {
"Win32" { "WindowsNoEditor" }
"Win64" { "WindowsNoEditor" }
"Linux" { "LinuxNoEditor" }
"Mac" { "MacNoEditor" }
Default { throw "Unsupported platform $($variant.Platform)" }
}
return Join-Path $root $subfolder
}

40
inc/itch.ps1 Normal file
View File

@ -0,0 +1,40 @@
function Release-Itch {
param (
[PackageConfig]$config,
[PackageVariant]$variant,
[string]$sourcefolder,
[string]$version,
[switch]$dryrun = $false
)
Write-Output ">>>--- Itch Upload Start ---<<<"
$appid = $variant.ItchAppId
$channel = $variant.ItchChannel
if (-not $appid) {
throw "Missing property ItchAppId in $($variant.Name)"
}
if (-not $channel) {
throw "Missing property ItchChannel in $($variant.Name)"
}
$target = "$($appid):$channel"
if ($dryrun) {
Write-Output "Would have run butler command:"
Write-Output " > butler push --userversion=$version '$sourcefolder' $target"
} else {
Write-Output "Releasing version $version to Itch.io at $target"
Write-Output " Source: $sourcefolder"
butler push --userversion=$version "$sourcefolder" $target
if (!$?) {
throw "Itch butler tool failed!"
}
}
Write-Output ">>>--- Itch Upload Done! ---<<<"
Write-Output ""
}

View File

@ -12,6 +12,8 @@ class PackageVariant {
[string]$ExtraBuildArguments
# Whether to create a zip of this package (default false)
[bool]$Zip
# List of services this variant should be released to ("steam", "itch" currently supported)
[array]$ReleaseTo
# The Steam application ID, if you intend to send this variant to Steam
[string]$SteamAppId
# The Steam depot ID, if you intend to send this variant to Steam

110
inc/steam.ps1 Normal file
View File

@ -0,0 +1,110 @@
function Release-Steam {
param (
[PackageConfig]$config,
[PackageVariant]$variant,
[string]$sourcefolder,
[string]$version,
[switch]$dryrun = $false
)
Write-Output ">>>--- Steam Upload Start ---<<<"
$appid = $variant.SteamAppId
$depotid = $variant.SteamDepotId
$login = $variant.SteamLogin
if (-not $appid) {
throw "Missing property SteamAppId in $($variant.Name)"
}
if (-not $depotid) {
throw "Missing property SteamDepotId in $($variant.Name)"
}
if (-not $login) {
throw "Missing property SteamLogin in $($variant.Name)"
}
$steamconfigdir = Join-Path (Get-Item $sourcefolder).Parent "SteamConfig"
New-Item -ItemType Directory $steamconfigdir -Force > $null
# Preview mode in Steam build just outputs logs so it's dryrun
$preview = if($dryrun) { "1" } else { "0"}
# Use the UE4 platform as Steam target
$target = $variant.Platform
# write app file up to depot section then fill that in as we do depots
$appfile = "$steamconfigdir\app_build_$($appid).vdf"
Write-Output "Creating app build config $appfile"
Remove-Item $appfile -Force -ErrorAction SilentlyContinue
$appfp = New-Object -TypeName System.IO.FileStream(
$appfile,
[System.IO.FileMode]::Create,
[System.IO.FileAccess]::Write)
$appstream = New-Object System.IO.StreamWriter ($appfp, [System.Text.Encoding]::UTF8)
$appstream.WriteLine("`"appbuild`"")
$appstream.WriteLine("{")
$appstream.WriteLine(" `"appid`" `"$appid`"")
$appstream.WriteLine(" `"desc`" `"$version`"")
$appstream.WriteLine(" `"buildoutput`" `".\steamcmdbuild`"")
# we don't set contentroot in app file, we specify in depot files
$appstream.WriteLine(" `"setlive`" `"`"") # never try to set live
$appstream.WriteLine(" `"preview`" `"$preview`"")
$appstream.WriteLine(" `"local`" `"`"")
$appstream.WriteLine(" `"depots`"")
$appstream.WriteLine(" {")
# Depots inline
# Just one in this case
$depotfilerel = "depot_${target}_${depotid}.vdf"
$depotfile = "$steamconfigdir\$depotfilerel"
Write-Output "Creating depot build config $depotfile"
Remove-Item $depotfile -Force -ErrorAction SilentlyContinue
$depotfp = New-Object -TypeName System.IO.FileStream(
$depotfile,
[System.IO.FileMode]::Create,
[System.IO.FileAccess]::Write)
$depotstream = New-Object System.IO.StreamWriter($depotfp, [System.Text.Encoding]::UTF8)
$depotstream.WriteLine("`"DepotBuildConfig`"")
$depotstream.WriteLine("{")
$depotstream.WriteLine(" `"DepotID`" `"$depotid`"")
# We'll set ContentRoot specifically for
$depotstream.WriteLine(" `"ContentRoot`" `"$sourcefolder`"")
$depotstream.WriteLine(" `"FileMapping`"")
$depotstream.WriteLine(" {")
$depotstream.WriteLine(" `"LocalPath`" `"*`"")
$depotstream.WriteLine(" `"DepotPath`" `".`"")
$depotstream.WriteLine(" `"recursive`" `"1`"")
$depotstream.WriteLine(" }")
$depotstream.WriteLine(" `"FileExclusion`" `"*.pdb`"")
$depotstream.WriteLine("}")
$depotstream.Close()
$depotfp.Close()
# Now write depot entry to in-progress app file, relative file (same folder)
$appstream.WriteLine(" `"$depotid`" `"$depotfilerel`"")
# Finish the app file
$appstream.WriteLine(" }")
$appstream.WriteLine("}")
$appstream.Close()
if ($dryrun) {
Write-Output "Would have run Steam command:"
Write-Output " > steamcmd +login $($config.SteamLogin) +run_app_build_http $appfile +quit"
} else {
Write-Output "Releasing version $version to Steam ($appid)"
steamcmd +login $($config.SteamLogin) +run_app_build_http $appfile +quit
if (!$?) {
throw "Steam upload tool failed!"
}
}
Write-Output ">>>--- Steam Upload Done ---<<<"
Write-Output ""
if (-not $dryrun) {
Write-Output "-- Remember to release in Steamworks Admin --"
}
}

View File

@ -32,8 +32,12 @@
"Name": "PublicWin64SteamBuild",
"Platform": "Win64",
"Configuration": "Shipping",
"ReleaseTo": [
"Steam"
],
"SteamAppId": "YourSteamAppId",
"SteamDepotId": "YourWindowsDepotId",
"SteamLogin": "YourSteamReleaseUser",
"Zip": false,
"ExtraBuildArguments": "-EnableSteamworks",
"Cultures": [
@ -46,13 +50,16 @@
"Name": "PublicWin64Build",
"Platform": "Win64",
"Configuration": "Shipping",
"ReleaseTo": [
"Itch",
"SomeOtherService"
],
"ItchAppId": "itch-user/app-name",
"ItchChannel": "win64",
"Zip": false
}
],
"SteamLogin": "YourSteamReleaseUser"
}

View File

@ -204,7 +204,7 @@ try {
foreach ($var in $chosenVariants) {
$outDir = Join-Path $config.OutputDir "$versionNumber/$($var.Name)"
$outDir = Get-Package-Dir -config:$config -versionNumber:$versionNumber -variantName:$var.Name
$argList = [System.Collections.ArrayList]@()
$argList.Add("-ScriptsForProject=`"$projfile`"") > $null

117
ue4-release.ps1 Normal file
View File

@ -0,0 +1,117 @@
[CmdletBinding()] # Fail on unknown args
param (
# Version to release
[Parameter(Mandatory=$true)]
[string]$version,
# Variant name to release
[Parameter(Mandatory=$true)]
# Project folder (assumes current dir if not specified)
[string]$variant,
# Source folder, current dir if omitted
[string]$src,
# Which service(s) to release on e.g. "steam": defaults to "ReleaseTo" services in packageconfig.json for variant
[array]$services,
# Dry-run; does nothing but report what *would* have happened
[switch]$dryrun = $false,
[switch]$help = $false
)
. $PSScriptRoot\inc\platform.ps1
. $PSScriptRoot\inc\packageconfig.ps1
. $PSScriptRoot\inc\filetools.ps1
. $PSScriptRoot\inc\steam.ps1
. $PSScriptRoot\inc\itch.ps1
function Write-Usage {
Write-Output "Steve's UE4 release tool"
Write-Output "Usage:"
Write-Output " ue4-release.ps1 -version:ver -variant:var -services:steam,itch [-src:sourcefolder] [-dryrun]"
Write-Output " "
Write-Output " -version:ver : Version to release; must have been packaged already"
Write-Output " -variant:var : Name of package variant to release"
Write-Output " -services:s1,s2 : Name of services to release to. Can omit and rely on ReleaseTo"
Write-Output " setting of variant in packageconfig.json "
Write-Output " -src : Source folder (current folder if omitted), must contain packageconfig.json"
Write-Output " -dryrun : Don't perform any actual actions, just report what would happen"
Write-Output " -help : Print this help"
}
$ErrorActionPreference = "Stop"
if ($help) {
Write-Usage
Exit 0
}
if ($src.Length -eq 0) {
$src = "."
Write-Verbose "-src not specified, assuming current directory"
}
Write-Output "~-~-~ UE4 Release Helper Start ~-~-~"
try {
# Import config
$config = Read-Package-Config -srcfolder:$src
# Find variant (first match in case config has many)
$variantConfig = $config.Variants | Where-Object { $_.Name -eq $variant }
if ($variantConfig -is [array]) {
if ($variantConfig.Count > 1) {
throw "More than one package variant called $variant in packageconfig.json, ambiguous!"
} else {
# Don't think this will happen but still
$variantConfig = $variantConfig[0]
}
}
# Get source dir
$sourcedir = Get-Package-Client-Dir -config:$config -versionNumber:$version -variantName:$variant
if (-not (Test-Path $sourcedir -PathType Container)) {
throw "Release folder $sourcedir does not exist"
}
# Find service(s)
if ($services) {
# Release to a subset of allowed services
$servicesFound = $services | Where-Object {$variantConfig.ReleaseTo -contains $_ }
if ($servicesFound.Count -ne $services.Count) {
$unmatchedServices = $services | Where-Object { $servicesFound -notcontains $_ }
Write-Warning "Services(s) not supported by $($variantConfig.Name): $($unmatchedServices -join ", ")"
}
} else {
$servicesFound = $variantConfig.ReleaseTo
}
if (-not $servicesFound) {
throw "No matching services to release $variant to"
}
Write-Output ""
Write-Output "Variant : $variant"
Write-Output "Source Folder : $sourcedir"
Write-Output "Service(s) : $($servicesFound -join ", ")"
Write-Output ""
foreach ($service in $servicesFound) {
if ($service -eq "steam") {
Release-Steam -config:$config -variant:$variantConfig -sourcefolder:$sourcedir -version:$version -dryrun:$dryrun
} elseif ($service -eq "itch") {
Release-Itch -config:$config -variant:$variantConfig -sourcefolder:$sourcedir -version:$version -dryrun:$dryrun
} else {
throw "Unknown release service: $service"
}
}
} catch {
Write-Output $_.Exception.Message
Write-Output "~-~-~ UE4 Release Helper FAILED ~-~-~"
Exit 9
}
Write-Output "~-~-~ UE4 Release Helper Completed OK ~-~-~"