Merge pull request #2249 from Belphemur/copilot/soundswitch-41w-fix-t… #72
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: Nightly | |
| on: | |
| push: | |
| branches: [dev] | |
| paths: | |
| - ".github/workflows/nightly.yml" | |
| - "SoundSwitch*/**" | |
| - "devVersion.ps1" | |
| - "tools/upload_nightly_r2.py" | |
| env: | |
| DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | |
| PROJECT_NAME: SoundSwitch | |
| CONFIGURATION: Nightly | |
| SENTRY_NAME: soundswitch | |
| jobs: | |
| publish-nightly: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }}-publish-nightly | |
| cancel-in-progress: true | |
| runs-on: windows-latest | |
| outputs: | |
| version: ${{ steps.dev-version.outputs.version }} | |
| download_url: ${{ steps.metadata.outputs['download-url'] }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect target framework and SDK version | |
| id: dotnet-version | |
| shell: pwsh | |
| run: | | |
| [xml]$project = Get-Content "${{ env.PROJECT_NAME }}/${{ env.PROJECT_NAME }}.csproj" | |
| $framework = $project.Project.PropertyGroup.TargetFramework | Select-Object -First 1 | |
| if ([string]::IsNullOrWhiteSpace($framework)) { | |
| throw "Unable to determine TargetFramework from ${{ env.PROJECT_NAME }}/${{ env.PROJECT_NAME }}.csproj" | |
| } | |
| $match = [System.Text.RegularExpressions.Regex]::Match($framework, '^net(?<major>\d+)\.(?<minor>\d+)') | |
| if (-not $match.Success) { | |
| throw "Unable to derive .NET SDK version from TargetFramework '$framework'" | |
| } | |
| $dotnetVersion = "{0}.{1}.x" -f $match.Groups['major'].Value, $match.Groups['minor'].Value | |
| "dotnet-version=$dotnetVersion" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: ${{ steps.dotnet-version.outputs.dotnet-version }} | |
| cache: true | |
| cache-dependency-path: Directory.Packages.props | |
| - name: Install Inno Setup | |
| shell: pwsh | |
| run: | | |
| $regPaths = @( | |
| 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 6_is1', | |
| 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 6_is1' | |
| ) | |
| $isccPath = $null | |
| foreach ($rp in $regPaths) { | |
| if (Test-Path $rp) { | |
| $installDir = (Get-ItemProperty $rp).InstallLocation | |
| if ($installDir -and (Test-Path (Join-Path $installDir 'ISCC.exe'))) { | |
| $isccPath = Join-Path $installDir 'ISCC.exe' | |
| break | |
| } | |
| } | |
| } | |
| if ($isccPath) { | |
| Write-Host "Inno Setup is already installed at: $isccPath" | |
| } else { | |
| Write-Host "Inno Setup not found — installing via winget ..." | |
| winget install --id=JRSoftware.InnoSetup --exact --source winget --scope machine --accept-package-agreements --accept-source-agreements | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "winget install failed with exit code $LASTEXITCODE" | |
| } | |
| Write-Host "Inno Setup installed successfully." | |
| } | |
| - name: Setup Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.x" | |
| - name: Install Python deps | |
| shell: pwsh | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install boto3 markdown | |
| - name: Set nightly dev version | |
| id: dev-version | |
| shell: pwsh | |
| run: | | |
| $version = .\devVersion.ps1 | |
| if ([string]::IsNullOrWhiteSpace($version)) { | |
| throw 'Nightly version was not produced by devVersion.ps1.' | |
| } | |
| "version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| - name: Build nightly installer | |
| shell: pwsh | |
| env: | |
| NIGHTLY_VERSION: ${{ steps.dev-version.outputs.version }} | |
| run: | | |
| $version = $env:NIGHTLY_VERSION | |
| if ([string]::IsNullOrWhiteSpace($version)) { | |
| throw 'Nightly version was not produced by devVersion.ps1.' | |
| } | |
| .\devVersion.ps1 -Version $version | |
| .\tools\Publish-Release.ps1 -BuildFromSource -Configuration Nightly -SkipSigning -InstallerReleaseState Nightly | |
| - name: Upload nightly files | |
| id: metadata | |
| shell: pwsh | |
| env: | |
| R2_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} | |
| R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} | |
| DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} | |
| NIGHTLY_BUCKET: ${{ vars.NIGHTLY_BUCKET }} | |
| NIGHTLY_PUBLIC_BASE_URL: ${{ vars.NIGHTLY_PUBLIC_BASE_URL }} | |
| NIGHTLY_VERSION: ${{ steps.dev-version.outputs.version }} | |
| run: | | |
| $version = $env:NIGHTLY_VERSION | |
| if ([string]::IsNullOrWhiteSpace($version)) { | |
| throw 'Nightly version was not produced by the build workflow.' | |
| } | |
| if ([string]::IsNullOrWhiteSpace($env:R2_ACCOUNT_ID)) { | |
| throw 'R2_ACCOUNT_ID is not configured.' | |
| } | |
| if ([string]::IsNullOrWhiteSpace($env:R2_ACCESS_KEY_ID)) { | |
| throw 'R2_ACCESS_KEY_ID is not configured.' | |
| } | |
| if ([string]::IsNullOrWhiteSpace($env:R2_SECRET_ACCESS_KEY)) { | |
| throw 'R2_SECRET_ACCESS_KEY is not configured.' | |
| } | |
| if ([string]::IsNullOrWhiteSpace($env:NIGHTLY_BUCKET)) { | |
| throw 'NIGHTLY_BUCKET is not configured.' | |
| } | |
| $installer = Get-ChildItem (Join-Path $PWD 'Final\Installer') -Filter '*Nightly_Installer.exe' | Select-Object -First 1 | |
| if (-not $installer) { | |
| throw 'No nightly installer was produced.' | |
| } | |
| python tools\upload_nightly_r2.py ` | |
| --file "$($installer.FullName)" ` | |
| --version "$version" ` | |
| --bucket "$env:NIGHTLY_BUCKET" ` | |
| --account-id "$env:R2_ACCOUNT_ID" ` | |
| --access-key-id "$env:R2_ACCESS_KEY_ID" ` | |
| --secret-access-key "$env:R2_SECRET_ACCESS_KEY" ` | |
| --public-base-url "$env:NIGHTLY_PUBLIC_BASE_URL" ` | |
| --metadata-file "version.json" ` | |
| --discord-webhook "$env:DISCORD_WEBHOOK" ` | |
| --repository "${{ github.repository }}" ` | |
| --prefix nightly | |
| - name: Upload nightly metadata | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: nightly-metadata | |
| path: version.json | |
| comment-nightly-issues: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }}-comment-nightly-issues | |
| cancel-in-progress: true | |
| needs: publish-nightly | |
| runs-on: ubuntu-latest | |
| if: needs.publish-nightly.result == 'success' | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Ensure nightly label exists | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if ! gh label list --repo "${{ github.repository }}" --json name --jq '.[] | .name' | grep -qx "nightly"; then | |
| gh label create "nightly" \ | |
| --description "Fix available in nightly build" \ | |
| --color "0075ca" \ | |
| --repo "${{ github.repository }}" | |
| fi | |
| - name: Comment on fixed issues | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| DOWNLOAD_URL: ${{ needs.publish-nightly.outputs.download_url }} | |
| VERSION: ${{ needs.publish-nightly.outputs.version }} | |
| run: | | |
| if [ -z "$VERSION" ] || [ -z "$DOWNLOAD_URL" ]; then | |
| echo "Missing VERSION or DOWNLOAD_URL output from publish-nightly." | |
| exit 1 | |
| fi | |
| BEFORE="${{ github.event.before }}" | |
| AFTER="${{ github.sha }}" | |
| if git rev-parse --verify "$BEFORE" >/dev/null 2>&1; then | |
| COMMITS=$(git log "$BEFORE..$AFTER" --format="%B") | |
| else | |
| COMMITS=$(git log -20 --format="%B") | |
| fi | |
| ISSUES=$(echo "$COMMITS" | \ | |
| grep -iEo "(close[sd]?|fix(e[sd])?|resolve[sd]?)[[:space:]:]*#([0-9]+)" | \ | |
| grep -Eo "[0-9]+$" | sort -u || true) | |
| if [ -z "$ISSUES" ]; then | |
| echo "No issues referenced in commits." | |
| exit 0 | |
| fi | |
| for ISSUE in $ISSUES; do | |
| STATE=$(gh issue view "$ISSUE" \ | |
| --repo "${{ github.repository }}" \ | |
| --json state --jq '.state' 2>/dev/null || echo "") | |
| LABELS=$(gh issue view "$ISSUE" \ | |
| --repo "${{ github.repository }}" \ | |
| --json labels --jq '.labels[].name' 2>/dev/null || echo "") | |
| if echo "$LABELS" | grep -qx "nightly"; then | |
| echo "Issue #$ISSUE already tagged nightly, skipping." | |
| continue | |
| fi | |
| BODY=$(printf '🌙 This fix is included in nightly build **%s**.\nYou can download it here: %s' "${VERSION}" "${DOWNLOAD_URL}") | |
| gh issue comment "$ISSUE" \ | |
| --repo "${{ github.repository }}" \ | |
| --body "$BODY" | |
| gh issue edit "$ISSUE" \ | |
| --repo "${{ github.repository }}" \ | |
| --add-label "nightly" | |
| echo "Commented and labelled issue #$ISSUE" | |
| done | |
| nightly-sentry: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }}-sentry | |
| cancel-in-progress: true | |
| needs: publish-nightly | |
| runs-on: ubuntu-latest | |
| if: needs.publish-nightly.result == 'success' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Sentry Release | |
| uses: getsentry/action-release@v3.7.0 | |
| env: | |
| SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
| SENTRY_ORG: ${{ env.SENTRY_NAME }} | |
| SENTRY_PROJECT: ${{ env.SENTRY_NAME }} | |
| with: | |
| environment: Nightly | |
| release: "${{ env.PROJECT_NAME }}@${{ needs.publish-nightly.outputs.version }}" |