name: Sanctum Release on: push: tags: - 'v*' jobs: # SA-02 & SA-04: Entkoppelte Build- & Test-Umgebung ohne Zugriff auf Signatur-Secrets build: name: Build & Test (Windows x86_64) runs-on: windows-latest steps: - name: Checkout Code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master commit pinned with: toolchain: "1.85.0" targets: x86_64-pc-windows-msvc - name: Run Tests run: cargo test --all --verbose - name: Build Release Binary run: cargo build --release - name: Package Artifacts id: package shell: pwsh run: | $Tag = "${{ gitea.ref_name }}" $DistDir = "dist" $PackageName = "sanctum-${Tag}-windows-x86_64" $StagingDir = "${DistDir}/${PackageName}" $ZipFile = "${DistDir}/${PackageName}.zip" New-Item -ItemType Directory -Path $StagingDir -Force | Out-Null Copy-Item "target/release/sanctum.exe" "$StagingDir/" Copy-Item "README.md" "$StagingDir/" Copy-Item "LICENSE" "$StagingDir/" Copy-Item "CHANGELOG.md" "$StagingDir/" Compress-Archive -Path "$StagingDir/*" -DestinationPath $ZipFile -Force $ZipHash = (Get-FileHash -Path $ZipFile -Algorithm SHA256).Hash.ToLower() $ExeHash = (Get-FileHash -Path "target/release/sanctum.exe" -Algorithm SHA256).Hash.ToLower() @("$ZipHash ${PackageName}.zip", "$ExeHash sanctum.exe") | Set-Content -Path "${DistDir}/SHA256SUMS.txt" -Encoding utf8 echo "ZIP_FILE=$ZipFile" >> $env:GITHUB_OUTPUT echo "PACKAGE_NAME=$PackageName" >> $env:GITHUB_OUTPUT - name: Upload Build Artifacts uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: dist-artifacts path: dist/ # SA-02, SA-03 & SA-04: Dedizierter Signatur- & Release-Job mit isolierten Secrets und Prüfsummen-Verifikation sign-and-release: name: Sign & Release needs: [build] runs-on: windows-latest if: startsWith(github.ref, 'refs/tags/v') steps: - name: Download Build Artifacts uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: dist-artifacts path: dist - name: Verify and Sign Checksums with Minisign shell: pwsh env: MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }} run: | # SA-02: Secret-Isolation — MINISIGN_SECRET_KEY ist ausschließlich in diesem dedizierten Signier-Job verfügbar if (-not $env:MINISIGN_SECRET_KEY) { Write-Error "Secret MINISIGN_SECRET_KEY ist nicht gesetzt! Release ohne Signatur verboten." exit 1 } # SA-03: Pinned Download-Integrität für minisign.exe mit zwingender SHA-256 Validierung $MinisignUrl = "https://github.com/jedisct1/minisign/releases/download/0.11/minisign-0.11-win64.zip" $ExpectedMinisignHash = "b9c31c2c3034f81f0e5f5d92cbcc20e67a9671b6e5455661588638848dc58031" if (-not (Get-Command minisign -ErrorAction SilentlyContinue)) { Write-Host "Lade gepinnten Minisign-Release herunter: $MinisignUrl" Invoke-WebRequest -Uri $MinisignUrl -OutFile "minisign.zip" $ActualHash = (Get-FileHash -Path "minisign.zip" -Algorithm SHA256).Hash.ToLower() if ($ActualHash -ne $ExpectedMinisignHash) { Write-Error "KRITISCHER SICHERHEITSFEHLER: Minisign SHA-256 Prüfsumme ungültig!`nErwartet: $ExpectedMinisignHash`nErhalten: $ActualHash`nAbbruch." exit 1 } Write-Host "Minisign SHA-256 Integrität erfolgreich verifiziert ($ActualHash)." Expand-Archive -Path "minisign.zip" -DestinationPath "minisign-bin" $MinisignExe = "minisign-bin/minisign-win64/minisign.exe" } else { $MinisignExe = "minisign" } $KeyFile = "sanctum-ci-release.key" [System.IO.File]::WriteAllText($KeyFile, $env:MINISIGN_SECRET_KEY) try { & $MinisignExe -S -s $KeyFile -m "dist/SHA256SUMS.txt" -W -x "dist/SHA256SUMS.txt.minisig" if ($LASTEXITCODE -ne 0 -or -not (Test-Path "dist/SHA256SUMS.txt.minisig")) { Write-Error "Minisign-Signierung fehlgeschlagen!" exit 1 } } finally { Remove-Item $KeyFile -Force -ErrorAction SilentlyContinue } - name: Create Gitea Release uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 with: files: | dist/*.zip dist/SHA256SUMS.txt dist/SHA256SUMS.txt.minisig body_path: CHANGELOG.md draft: false prerelease: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}