CI: Add Windows Patches Action

This commit is contained in:
derrod 2024-04-28 07:22:32 +02:00 committed by Ryan Foster
parent f7f06dea8d
commit 7968f567b1
7 changed files with 390 additions and 0 deletions

View file

@ -0,0 +1,29 @@
function Ensure-Location {
<#
.SYNOPSIS
Ensures current location to be set to specified directory.
.DESCRIPTION
If specified directory exists, switch to it. Otherwise create it,
then switch.
.EXAMPLE
Ensure-Location "My-Directory"
Ensure-Location -Path "Path-To-My-Directory"
#>
param(
[Parameter(Mandatory)]
[string] $Path
)
if ( ! ( Test-Path $Path ) ) {
$_Params = @{
ItemType = "Directory"
Path = ${Path}
ErrorAction = "SilentlyContinue"
}
New-Item @_Params | Set-Location
} else {
Set-Location -Path ${Path}
}
}

View file

@ -0,0 +1,40 @@
function Invoke-External {
<#
.SYNOPSIS
Invokes a non-PowerShell command.
.DESCRIPTION
Runs a non-PowerShell command, and captures its return code.
Throws an exception if the command returns non-zero.
.EXAMPLE
Invoke-External 7z x $MyArchive
#>
if ( $args.Count -eq 0 ) {
throw 'Invoke-External called without arguments.'
}
if ( ! ( Test-Path function:Log-Information ) ) {
. $PSScriptRoot/Logger.ps1
}
$Command = $args[0]
$CommandArgs = @()
if ( $args.Count -gt 1) {
$CommandArgs = $args[1..($args.Count - 1)]
}
$_EAP = $ErrorActionPreference
$ErrorActionPreference = "Continue"
Log-Debug "Invoke-External: ${Command} ${CommandArgs}"
& $command $commandArgs
$Result = $LASTEXITCODE
$ErrorActionPreference = $_EAP
if ( $Result -ne 0 ) {
throw "${Command} ${CommandArgs} exited with non-zero code ${Result}."
}
}

View file

@ -0,0 +1,149 @@
function Log-Debug {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Debug $m
}
}
}
function Log-Verbose {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Verbose $m
}
}
}
function Log-Warning {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Warning $m
}
}
}
function Log-Error {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
foreach($m in $Message) {
Write-Error $m
}
}
}
function Log-Information {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $script:StageName -ne $null ) { $script:StageName } else { '' })
$Icon = ' =>'
foreach($m in $Message) {
Write-Host -NoNewLine -ForegroundColor Blue " ${StageName} $($Icon.PadRight(5)) "
Write-Host "${m}"
}
}
}
}
function Log-Group {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
[string[]] $Message
)
Process {
if ( $Env:CI -ne $null ) {
if ( $script:LogGroup ) {
Write-Output '::endgroup::'
$script:LogGroup = $false
}
if ( $Message.count -ge 1 ) {
Write-Output "::group::$($Message -join ' ')"
$script:LogGroup = $true
}
} else {
if ( $Message.count -ge 1 ) {
Log-Information $Message
}
}
}
}
function Log-Status {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $StageName -ne $null ) { $StageName } else { '' })
$Icon = ' >'
foreach($m in $Message) {
Write-Host -NoNewLine -ForegroundColor Green " ${StageName} $($Icon.PadRight(5)) "
Write-Host "${m}"
}
}
}
}
function Log-Output {
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string[]] $Message
)
Process {
if ( ! ( $script:Quiet ) ) {
$StageName = $( if ( $script:StageName -ne $null ) { $script:StageName } else { '' })
$Icon = ''
foreach($m in $Message) {
Write-Output " ${StageName} $($Icon.PadRight(5)) ${m}"
}
}
}
}
$Columns = (Get-Host).UI.RawUI.WindowSize.Width - 5

View file

