diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9ef6c2af7..b05586197 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + version: 2 updates: # Enable version updates for GitHub Actions - - package-ecosystem: "github-actions" + - package-ecosystem: "github-actions" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37b7b8ad0..d49a664cf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,17 +42,24 @@ jobs: - name: Summary - Repository checkout shell: pwsh run: | - echo "## đŸ“Ļ Build Cmder - Workflow Summary" >> $env:GITHUB_STEP_SUMMARY - echo "" >> $env:GITHUB_STEP_SUMMARY - echo "### Repository Information" >> $env:GITHUB_STEP_SUMMARY - echo "| Property | Value |" >> $env:GITHUB_STEP_SUMMARY - echo "| --- | --- |" >> $env:GITHUB_STEP_SUMMARY - echo "| Repository | \`${{ github.repository }}\` |" >> $env:GITHUB_STEP_SUMMARY - echo "| Branch | \`${{ github.ref_name }}\` |" >> $env:GITHUB_STEP_SUMMARY - echo "| Commit | \`${{ github.sha }}\` |" >> $env:GITHUB_STEP_SUMMARY - echo "| Actor | @${{ github.actor }} |" >> $env:GITHUB_STEP_SUMMARY - echo "| Workflow | \`${{ github.workflow }}\` |" >> $env:GITHUB_STEP_SUMMARY - echo "" >> $env:GITHUB_STEP_SUMMARY + $summary = @" + ## đŸ“Ļ Build Cmder - Workflow Summary + + Build started: $buildTime + + ### Repository Information + | Property | Value | + | --- | --- | + | Repository | [``${{ github.repository }}``](https://github.com/${{ github.repository }}) | + | Branch | [``$branchName``]($branchLink) | + | Commit | [``${{ github.sha }}``](https://github.com/${{ github.repository }}/commit/${{ github.sha }}) | + | Actor | [@${{ github.actor }}](https://github.com/${{ github.actor }}) | + | Workflow | ``${{ github.workflow }}`` | + | Cmder Version | **$cmderVersion** | + "@ + $summary += "`n" + + $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8 - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v2 @@ -66,10 +73,17 @@ jobs: if: success() shell: pwsh run: | - echo "### ✅ Build Status" >> $env:GITHUB_STEP_SUMMARY - echo "" >> $env:GITHUB_STEP_SUMMARY - echo "Cmder launcher successfully compiled." >> $env:GITHUB_STEP_SUMMARY - echo "" >> $env:GITHUB_STEP_SUMMARY + $summary = @" + + --- + + ### Build Status + + ✅ Cmder built successfully. + + "@ + + $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8 - name: Pack the built files shell: pwsh diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1497bf9ac..3711ffe83 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -50,20 +50,21 @@ jobs: - name: Summary - CodeQL analysis started shell: pwsh run: | - $summary = @( - '## 🔒 CodeQL Security Analysis - Workflow Summary' - '' - '### Analysis Configuration' - '' - '| Property | Value |' - '| --- | --- |' - '| Repository | `${{ github.repository }}` |' - '| Branch | `${{ github.ref_name }}` |' - '| Language | `${{ matrix.language }}` |' - '| Commit | `${{ github.sha }}` |' - '' - ) - $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY + $summary = @" + ## 🔒 CodeQL Security Analysis - Workflow Summary + + ### Analysis Configuration + + | Property | Value | + | --- | --- | + | Repository | ``${{ github.repository }}`` | + | Branch | ``${{ github.ref_name }}`` | + | Language | ``${{ matrix.language }}`` | + | Commit | ``${{ github.sha }}`` | + + "@ + + $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL @@ -89,13 +90,14 @@ jobs: if: success() shell: pwsh run: | - $summary = @( - '### ✅ Build Completed' - '' - 'Cmder launcher built successfully for CodeQL analysis.' - '' - ) - $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY + $summary = @" + ### ✅ Build Completed + + Cmder launcher built successfully for CodeQL analysis. + + "@ + + $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 @@ -106,13 +108,14 @@ jobs: if: success() shell: pwsh run: | - $summary = @( - '### 🔍 CodeQL Analysis Results' - '' - '✅ CodeQL security analysis completed successfully.' - '' - '**Language analyzed:** `${{ matrix.language }}`' - '' - '> Check the Security tab for detailed findings and recommendations.' - ) - $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY + $summary = @" + ### 🔍 CodeQL Analysis Results + + ✅ CodeQL security analysis completed successfully. + + **Language analyzed:** ``${{ matrix.language }}`` + + > Check the Security tab for detailed findings and recommendations. + "@ + + $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5110ab18d..cf08d3245 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,6 +39,8 @@ jobs: steps: - uses: actions/checkout@v6 + with: + fetch-depth: 0 - name: Summary - Test execution started shell: pwsh diff --git a/.github/workflows/vendor.yml b/.github/workflows/vendor.yml index ab254aedf..801f8e872 100644 --- a/.github/workflows/vendor.yml +++ b/.github/workflows/vendor.yml @@ -34,10 +34,11 @@ jobs: $summary = @( '## đŸ“Ļ Update Vendor - Workflow Summary' '' - 'Checking for vendor dependency updates...' + '🔍 Checking for vendor dependency updates...' '' ) - $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY + + $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8 - id: make-changes name: Checking for updates @@ -46,72 +47,256 @@ jobs: run: | $currentVersion = (Get-Content .\vendor\sources.json | ConvertFrom-Json) . .\scripts\update.ps1 -verbose + + # Export count of updated packages (update.ps1 is expected to set $count) + if (-not ($count)) { $count = 0 } Set-GHVariable -Name COUNT_UPDATED -Value $count + $newVersion = (Get-Content .\vendor\sources.json | ConvertFrom-Json) $listUpdated = "" - $updateMessage = "| Name | Old Version | New Version |`n| :--- | ---- | ---- |`n" + $updateMessage = "| Name | Old Version | New Version |`n| :--- | :---: | :---: |`n" + $majorUpdates = @() + $singleDepName = "" + $singleDepOldVersion = "" + $singleDepNewVersion = "" foreach ($s in $newVersion) { $oldVersion = ($currentVersion | Where-Object {$_.name -eq $s.name}).version if ($s.version -ne $oldVersion) { $repoUrl = ($repoUrl = $s.Url.Replace("/archive/", "/releases/")).Substring(0, $repoUrl.IndexOf("/releases/")) + "/releases" + + # Store single dependency info for messages (only if this is the only update) + if ($count -eq 1) { + $singleDepName = $s.name + $singleDepOldVersion = $oldVersion + $singleDepNewVersion = $s.version + } + + # Determine change type and emoji + $changeType = "unknown" + $emoji = "🔄" + $isMajor = $false + try { + # Handle versions with more than 4 parts + $oldVerStr = $oldVersion.Split('-')[0] + $newVerStr = $s.version.Split('-')[0] + + # Split by dots and take only numeric parts, first 4 max + $oldParts = $oldVerStr.Split('.') | Where-Object { $_ -match '^\d+$' } | Select-Object -First 4 + $newParts = $newVerStr.Split('.') | Where-Object { $_ -match '^\d+$' } | Select-Object -First 4 + + # Ensure we have at least 2 parts (major.minor) + if ($oldParts.Count -ge 2 -and $newParts.Count -ge 2) { + $oldVerParseable = $oldParts -join '.' + $newVerParseable = $newParts -join '.' + + $oldVer = [System.Version]::Parse($oldVerParseable) + $newVer = [System.Version]::Parse($newVerParseable) + + if ($newVer.Major -gt $oldVer.Major) { + $changeType = "major" + $emoji = "đŸ”Ĩ" + $isMajor = $true + } elseif ($newVer.Minor -gt $oldVer.Minor) { + $changeType = "minor" + $emoji = "🚀" + } else { + $changeType = "patch" + $emoji = "âŦ†ī¸" + } + } + } catch { + $changeType = "unknown" + $emoji = "🔄" + } + + # Track major updates for changelog section + if ($isMajor) { + $compareUrl = "$repoUrl/compare/v$oldVersion...v$($s.version)" + $majorUpdates += @{ + name = $s.name + oldVersion = $oldVersion + newVersion = $s.version + compareUrl = $compareUrl + repoUrl = $repoUrl + } + } + $listUpdated += "$($s.name) v$($s.version), " - $updateMessage += "| **[$($s.name)]($repoUrl)** | $oldVersion | **$($s.version)** |`n" + $updateMessage += "| $emoji **[$($s.name)]($repoUrl)** | \`$oldVersion\` | **\`$($s.version)\`** |`n" } } + if ($count -eq 0) { return } + Set-GHVariable -Name LIST_UPDATED -Value $listUpdated.Trim(', ') - echo "UPDATE_MESSAGE<< 0 && env.HAS_BREAKING_CHANGES != 'True' + shell: pwsh + run: | + try { + echo "### 🚀 Auto-merging Updates" >> $env:GITHUB_STEP_SUMMARY + echo "" >> $env:GITHUB_STEP_SUMMARY + echo "Attempting to automatically merge non-breaking changes to master..." >> $env:GITHUB_STEP_SUMMARY + + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + # Commit the changes + git add vendor/sources.json + $commitResult = git commit -m "âŦ†ī¸ Update dependencies ($env:LIST_UPDATED)" + + # Push directly to master + git push origin HEAD:master + + echo "" >> $env:GITHUB_STEP_SUMMARY + echo "✅ **Success!** Updates have been automatically merged to master." >> $env:GITHUB_STEP_SUMMARY + echo "" >> $env:GITHUB_STEP_SUMMARY + echo "**Updated dependencies:** $env:LIST_UPDATED" >> $env:GITHUB_STEP_SUMMARY + + # Set a flag to skip PR creation + echo "AUTO_MERGED=true" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + } catch { + echo "" >> $env:GITHUB_STEP_SUMMARY + echo "âš ī¸ **Warning:** Unable to automatically merge updates." >> $env:GITHUB_STEP_SUMMARY + echo "" >> $env:GITHUB_STEP_SUMMARY + echo "**Error:** $($_.Exception.Message)" >> $env:GITHUB_STEP_SUMMARY + echo "" >> $env:GITHUB_STEP_SUMMARY + echo "Falling back to creating a pull request..." >> $env:GITHUB_STEP_SUMMARY + + Write-Warning "Failed to auto-merge: $($_.Exception.Message)" + + # Reset the commit if one was made + if ($commitResult) { + git reset --hard HEAD~1 + } + + # Set flag to create PR instead + echo "AUTO_MERGED=false" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 } - uses: peter-evans/create-pull-request@v8 - if: env.COUNT_UPDATED > 0 + if: env.COUNT_UPDATED > 0 && (env.HAS_BREAKING_CHANGES == 'True' || env.AUTO_MERGED == 'false') with: - title: 'Updates to `${{ env.COUNT_UPDATED }}` vendored dependencies' + title: ${{ env.COUNT_UPDATED == '1' && format('âŦ†ī¸ Update {0}', env.LIST_UPDATED) || format('âŦ†ī¸ Update {0} vendored dependencies', env.COUNT_UPDATED) }} body: | - ### Automatically updated `${{ env.COUNT_UPDATED }}` dependencies: + ### ${{ env.COUNT_UPDATED == 1 && format('đŸ“Ļ Updated {0} from `{1}` to `{2}`', env.SINGLE_DEP_NAME, env.SINGLE_DEP_OLD_VERSION, env.SINGLE_DEP_NEW_VERSION) || format('đŸ“Ļ Automatically updated `{0}` dependencies', env.COUNT_UPDATED) }} + ${{ env.UPDATE_MESSAGE }} + + ${{ env.CHANGELOG_SECTION }} + --- - Please verify and then **Merge** the pull request to update. + + ${{ env.HAS_BREAKING_CHANGES == 'True' && 'âš ī¸ **This update contains major version changes that may include breaking changes.**' || 'â„šī¸ This update only contains minor or patch changes.' }} + + Please verify and then **Merge** the pull request to apply the updates. commit-message: 'âŦ†ī¸ Update dependencies (${{ env.LIST_UPDATED }})' branch: update-vendor base: master - name: Summary - Pull request created - if: env.COUNT_UPDATED > 0 + if: env.COUNT_UPDATED > 0 && (env.HAS_BREAKING_CHANGES == 'True' || env.AUTO_MERGED == 'false') shell: pwsh run: | - $summary = @( - '### 🎉 Pull Request Created' - '' - 'A pull request has been created to update the vendor dependencies.' - '' - '**Branch:** `update-vendor`' - '' - $env:LIST_UPDATED -and "**Updated dependencies:** $env:LIST_UPDATED" -or "**Updated dependencies:** " - '' - '> Please review and merge the pull request to apply the updates.' - ) - $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY + $updatedLine = if (-not [string]::IsNullOrEmpty($env:LIST_UPDATED)) { "**Updated dependencies:** $env:LIST_UPDATED" } else { "**Updated dependencies:** " } + $summary = @" + ### 🎉 Pull Request Created + + A pull request has been created to update the vendor dependencies. + + **Branch:** `update-vendor` + + $updatedLine + + "@ + + if ($env:HAS_BREAKING_CHANGES -eq 'True') { + $summary += "> âš ī¸ **Manual review required:** This update contains major version changes." + } else { + $summary += "> â„šī¸ **Note:** Auto-merge failed, manual review required." + } + + $summary += @" + > Please review and merge the pull request to apply the updates. + + "@ + + $summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8 diff --git a/scripts/update.ps1 b/scripts/update.ps1 index c6b982d7c..2d1b5d1bc 100644 --- a/scripts/update.ps1 +++ b/scripts/update.ps1 @@ -259,6 +259,8 @@ function Fetch-DownloadUrl { } $count = 0 +$hasBreakingChanges = $false +$updateDetails = @() # Read the current sources content $sources = Get-Content $sourcesPath | Out-String | ConvertFrom-Json @@ -301,6 +303,52 @@ foreach ($s in $sources) { # } $count++ + + # Analyze version change type + $changeType = "unknown" + try { + # Try parsing as semantic version + # Handle versions with more than 4 parts by taking only the first 3-4 parts + $oldVerStr = $s.version.Split('-')[0] + $newVerStr = $version.Split('-')[0] + + # Split by dots and take only numeric parts, first 4 max + $oldParts = $oldVerStr.Split('.') | Where-Object { $_ -match '^\d+$' } | Select-Object -First 4 + $newParts = $newVerStr.Split('.') | Where-Object { $_ -match '^\d+$' } | Select-Object -First 4 + + # Ensure we have at least 2 parts (major.minor) + if ($oldParts.Count -ge 2 -and $newParts.Count -ge 2) { + $oldVerParseable = $oldParts -join '.' + $newVerParseable = $newParts -join '.' + + $oldVer = [System.Version]::Parse($oldVerParseable) + $newVer = [System.Version]::Parse($newVerParseable) + + if ($newVer.Major -gt $oldVer.Major) { + $changeType = "major" + $hasBreakingChanges = $true + } elseif ($newVer.Minor -gt $oldVer.Minor) { + $changeType = "minor" + } else { + $changeType = "patch" + } + } else { + # Not enough numeric parts for semantic versioning + throw "Not enough numeric version parts" + } + } catch { + # If semantic versioning fails, treat as unknown (potentially breaking) + $changeType = "unknown" + $hasBreakingChanges = $true + Write-Verbose "Could not parse version as semantic version, treating as potentially breaking" + } + + $updateDetails += @{ + name = $s.name + oldVersion = $s.version + newVersion = $version + changeType = $changeType + } } $s.url = $downloadUrl @@ -314,12 +362,16 @@ if ($count -eq 0) { return } -if ($Env:APPVEYOR -eq 'True') { - Add-AppveyorMessage -Message "Successfully updated $count dependencies." -Category Information -} - +# Export update details for GitHub Actions if ($Env:GITHUB_ACTIONS -eq 'true') { + $updateDetailsJson = $updateDetails | ConvertTo-Json -Compress + Write-Output "UPDATE_DETAILS=$updateDetailsJson" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + Write-Output "HAS_BREAKING_CHANGES=$hasBreakingChanges" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 Write-Output "::notice title=Task Complete::Successfully updated $count dependencies." } +if ($Env:APPVEYOR -eq 'True') { + Add-AppveyorMessage -Message "Successfully updated $count dependencies." -Category Information +} + Write-Host -ForegroundColor green "Successfully updated $count dependencies."