Merge pull request #4 from TheMysteriousStranger90/develop #10
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: 'LogAnalyzerForWindows.sln' | |
| PROJECT_PATH: 'LogAnalyzerForWindows/LogAnalyzerForWindows.csproj' | |
| ARTIFACT_NAME: 'LogAnalyzerForWindows' | |
| 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: Check code formatting | |
| run: dotnet format ${{ env.SOLUTION_NAME }} --verify-no-changes --verbosity diagnostic | |
| continue-on-error: true | |
| - name: Run Code Analysis | |
| run: dotnet build ${{ env.SOLUTION_NAME }} --configuration Release --no-restore /p:TreatWarningsAsErrors=false | |
| # ============================================ | |
| # 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 | |
| - 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 | |
| # ============================================ | |
| # 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 = "2.0.0-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: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/LogAnalyzerForWindows.exe" | |
| 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 | |
| } | |
| - 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 = @" | |
| Build Information | |
| ================= | |
| Version: ${{ steps.version.outputs.version }} | |
| Configuration: Release (Hybrid - ReadyToRun without Trimming) | |
| Runtime: win-x64 (self-contained) | |
| 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 | |
| Build Date: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss UTC") | |
| Commit: ${{ github.sha }} | |
| "@ | |
| $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 | |
| if: steps.changelog.outputs.found != 'true' | |
| run: | | |
| $version = "${{ steps.version.outputs.version }}" | |
| $notes = @" | |
| # ${{ env.ARTIFACT_NAME }} $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 | |
| - Size: ~85-95 MB (compressed ZIP) | |
| ## 🚀 Installation | |
| 1. Download the ZIP file below | |
| 2. Extract to any folder | |
| 3. Run ``LogAnalyzerForWindows.exe`` | |
| 4. (Optional) Run as Administrator for full access to Security logs | |
| ## ✨ Features | |
| - Real-time Windows Event Log monitoring | |
| - Database mode for historical analysis with pagination | |
| - Session-based filtering and export | |
| - Email integration (requires SMTP configuration) | |
| - Multi-format export (TXT, JSON) | |
| - Automatic log archiving with ZIP compression | |
| ## 📋 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 | |
| ## ⚡ Performance | |
| This build uses **Hybrid approach**: | |
| - ✅ ReadyToRun compilation for 30-40% faster startup | |
| - ✅ No trimming = full compatibility with EF Core and JSON serialization | |
| - ✅ Optimized garbage collection (Server GC) | |
| - ✅ Tiered compilation for runtime optimization | |
| ## 🔒 Security | |
| - **SHA256 Checksum**: Available in artifact details | |
| - Verify the hash after download to ensure file integrity | |
| - Supports running as Administrator for elevated log access | |
| --- | |
| **Full Changelog**: https://github.com/${{ github.repository }}/compare/v1.0.0...$version | |
| "@ | |
| $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 |