@ -0,0 +1,111 @@
name: Run bouf Patch Generation
description: Generates OBS updater manifest and patches
inputs:
gcsAccessKeyId:
description: GCS S3 Access Key ID
required: true
gcsAccessKeySecret:
description: GCS S3 Access Key Secret
required: true
workflowSecret:
description: GitHub API token to use for API calls
required: true
tagName:
description: GitHub Release tag
required: true
channel:
description: Update channel
required: false
default: 'stable'
runs:
using: composite
steps:
- uses: actions/checkout@v4
with:
path: "repo"
fetch-depth: 0
- name: Download Release Artifact
shell: pwsh
env:
GH_TOKEN: ${{ inputs.workflowSecret }}
run: |
# Download OBS release
. ${env:GITHUB_ACTION_PATH}\Invoke-External.ps1
Invoke-External gh release download "${{ inputs.tagName }}" -p "*-Windows.zip"
Expand-Archive -Path "*-Windows.zip" -DestinationPath "${{ github.workspace }}/build"
- name: Setup bouf
shell: pwsh
env:
BOUF_TAG: 'v0.6.3'
BOUF_HASH: '7f1d266467620aa553a705391ee06128e8ee14af66129a0e64a282997fb6fd83'
BOUF_NSIS_HASH: 'a234126de89f122b6a552df3416de3eabcb4195217626c7f4eaec71b20fe36eb'
GH_TOKEN: ${{ github.token }}
run: |
# Download bouf release
. ${env:GITHUB_ACTION_PATH}\Ensure-Location.ps1
. ${env:GITHUB_ACTION_PATH}\Invoke-External.ps1
Ensure-Location bouf
$windows_zip = "bouf-windows-${env:BOUF_TAG}.zip"
$nsis_zip = "bouf-nsis-${env:BOUF_TAG}.zip"
Invoke-External gh release download "${env:BOUF_TAG}" -R "obsproject/bouf" -p $windows_zip -p $nsis_zip
if ((Get-FileHash $windows_zip -Algorithm SHA256).Hash -ne "${env:BOUF_HASH}") {
throw "bouf hash does not match."
}
if ((Get-FileHash $nsis_zip -Algorithm SHA256).Hash -ne "${env:BOUF_NSIS_HASH}") {
throw "NSIS package hash does not match."
}
Expand-Archive -Path $windows_zip -DestinationPath bin
Expand-Archive -Path $nsis_zip -DestinationPath nsis
- name: Install rclone and pandoc
shell: pwsh
run: |
choco install rclone pandoc -y --no-progress
- name: Download Previous Builds
shell: pwsh
env:
RCLONE_TRANSFERS: '100'
RCLONE_FAST_LIST: 'true'
RCLONE_EXCLUDE: '{pdbs/**,**/${{ inputs.tagName }}/**}'
RCLONE_S3_PROVIDER: 'GCS'
RCLONE_S3_ACCESS_KEY_ID: '${{ inputs.gcsAccessKeyId }}'
RCLONE_S3_SECRET_ACCESS_KEY: '${{ inputs.gcsAccessKeySecret }}'
RCLONE_S3_ENDPOINT: 'https://storage.googleapis.com'
run: |
rclone -q copy ":s3:obs-builds" "${{ github.workspace }}/old_builds"
- name: Prepare Release Notes
shell: pwsh
run: |
# Release notes are just the tag body on Windows
Set-Location repo
git tag -l --format='%(contents:body)' ${{ inputs.version }} > "${{ github.workspace }}/notes.rst"
- name: Run bouf
shell: pwsh
run: |
. ${env:GITHUB_ACTION_PATH}\Invoke-External.ps1
$boufArgs = @(
"--config", "${env:GITHUB_ACTION_PATH}/config.toml",
"--version", "${{ inputs.tagName }}"
"--branch", "${{ inputs.channel }}"
"--notes-file", "${{ github.workspace }}/notes.rst"
"-i", "${{ github.workspace }}/build"
"-p", "${{ github.workspace }}/old_builds"
"-o", "${{ github.workspace }}/output"
"--updater-data-only"
)
Invoke-External "${{ github.workspace }}\bouf\bin\bouf.exe" @boufArgs
- name: Upload Outputs
uses: actions/upload-artifact@v4
with:
name: windows-updater-files
compression-level: 0
path: ${{ github.workspace }}/output

View file

@ -0,0 +1,25 @@
[general]
log_level = "trace"
[env]
# On CI these should be in %PATH%
sevenzip_path = "7z"
makensis_path = "makensis"
pandoc_path = "pandoc"
pdbcopy_path = "C:/Program Files (x86)/Windows Kits/10/Debuggers/x64/pdbcopy.exe"
[prepare.codesign]
skip_sign = true
[generate]
patch_type = "zstd"
compress_files = true
[package]
[package.installer]
skip = true
[package.updater]
vc_redist_path = "bouf/nsis/VC_redist.x64.exe"
skip_sign = true

View file

@ -12,6 +12,7 @@ on:
- services
- translations
- documentation
- patches
ref:
description: GitHub reference to use for job
type: string
@ -28,6 +29,10 @@ on:
description: Custom macOS Intel build for Steam Upload
type: string
required: false
channel:
description: Channel to use when generating Windows update files
type: string
required: false
permissions:
contents: write
jobs:
@ -130,3 +135,17 @@ jobs:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
command: pages publish . --project-name=${{ vars.CF_PAGES_PROJECT }} --commit-hash='${{ steps.setup.outputs.commitHash }}'
windows-patches:
name: Create Windows Patches 🩹
if: github.repository_owner == 'obsproject' && inputs.job == 'patches'
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/windows-patches
with:
tagName: ${{ inputs.ref }}
workflowSecret: ${{ github.token }}
channel: ${{ inputs.channel }}
gcsAccessKeyId: ${{ secrets.GCS_ACCESS_KEY_ID }}
gcsAccessKeySecret: ${{ secrets.GCS_ACCESS_KEY_SECRET }}

View file

@ -32,10 +32,12 @@ jobs:
+([0-9]).+([0-9]).+([0-9]) )
echo 'validTag=true' >> $GITHUB_OUTPUT
echo 'flatpakMatrix=["beta", "stable"]' >> $GITHUB_OUTPUT
echo 'updateChannel=stable' >> $GITHUB_OUTPUT
;;
+([0-9]).+([0-9]).+([0-9])-@(beta|rc)*([0-9]) )
echo 'validTag=true' >> $GITHUB_OUTPUT
echo 'flatpakMatrix=["beta"]' >> $GITHUB_OUTPUT
echo 'updateChannel=beta' >> $GITHUB_OUTPUT
;;
*) echo 'validTag=false' >> $GITHUB_OUTPUT ;;
esac
@ -171,3 +173,18 @@ jobs:
workflowSecret: ${{ github.token }}
tagName: ${{ github.ref_name }}
preview: false
windows-patches:
name: Create Windows Patches 🩹
needs: check-tag
if: github.repository_owner == 'obsproject' && fromJSON(needs.check-tag.outputs.validTag)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/windows-patches
with:
tagName: ${{ github.ref_name }}
workflowSecret: ${{ github.token }}
channel: ${{ needs.check-tag.outputs.updateChannel }}
gcsAccessKeyId: ${{ secrets.GCS_ACCESS_KEY_ID }}
gcsAccessKeySecret: ${{ secrets.GCS_ACCESS_KEY_SECRET }}