Skip to content

[WIP] Signed updates #58

[WIP] Signed updates

[WIP] Signed updates #58

Workflow file for this run

name: Releasing ModVerify
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
inputs:
branch:
description: "The branch to a release to"
required: true
env:
TOOL_PROJ_PATH: ./src/ModVerify.CliApp/ModVerify.CliApp.csproj
CREATOR_PROJ_PATH: ./modules/ModdingToolBase/src/AnakinApps/ApplicationManifestCreator/ApplicationManifestCreator.csproj
SIGNER_PROJ_PATH: ./modules/ModdingToolBase/src/AnakinApps/ApplicationManifestSigner/ApplicationManifestSigner.csproj
UPLOADER_PROJ_PATH: ./modules/ModdingToolBase/src/AnakinApps/FtpUploader/FtpUploader.csproj
TOOL_EXE: ModVerify.exe
UPDATER_EXE: AnakinRaW.ExternalUpdater.exe
MANIFEST_CREATOR: AnakinRaW.ApplicationManifestCreator.dll
MANIFEST_SIGNER: AnakinRaW.ApplicationManifestSigner.dll
SFTP_UPLOADER: AnakinRaW.FtpUploader.dll
ORIGIN_BASE: https://republicatwar.com/downloads/ModVerify
ORIGIN_BASE_PART: downloads/ModVerify/
BRANCH_NAME: ${{ github.event.inputs.branch || 'stable' }}
jobs:
# Builds and tests the solution.
test:
uses: ./.github/workflows/test.yml
pack:
name: Pack
needs: [test]
runs-on: windows-latest
steps:
- name: Checkout sources
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v5
- name: Create NetFramework Release
# use build for .NET Framework to enusre external updatere .EXE is included
run: dotnet build ${{ env.TOOL_PROJ_PATH }} --configuration Release -f net481 --output ./releases/net481 /p:DebugType=None /p:DebugSymbols=false
- name: Create Net Core Release
# use publish for .NET Core
run: dotnet publish ${{ env.TOOL_PROJ_PATH }} --configuration Release -f net10.0 --output ./releases/net10.0 /p:DebugType=None /p:DebugSymbols=false
- name: Create Linux Release
run: dotnet publish ${{ env.TOOL_PROJ_PATH }} --configuration Release -f net10.0 --runtime linux-x64 --self-contained true --output ./releases/linux-x64 /p:DebugType=None /p:DebugSymbols=false
- name: Upload a Build Artifact
uses: actions/upload-artifact@v7
with:
name: Binary Releases
path: ./releases
if-no-files-found: error
retention-days: 1
deploy:
name: Deploy
# Stable deploys are gated to 'main'. Non-stable channels (beta, canary, etc.) can be
# workflow_dispatched from any branch.
if: |
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'workflow_dispatch' &&
(github.event.inputs.branch != 'stable' || github.ref == 'refs/heads/main'))
needs: [pack]
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Verify embedded trust cert
shell: pwsh
run: |
$certPath = "src/ModVerify.CliApp/Resources/Certs/modverify-trust.cer"
if (-not (Test-Path $certPath)) {
Write-Error "$certPath is missing. Generate the production trust cert per docs/update-signing-setup.md and commit it before releasing."
exit 1
}
try {
$bytes = [IO.File]::ReadAllBytes($certPath)
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($bytes)
} catch {
Write-Error "Failed to load $certPath as an X.509 certificate: $_"
exit 1
}
if ($cert.HasPrivateKey) {
Write-Error "$certPath contains a private key. Only the public DER (.cer) is allowed; embedding a PFX would ship the signing key to every consumer."
exit 1
}
Write-Host "OK: $certPath is public-only ($($cert.Subject))."
- uses: actions/download-artifact@v8
with:
name: Binary Releases
path: ./releases
# Deploy .NET Framework self-update release
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
- name: Build Creator
run: dotnet build ${{env.CREATOR_PROJ_PATH}} --configuration Release --output ./dev
- name: Build Signer
run: dotnet build ${{env.SIGNER_PROJ_PATH}} --configuration Release --output ./dev
- name: Build Uploader
run: dotnet build ${{env.UPLOADER_PROJ_PATH}} --configuration Release --output ./dev
- name: Create binaries directory
run: mkdir -p ./deploy
- name: Copy self-update files
run: |
cp ./releases/net481/${{env.TOOL_EXE}} ./deploy/
cp ./releases/net481/${{env.UPDATER_EXE}} ./deploy/
- name: Create Manifest
run: dotnet ./dev/${{env.MANIFEST_CREATOR}} -a deploy/${{env.TOOL_EXE}} --appDataFiles deploy/${{env.UPDATER_EXE}} --origin ${{env.ORIGIN_BASE}} -o ./deploy -b ${{env.BRANCH_NAME}}
- name: Decode signing pfx
shell: bash
run: echo "${{ secrets.UPDATER_SIGNING_PFX_B64 }}" | base64 -d > $RUNNER_TEMP/signing.pfx
- name: Sign Manifest
run: dotnet ./dev/${{env.MANIFEST_SIGNER}} --manifest ./deploy/manifest.json --pfx $RUNNER_TEMP/signing.pfx --password "${{ secrets.UPDATER_SIGNING_PFX_PASSWORD }}"
- name: Wipe pfx
if: always()
run: rm -f $RUNNER_TEMP/signing.pfx
- name: Upload Build
run: dotnet ./dev/${{env.SFTP_UPLOADER}} ftp --host $host --port $port -u ${{secrets.SFTP_USER}} -p ${{secrets.SFTP_PASSWORD}} --base $base_path -s $source
env:
host: republicatwar.com
port: 1579
base_path: ${{env.ORIGIN_BASE_PART}}
source: ./deploy
# Deploy .NET Core and .NET Framework apps to Github
- name: Create NET Core .zip
# Change into the artifacts directory to avoid including the directory itself in the zip archive
working-directory: ./releases/net10.0
run: zip -r ../ModVerify-Net10.zip .
- uses: dotnet/nbgv@v0.5.1
id: nbgv
- name: Create GitHub release
# Create a GitHub release on push to main only
if: |
github.ref == 'refs/heads/main' && github.event_name == 'push'
uses: softprops/action-gh-release@v3
with:
name: v${{ steps.nbgv.outputs.SemVer2 }}
tag_name: v${{ steps.nbgv.outputs.SemVer2 }}
token: ${{ secrets.GITHUB_TOKEN }}
generate_release_notes: true
files: |
./releases/net481/ModVerify.exe
./releases/ModVerify-Net10.zip
./releases/linux-x64/ModVerify