This repository includes comprehensive GitHub Actions workflows for building, testing, and releasing the Windows API CodePack project.
Triggers: Push to main/develop branches, Pull Requests
Features:
- Builds all .NET projects (.NET Framework 4.6.2-4.8.1, .NET 8-10)
- Builds C++ DirectX project (x64, x86 platforms)
- Runs tests and uploads results
- Validates NuGet package generation
- Performs security scans
- Supports multiple configurations (Debug/Release) and platforms
Matrix Strategy:
- Configuration: Debug, Release
- Platform: Any CPU, x64, x86 (x86 excluded for .NET 8+)
Triggers: Git tags (v*), Manual dispatch
Features:
- Automated version detection from tags
- Builds and packages all projects
- Authenticode signing (if certificate secrets are configured)
- Publishes NuGet packages to NuGet.org
- Creates GitHub releases with release notes
- Supports prerelease versions
- Comprehensive error handling and notifications
Manual Release:
# Create a tag
git tag v8.0.11
git push origin v8.0.11
# Or use workflow dispatch in GitHub UITriggers: Pull Requests to main/develop
Features:
- Validates all changes build successfully
- Checks for breaking changes
- Performs security vulnerability scans
- Validates NuGet package metadata
- Generates comprehensive PR summary
Triggers: Weekly schedule (Mondays), Manual dispatch
Features:
- Checks for outdated packages
- Identifies security vulnerabilities
- Creates GitHub issues for updates needed
- Automated dependency updates (manual trigger)
- Creates PRs for dependency updates
Add these secrets to your GitHub repository:
NUGET_API_KEY: Your NuGet API key for publishing packagesGITHUB_TOKEN: Automatically provided by GitHub
To enable Authenticode signing of DLLs during release builds, add these optional secrets:
CODESIGN_CERTIFICATE_BASE64: Base64-encoded PFX certificate file (required for signing)CODESIGN_CERTIFICATE_PASSWORD: Password for the PFX certificate (if password-protected)
How to create a code signing certificate:
Self-signed certificates are useful for testing but will show a warning to end users. They are not trusted by default on other machines.
Create a self-signed certificate using PowerShell:
# Create a self-signed code signing certificate
$cert = New-SelfSignedCertificate `
-Type CodeSigningCert `
-Subject "CN=Your Company Name Code Signing" `
-KeyUsage DigitalSignature `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-HashAlgorithm SHA256 `
-CertStoreLocation Cert:\CurrentUser\My `
-NotAfter (Get-Date).AddYears(3)
Write-Host "Certificate created with thumbprint: $($cert.Thumbprint)"
Write-Host "Certificate location: $($cert.PSPath)"Export to PFX format:
# Export the certificate to PFX file
$password = Read-Host -AsSecureString -Prompt "Enter password for PFX file"
$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert | Where-Object { $_.Thumbprint -eq "YOUR_THUMBPRINT_HERE" }
Export-PfxCertificate -Cert $cert -FilePath codesign.pfx -Password $passwordFor production use, you need a certificate from a trusted Certificate Authority (CA). These certificates are trusted by Windows and won't show warnings to users.
Popular Code Signing Certificate Providers:
- DigiCert - https://www.digicert.com/code-signing/
- Sectigo (formerly Comodo) - https://sectigo.com/ssl-certificates-tls/code-signing
- GlobalSign - https://www.globalsign.com/en/code-signing-certificate
- SSL.com - https://www.ssl.com/certificates/code-signing/
Purchase Process:
- Purchase a code signing certificate from a CA
- Complete identity verification (required for code signing certificates)
- Download the certificate or receive installation instructions
- Install the certificate in your certificate store
Export purchased certificate to PFX:
# List code signing certificates in your store
Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert | Format-Table Subject, Thumbprint, NotAfter
# Export specific certificate to PFX
$thumbprint = "YOUR_CERTIFICATE_THUMBPRINT"
$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert | Where-Object { $_.Thumbprint -eq $thumbprint }
$password = Read-Host -AsSecureString -Prompt "Enter password for PFX file"
Export-PfxCertificate -Cert $cert -FilePath codesign.pfx -Password $passwordNote: Some CAs provide the certificate directly as a PFX file. In that case, you can skip the export step.
Once you have a PFX file, prepare it for GitHub Actions:
-
Convert PFX to Base64:
$certBytes = [System.IO.File]::ReadAllBytes("codesign.pfx") $certBase64 = [Convert]::ToBase64String($certBytes) $certBase64 | Out-File -FilePath "cert-base64.txt" -Encoding ASCII # Display the base64 (copy this for GitHub secret) Write-Host "Base64 certificate:" Write-Host $certBase64
-
Add to GitHub Secrets:
- Go to Repository Settings → Secrets and variables → Actions
- Click "New repository secret"
- Name:
CODESIGN_CERTIFICATE_BASE64 - Value: Paste the base64 content from
cert-base64.txt - Click "Add secret"
- If your PFX has a password, add another secret:
- Name:
CODESIGN_CERTIFICATE_PASSWORD - Value: Your PFX password
- Name:
Quick Start - Use the Helper Script:
We provide a PowerShell script to automate certificate creation:
# Run the helper script (in the .github/workflows directory)
.\create-codesign-certificate.ps1
# Or with custom parameters:
.\create-codesign-certificate.ps1 -Subject "CN=My Company Code Signing" -ValidYears 3The script will:
- Create a self-signed code signing certificate
- Export it to PFX format
- Convert to Base64 for GitHub Actions
- Display instructions for adding to GitHub Secrets
Manual Certificate Creation:
If you prefer to create the certificate manually:
# Step 1: Create or get certificate
# For self-signed (testing):
$cert = New-SelfSignedCertificate `
-Type CodeSigningCert `
-Subject "CN=MyApp Code Signing" `
-KeyUsage DigitalSignature `
-CertStoreLocation Cert:\CurrentUser\My `
-NotAfter (Get-Date).AddYears(1)
# Or get existing certificate:
# $cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
# Step 2: Export to PFX
$pfxPassword = "YourSecurePassword123!"
$pfxPath = "codesign.pfx"
Export-PfxCertificate `
-Cert $cert `
-FilePath $pfxPath `
-Password (ConvertTo-SecureString -String $pfxPassword -AsPlainText -Force)
# Step 3: Convert to Base64
$certBytes = [System.IO.File]::ReadAllBytes($pfxPath)
$certBase64 = [Convert]::ToBase64String($certBytes)
# Step 4: Save base64 to file
$certBase64 | Out-File -FilePath "cert-base64.txt" -Encoding ASCII
Write-Host "Certificate exported to: $pfxPath"
Write-Host "Base64 saved to: cert-base64.txt"
Write-Host ""
Write-Host "Next steps:"
Write-Host "1. Copy the content of cert-base64.txt"
Write-Host "2. Add it as GitHub secret: CODESIGN_CERTIFICATE_BASE64"
Write-Host "3. Add password as GitHub secret: CODESIGN_CERTIFICATE_PASSWORD = $pfxPassword"Security Best Practices:
- ✅ Store the PFX password securely (use GitHub Secrets)
- ✅ Never commit certificates or passwords to the repository
- ✅ Use strong passwords for PFX files
- ✅ Keep your private key secure
- ✅ For production, use certificates from trusted CAs
- ✅ Regularly renew certificates before expiration
Note: If these secrets are not provided, the build will complete successfully without Authenticode signing. The signing is optional and only applies to Release builds.
Recommended branch protection settings:
main:
required_status_checks:
strict: true
contexts:
- "CI Build"
- "Pull Request Validation"
enforce_admins: true
required_pull_request_reviews:
required_approving_review_count: 1
restrictions:
users: []
teams: []The workflows require these permissions:
actions: write(for artifacts)contents: read(for code checkout)issues: write(for dependency update issues)pull-requests: write(for PR validation)
-
Automatic Release (Recommended):
git tag v8.0.11 git push origin v8.0.11
-
Manual Release:
- Go to Actions → Release workflow
- Click "Run workflow"
- Enter version (e.g., "8.0.11")
- Choose prerelease if needed
-
Check for Updates:
- Workflow runs automatically every Monday
- Creates issues for outdated/vulnerable packages
-
Manual Update:
- Go to Actions → Dependency Updates workflow
- Click "Run workflow"
- Choose update type (major/minor/patch/all)
- Creates PR with updates
- Automatically runs on all PRs
- Provides comprehensive validation report
- Checks for breaking changes
- Validates package metadata
To add a new .NET project:
- Add to solution file
- Update
SOLUTION_PATHin workflows if needed - Ensure project follows naming conventions
Edit the strategy.matrix section in ci.yml:
strategy:
matrix:
configuration: [Debug, Release]
platform: [Any CPU, x64, x86]
exclude:
- configuration: Debug
platform: x86Modify the publish-nuget job in release.yml:
- name: Publish to NuGet
run: |
dotnet nuget push *.nupkg --source ${{ env.NUGET_SOURCE }} --api-key ${{ secrets.NUGET_API_KEY }}-
Build Failures:
- Check Visual Studio version compatibility
- Verify .NET SDK versions
- Review platform-specific build issues
-
Package Publishing Issues:
- Verify NuGet API key permissions
- Check package version conflicts
- Ensure package metadata is complete
-
C++ Build Issues:
- Verify Visual Studio Build Tools installation
- Check Windows SDK version
- Review platform toolset compatibility
-
Enable Debug Logging:
- name: Debug step run: | echo "Debug information" dotnet --info env: ACTIONS_STEP_DEBUG: true
-
Check Artifacts:
- Download build artifacts from failed runs
- Review logs for specific error messages
-
Local Testing:
# Test build locally dotnet build "Windows API CodePack/Windows API CodePack.sln" --configuration Release # Test package generation dotnet pack "Windows API CodePack/Windows API CodePack.sln" --configuration Release
When contributing to workflows:
- Test changes in a fork first
- Follow YAML best practices
- Document any new features
- Update this README if needed
For workflow-related issues:
- Check GitHub Actions logs
- Review this documentation
- Open an issue with detailed error information
- Include relevant workflow run URLs