[WIP] Signed updates #58
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |