Nightly & Pre-release Builds #87
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 & Pre-release Builds | |
| on: | |
| schedule: | |
| # Run every day at 12:00am GMT+8 (16:00 UTC) | |
| - cron: "0 16 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Version number (e.g., v0.3.3-nightly.20260104) for manual testing" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| pull-requests: read | |
| jobs: | |
| # Detect if there are new pushes to main branch AND if last commit is feat or fix | |
| detect-nightly-trigger: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_run_nightly: ${{ steps.check.outputs.should_run_nightly }} | |
| commit_type: ${{ steps.check.outputs.commit_type }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Check for new pushes and commit type | |
| id: check | |
| run: | | |
| # Get the last commit time | |
| LAST_COMMIT_TIME=$(git log -1 --pretty=%ct) | |
| # Get the current time | |
| CURRENT_TIME=$(date +%s) | |
| # Get the time since last commit (in hours) | |
| HOURS_SINCE_COMMIT=$(( (CURRENT_TIME - LAST_COMMIT_TIME) / 3600 )) | |
| # Get the last commit message | |
| COMMIT_MSG=$(git log -1 --pretty=%B) | |
| echo "Last commit message: $COMMIT_MSG" | |
| # Skip if it's a release commit or merge commit | |
| if [[ "$COMMIT_MSG" == "chore: release"* ]] || [[ "$COMMIT_MSG" == "Merge"* ]]; then | |
| echo "should_run_nightly=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| # Check if commit starts with feat: or fix: | |
| if [[ "$COMMIT_MSG" == "feat:"* ]]; then | |
| COMMIT_TYPE="feature" | |
| elif [[ "$COMMIT_MSG" == "fix:"* ]]; then | |
| COMMIT_TYPE="fix" | |
| else | |
| COMMIT_TYPE="other" | |
| fi | |
| # Only run nightly if last commit is feat or fix AND was pushed within last 24 hours | |
| if [ $HOURS_SINCE_COMMIT -le 24 ] && ([[ "$COMMIT_MSG" == "feat:"* ]] || [[ "$COMMIT_MSG" == "fix:"* ]]); then | |
| echo "should_run_nightly=true" >> $GITHUB_OUTPUT | |
| echo "commit_type=$COMMIT_TYPE" >> $GITHUB_OUTPUT | |
| else | |
| echo "should_run_nightly=false" >> $GITHUB_OUTPUT | |
| echo "commit_type=$COMMIT_TYPE" >> $GITHUB_OUTPUT | |
| fi | |
| # Build nightly installers | |
| build-nightly: | |
| needs: detect-nightly-trigger | |
| if: | | |
| always() && | |
| (github.event_name == 'workflow_dispatch' || | |
| needs.detect-nightly-trigger.outputs.should_run_nightly == 'true') | |
| runs-on: windows-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Generate nightly version | |
| id: version | |
| run: | | |
| # Check if this is a manual workflow dispatch | |
| if ("${{ github.event_name }}" -eq "workflow_dispatch") { | |
| $version = "${{ inputs.version }}" | |
| Write-Host "📌 Using manual version: $version" | |
| } else { | |
| # Get current date | |
| $date = Get-Date -Format "yyyyMMdd" | |
| # Read base version from pubspec.yaml (e.g. 0.3.3) | |
| $pubspec = Get-Content -Path "pubspec.yaml" -Raw | |
| if ($pubspec -match 'version:\s*([0-9]+\.[0-9]+\.[0-9]+)') { | |
| $baseVersion = $matches[1] | |
| } else { | |
| Write-Error "Unable to read base version from pubspec.yaml" | |
| exit 1 | |
| } | |
| # Create version: v0.3.3-nightly.20260102 | |
| $version = "v$baseVersion-nightly.$date" | |
| Write-Host "📌 Generated nightly version: $version" | |
| } | |
| echo "VERSION=$version" >> $env:GITHUB_OUTPUT | |
| echo "BUILD_NAME=OverKeys-$version" >> $env:GITHUB_OUTPUT | |
| shell: pwsh | |
| - name: Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: "stable" | |
| cache: true | |
| - name: Install InnoSetup | |
| run: | | |
| choco install innosetup -y | |
| Write-Host "✅ InnoSetup installed" | |
| shell: pwsh | |
| - name: Get dependencies | |
| run: flutter pub get | |
| shell: pwsh | |
| - name: Build Flutter Windows app | |
| run: | | |
| .\scripts\ci\build_windows.ps1 -StagingPath "${{ runner.temp }}\inno-staging" | |
| shell: pwsh | |
| - name: Compile InnoSetup installer | |
| run: | | |
| # For nightly builds, we use a different naming scheme | |
| .\scripts\ci\compile_installer.ps1 ` | |
| -StagingPath "${{ runner.temp }}\inno-staging" ` | |
| -OutputPath "${{ runner.temp }}\output" ` | |
| -Version "${{ steps.version.outputs.VERSION }}" | |
| shell: pwsh | |
| - name: Create portable ZIP archive | |
| run: | | |
| Copy-Item -Path "LICENSE" -Destination "${{ runner.temp }}\inno-staging" | |
| .\scripts\ci\compile_zip.ps1 ` | |
| -StagingPath "${{ runner.temp }}\inno-staging" ` | |
| -OutputPath "${{ runner.temp }}\output" ` | |
| -Version "${{ steps.version.outputs.VERSION }}" | |
| shell: pwsh | |
| - name: Fetch Release-Please PR Changelog | |
| id: changelog | |
| run: | | |
| # Find the latest release-please PR (filter by title since it uses PAT) | |
| $prs = @( | |
| (gh pr list ` | |
| --repo ${{ github.repository }} ` | |
| --search "chore: release in:title" ` | |
| --state open ` | |
| --json number,body,title ` | |
| --limit 1) | ConvertFrom-Json | |
| ) | |
| if ($prs.Count -eq 0) { | |
| Write-Host "⚠️ No open release-please PR found, using empty changelog" | |
| $EOF = "EOF_CHANGELOG_$([System.Guid]::NewGuid().ToString())" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "CHANGELOG<<$EOF" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value $EOF | |
| exit 0 | |
| } | |
| $pr = $prs[0] | |
| $prNumber = $pr.number | |
| $body = $pr.body | |
| Write-Host "ℹ️ Found release-please PR #$prNumber" | |
| Write-Host "🔍 Extracting changelog from PR body..." | |
| # Extract changelog content (everything after "🤖 New release prepared" marker) | |
| if ($body -match '(?s)---\s*\n\s*\n##\s*\[.*?\]\(.*?\)\s*\(.*?\)\s*\n(.+)---\s*\nThis PR was generated') { | |
| $changelog = $matches[1].Trim() | |
| Write-Host "✅ Changelog extracted successfully" | |
| # Replace version number in changelog header with nightly version | |
| $nightlyVersion = "${{ steps.version.outputs.VERSION }}" | |
| $changelog = $changelog -replace '##\s*\[[\d\.]+\]\(https://github\.com/[^/]+/[^/]+/compare/v[\d\.]+(\.\.\.v)?[\d\.]+\)\s*\(\d{4}-\d{2}-\d{2}\)', "## [$nightlyVersion] ($((Get-Date).ToString('yyyy-MM-dd')))" | |
| Write-Host "✅ Updated changelog version to $nightlyVersion" | |
| } else { | |
| Write-Host "⚠️ Could not extract changelog from PR #$prNumber" | |
| $changelog = $body | |
| } | |
| # Save to environment variable using EOF delimiter for multiline content with special characters | |
| $EOF = "EOF_CHANGELOG_$([System.Guid]::NewGuid().ToString())" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "CHANGELOG<<$EOF" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value $changelog | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value $EOF | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Create pre-release on GitHub | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| ${{ runner.temp }}/output/overkeys_${{ steps.version.outputs.VERSION }}_x64_setup.exe | |
| ${{ runner.temp }}/output/overkeys_${{ steps.version.outputs.VERSION }}_x64.zip | |
| tag_name: ${{ steps.version.outputs.VERSION }} | |
| name: "${{ steps.version.outputs.VERSION }}" | |
| body: "${{ steps.changelog.outputs.CHANGELOG }}\n\n### 🐛 Found an issue?\nPlease report it with the nightly version number for faster debugging." | |
| prerelease: true | |
| draft: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Report status | |
| if: always() | |
| run: | | |
| Write-Host "✅ Nightly build completed successfully!" | |
| Write-Host "📦 Pre-release created: ${{ steps.version.outputs.VERSION }}" | |
| shell: pwsh |