Develop - Version 1.3.1 #15
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: Build, Test & Release | |
| on: | |
| push: | |
| branches: [ "master", "develop" ] | |
| tags: | |
| - 'v*.*.*' | |
| pull_request: | |
| branches: [ "master", "develop" ] | |
| workflow_dispatch: | |
| env: | |
| DOTNET_VERSION: '9.0.x' | |
| SOLUTION_NAME: 'VoiceRecorder.sln' | |
| PROJECT_PATH: 'VoiceRecorder/VoiceRecorder.csproj' | |
| ARTIFACT_NAME: 'AzioVoiceRecorder' | |
| EXE_NAME: 'AzioVoiceRecorder.exe' | |
| jobs: | |
| # ============================================ | |
| # Job 1: Code Quality Checks | |
| # ============================================ | |
| code-quality: | |
| name: Code Quality & Linting | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Restore dependencies | |
| run: dotnet restore ${{ env.SOLUTION_NAME }} | |
| - name: Fix code formatting | |
| run: dotnet format ${{ env.SOLUTION_NAME }} --verbosity diagnostic | |
| - name: Check code formatting | |
| run: dotnet format ${{ env.SOLUTION_NAME }} --verify-no-changes --verbosity diagnostic | |
| - name: Run Code Analysis | |
| run: | | |
| dotnet build ${{ env.SOLUTION_NAME }} ` | |
| --configuration Release ` | |
| --no-restore ` | |
| /p:TreatWarningsAsErrors=true | |
| # ============================================ | |
| # Job 2: Build & Test | |
| # ============================================ | |
| build-and-test: | |
| name: Build & Test (${{ matrix.configuration }}) | |
| runs-on: windows-latest | |
| needs: code-quality | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| configuration: [Debug, Release] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/Directory.Packages.props') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| run: dotnet restore ${{ env.SOLUTION_NAME }} | |
| - name: Build | |
| run: | | |
| dotnet build ${{ env.SOLUTION_NAME }} ` | |
| --configuration ${{ matrix.configuration }} ` | |
| --no-restore ` | |
| /p:ContinuousIntegrationBuild=true ` | |
| /p:AssemblyName=AzioVoiceRecorder | |
| - name: Run Unit Tests | |
| if: matrix.configuration == 'Release' | |
| run: | | |
| dotnet test ${{ env.SOLUTION_NAME }} ` | |
| --configuration ${{ matrix.configuration }} ` | |
| --no-build ` | |
| --verbosity normal ` | |
| --logger "trx;LogFileName=test-results.trx" ` | |
| --results-directory ./TestResults | |
| continue-on-error: true | |
| - name: Upload Test Results | |
| if: always() && matrix.configuration == 'Release' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results | |
| path: TestResults/**/*.trx | |
| retention-days: 7 | |
| - name: Upload Build Artifacts (${{ matrix.configuration }}) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Build-Artifacts-${{ matrix.configuration }} | |
| path: VoiceRecorder/bin/${{ matrix.configuration }} | |
| retention-days: 7 | |
| # ============================================ | |
| # Job 3: Publish Self-Contained (win-x64) - Hybrid Approach | |
| # ============================================ | |
| publish: | |
| name: Publish Self-Contained (win-x64) | |
| runs-on: windows-latest | |
| needs: build-and-test | |
| if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Restore dependencies | |
| run: dotnet restore ${{ env.SOLUTION_NAME }} | |
| - name: Get version from tag or use default | |
| id: version | |
| run: | | |
| if ("${{ github.ref }}" -match "refs/tags/v(.*)") { | |
| $version = $matches[1] | |
| } else { | |
| $version = "1.3.1-dev.${{ github.run_number }}" | |
| } | |
| echo "version=$version" >> $env:GITHUB_OUTPUT | |
| echo "Version: $version" | |
| - name: Publish Self-Contained (win-x64) - Hybrid with ReadyToRun | |
| run: | | |
| dotnet publish ${{ env.PROJECT_PATH }} ` | |
| --configuration Release ` | |
| --runtime win-x64 ` | |
| --self-contained true ` | |
| --output ./publish/win-x64 ` | |
| /p:PublishSingleFile=true ` | |
| /p:PublishTrimmed=false ` | |
| /p:PublishReadyToRun=true ` | |
| /p:PublishReadyToRunShowWarnings=true ` | |
| /p:PublishReadyToRunComposite=true ` | |
| /p:EnableCompressionInSingleFile=true ` | |
| /p:IncludeNativeLibrariesForSelfExtract=true ` | |
| /p:IncludeAllContentForSelfExtract=true ` | |
| /p:DebugType=embedded ` | |
| /p:DebugSymbols=true ` | |
| /p:AssemblyName=AzioVoiceRecorder ` | |
| /p:Version=${{ steps.version.outputs.version }} | |
| - name: List published files | |
| run: Get-ChildItem -Path ./publish/win-x64 -Recurse | |
| - name: Get file size | |
| id: filesize | |
| run: | | |
| $exePath = "./publish/win-x64/${{ env.EXE_NAME }}" | |
| if (Test-Path $exePath) { | |
| $sizeBytes = (Get-Item $exePath).Length | |
| $sizeMB = [math]::Round($sizeBytes / 1MB, 2) | |
| echo "size_mb=$sizeMB" >> $env:GITHUB_OUTPUT | |
| echo "Executable size: $sizeMB MB" | |
| } else { | |
| echo "size_mb=Unknown" >> $env:GITHUB_OUTPUT | |
| Write-Warning "Executable not found at: $exePath" | |
| } | |
| - name: Create ZIP archive | |
| run: | | |
| Compress-Archive -Path ./publish/win-x64/* ` | |
| -DestinationPath ./${{ env.ARTIFACT_NAME }}-v${{ steps.version.outputs.version }}-win-x64.zip ` | |
| -CompressionLevel Optimal | |
| - name: Calculate ZIP hash | |
| id: hash | |
| run: | | |
| $zipPath = "./${{ env.ARTIFACT_NAME }}-v${{ steps.version.outputs.version }}-win-x64.zip" | |
| $hash = Get-FileHash -Path $zipPath -Algorithm SHA256 | |
| $zipSizeBytes = (Get-Item $zipPath).Length | |
| $zipSizeMB = [math]::Round($zipSizeBytes / 1MB, 2) | |
| echo "sha256=$($hash.Hash)" >> $env:GITHUB_OUTPUT | |
| echo "zip_size_mb=$zipSizeMB" >> $env:GITHUB_OUTPUT | |
| echo "SHA256: $($hash.Hash)" | |
| echo "ZIP size: $zipSizeMB MB" | |
| - name: Upload Build Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.ARTIFACT_NAME }}-win-x64 | |
| path: ${{ env.ARTIFACT_NAME }}-v${{ steps.version.outputs.version }}-win-x64.zip | |
| retention-days: 90 | |
| compression-level: 0 | |
| - name: Create build info | |
| run: | | |
| $buildInfo = @" | |
| AzioVoice Recorder - Build Information | |
| ====================================== | |
| Version: ${{ steps.version.outputs.version }} | |
| Configuration: Release (Hybrid - ReadyToRun without Trimming) | |
| Runtime: win-x64 (self-contained) | |
| Executable: ${{ env.EXE_NAME }} | |
| Executable Size: ${{ steps.filesize.outputs.size_mb }} MB | |
| ZIP Size: ${{ steps.hash.outputs.zip_size_mb }} MB | |
| SHA256: ${{ steps.hash.outputs.sha256 }} | |
| Features: | |
| - Single-file executable | |
| - No .NET Runtime required | |
| - ReadyToRun compilation for faster startup | |
| - Full compatibility (no trimming issues) | |
| - Compressed native libraries | |
| - Real-time audio visualization | |
| - Advanced audio filtering (Echo, Flanger, Distortion, Chorus, Compressor) | |
| Build Date: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss UTC") | |
| Commit: ${{ github.sha }} | |
| Repository: ${{ github.repository }} | |
| "@ | |
| $buildInfo | Out-File -FilePath ./publish/win-x64/BUILD_INFO.txt -Encoding utf8 | |
| Write-Output $buildInfo | |
| # ============================================ | |
| # Job 4: Create GitHub Release (on tags) | |
| # ============================================ | |
| release: | |
| name: Create GitHub Release | |
| runs-on: windows-latest | |
| needs: publish | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ env.ARTIFACT_NAME }}-win-x64 | |
| path: ./artifacts | |
| - name: Get version | |
| id: version | |
| run: | | |
| $version = "${{ github.ref_name }}" | |
| echo "version=$version" >> $env:GITHUB_OUTPUT | |
| - name: Create Release Notes | |
| run: | | |
| $version = "${{ steps.version.outputs.version }}" | |
| $notes = @" | |
| # AzioVoice Recorder $version | |
| ## Downloads | |
| **Windows x64 (64-bit Intel/AMD)** | |
| - Self-contained build (no .NET Runtime required) | |
| - Single executable file with ReadyToRun compilation | |
| - Optimized for fast startup without trimming issues | |
| ## Installation | |
| 1. Download the ``${{ env.ARTIFACT_NAME }}-$version-win-x64.zip`` file below | |
| 2. Extract to any folder | |
| 3. Run ``${{ env.EXE_NAME }}`` | |
| 4. (Optional) Grant microphone permissions in Windows Privacy Settings | |
| ## Features | |
| - **Real-time audio recording** with live waveform visualization | |
| - **Built-in audio filters**: Echo, Flanger, Distortion, Chorus, Compressor | |
| - **Device selection** for recording from multiple microphones | |
| - **File explorer** with playback controls and audio management | |
| - **Modern Avalonia UI** with Fluent theme and smooth animations | |
| - **Configurable audio settings** (sample rate, bit depth, channels) | |
| ## Requirements | |
| - **OS**: Windows 10 version 1809 or later / Windows 11 | |
| - **Architecture**: x64 (64-bit) | |
| - **.NET Runtime**: Not required (self-contained) | |
| - **Disk Space**: ~100 MB | |
| - **RAM**: 256 MB minimum, 512 MB recommended | |
| - **Microphone**: Required for recording | |
| ## Performance | |
| This build uses **Hybrid approach**: | |
| - ✅ ReadyToRun compilation for 30-40% faster startup | |
| - ✅ No trimming = full compatibility with CSCore and audio libraries | |
| - ✅ Optimized garbage collection (Server GC) | |
| - ✅ Tiered compilation for runtime optimization | |
| - ✅ Embedded debug symbols for better diagnostics | |
| ## 🔒 Security | |
| - **SHA256 Checksum**: Available in artifact details and BUILD_INFO.txt | |
| - Verify the hash after download to ensure file integrity | |
| - No telemetry or data collection | |
| - All recordings stored locally | |
| ## 🐛 Known Issues | |
| - First-time microphone access may require Windows permissions | |
| --- | |
| **Full Changelog**: https://github.com/${{ github.repository }}/compare/v1.3.0...$version | |
| **Support**: For issues or questions, please visit [Issues](https://github.com/${{ github.repository }}/issues) | |
| "@ | |
| $notes | Out-File -FilePath release_notes.md -Encoding utf8 | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: ./artifacts/*.zip | |
| body_path: release_notes.md | |
| draft: false | |
| prerelease: ${{ contains(github.ref, '-alpha') || contains(github.ref, '-beta') || contains(github.ref, '-rc') }} | |
| generate_release_notes: true | |
| make_latest: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # ============================================ | |
| # Job 5: Security Scanning | |
| # ============================================ | |
| security-scan: | |
| name: Security Scan | |
| runs-on: windows-latest | |
| needs: build-and-test | |
| if: github.event_name == 'push' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Restore dependencies | |
| run: dotnet restore ${{ env.SOLUTION_NAME }} | |
| - name: Check for vulnerable packages | |
| run: | | |
| $output = dotnet list ${{ env.SOLUTION_NAME }} package --vulnerable --include-transitive 2>&1 | |
| Write-Output $output | |
| if ($output -match "has the following vulnerable packages") { | |
| Write-Error "❌ Vulnerable packages detected!" | |
| exit 1 | |
| } else { | |
| Write-Output "✅ No vulnerable packages found" | |
| } | |
| continue-on-error: true | |
| # ============================================ | |
| # Job 6: Dependency Review (PRs only) | |
| # ============================================ | |
| dependency-review: | |
| name: Dependency Review | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Dependency Review | |
| uses: actions/dependency-review-action@v4 | |
| with: | |
| fail-on-severity: moderate | |
| deny-licenses: GPL-2.0, GPL-3.0 |