Compare commits

..

27 Commits

Author SHA1 Message Date
Dax T. Games
ae3ed7718c Merge remote-tracking branch 'upstream/master' into copilot/improve-vendor-ci-cd-messaging
* upstream/master:
  trigger
  trigger
2026-02-28 09:56:13 -05:00
Dax T. Games
1e2d8eb47d fixes 2026-02-28 08:54:40 -05:00
Dax T. Games
d495b06726 fixes 2026-02-22 15:14:05 -05:00
Dax T. Games
a6f0015b16 cleanup 2026-02-22 13:47:37 -05:00
Dax T. Games
8c0e2c542c Fix workflow YAML 2026-02-22 18:25:56 -05:00
Dax T. Games
f2bde614d4 Fix workflows 2026-02-22 18:21:46 -05:00
copilot-swe-agent[bot]
7b86263b0a Wrap dependency count in backticks for consistency
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 06:26:34 +00:00
copilot-swe-agent[bot]
10a0675c96 Remove unused $headBeforeReset variable
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 06:22:39 +00:00
David Refoua
400cdfed54 Update .github/workflows/vendor.yml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-15 09:48:22 +03:30
copilot-swe-agent[bot]
a475de2d4c Remove temporary comment from CodeQL workflow
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 04:14:39 +00:00
copilot-swe-agent[bot]
1afbd4ae49 Use PowerShell here-string to fix CodeQL parser error (reverted previous attempts)
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 04:13:57 +00:00
GitHub Copilot
82f7fdd61a Merge and use PowerShell here-string for CodeQL summary 2025-12-15 04:12:54 +00:00
copilot-swe-agent[bot]
e598536485 Use PowerShell here-string for CodeQL summary to fix parser error
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 04:11:27 +00:00
copilot-swe-agent[bot]
9cfff38939 Fix CodeQL PowerShell syntax by using Write-Output instead of echo
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 03:33:57 +00:00
copilot-swe-agent[bot]
2cc1125f62 Fix CodeQL workflow PowerShell string termination error
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 03:22:14 +00:00
copilot-swe-agent[bot]
4911924259 Make new version bold in dependency update table
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 01:43:35 +00:00
copilot-swe-agent[bot]
cd2c4ec877 Update version change emojis: 🔥 major, 🚀 minor, ⬆️ patch
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 01:30:12 +00:00
copilot-swe-agent[bot]
0f6584fa02 Improve variable initialization logic with better error handling
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 01:11:46 +00:00
copilot-swe-agent[bot]
570b1d6043 Fix single dependency variable initialization to prevent CI failures
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 01:09:41 +00:00
David Refoua
fa2a34a4c0 Merge branch 'master' into copilot/improve-vendor-ci-cd-messaging 2025-12-15 04:29:44 +03:30
copilot-swe-agent[bot]
e6fea0bbab Use single emoji and show dependency name/version for single updates
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-08 21:22:53 +00:00
copilot-swe-agent[bot]
bf90303c96 Remove Change Type column and add collapsible changelog for major updates
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-08 21:12:27 +00:00
copilot-swe-agent[bot]
e64c0b110d Fix git reset logic in auto-merge error handling
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-08 20:57:57 +00:00
copilot-swe-agent[bot]
f2e8ae5189 Improve version parsing to handle complex version strings
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-08 20:56:30 +00:00
copilot-swe-agent[bot]
4d21982f26 Fix trailing spaces in vendor workflow YAML
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-08 20:53:19 +00:00
copilot-swe-agent[bot]
be60888258 Improve vendor CI/CD workflow with better messaging and auto-merge
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-08 20:52:20 +00:00
copilot-swe-agent[bot]
d61a4f7f36 Initial plan 2025-12-08 20:46:58 +00:00
9 changed files with 345 additions and 421 deletions

View File

@@ -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"

View File

@@ -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
<small>Build started: $buildTime</small>
### 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

View File

@@ -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

View File

@@ -39,6 +39,8 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Summary - Test execution started
shell: pwsh

View File

@@ -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<<<EOF`n$updateMessage`n<EOF" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
# Set single dependency variables (they will only be used if COUNT_UPDATED is 1)
# Use safe fallback values in case variables weren't set (shouldn't happen but prevents errors)
if ([string]::IsNullOrEmpty($singleDepName) -and $count -eq 1) {
# This shouldn't happen, but if it does, log a warning
Write-Warning "Single dependency name not set despite count being 1"
$singleDepName = "unknown-package"
$singleDepOldVersion = "unknown"
$singleDepNewVersion = "unknown"
} elseif ([string]::IsNullOrEmpty($singleDepName)) {
# For multiple dependencies, set placeholder values (won't be used)
$singleDepName = ""
$singleDepOldVersion = ""
$singleDepNewVersion = ""
}
Set-GHVariable -Name SINGLE_DEP_NAME -Value $singleDepName
Set-GHVariable -Name SINGLE_DEP_OLD_VERSION -Value $singleDepOldVersion
Set-GHVariable -Name SINGLE_DEP_NEW_VERSION -Value $singleDepNewVersion
# Write multiline UPDATE_MESSAGE to GITHUB_ENV
Add-Content -Path $env:GITHUB_ENV -Value "UPDATE_MESSAGE<<EOF"
Add-Content -Path $env:GITHUB_ENV -Value $updateMessage
Add-Content -Path $env:GITHUB_ENV -Value "EOF"
# Generate major updates changelog section and export
if ($majorUpdates.Count -gt 0) {
$changelogSection = "`n<details>`n<summary>🔥 Major version updates - View changelog</summary>`n`n"
foreach ($update in $majorUpdates) {
$changelogSection += "### [$($update.name)]($($update.repoUrl))`n"
$changelogSection += "**$($update.oldVersion)** → **$($update.newVersion)**`n`n"
$changelogSection += "- [View full changelog]($($update.compareUrl))`n"
$changelogSection += "- [Release notes]($($update.repoUrl)/tag/v$($update.newVersion))`n`n"
}
$changelogSection += "</details>`n"
Add-Content -Path $env:GITHUB_ENV -Value "CHANGELOG_SECTION<<EOF"
Add-Content -Path $env:GITHUB_ENV -Value $changelogSection
Add-Content -Path $env:GITHUB_ENV -Value "EOF"
Add-Content -Path $env:GITHUB_ENV -Value "HAS_BREAKING_CHANGES=True"
} else {
Add-Content -Path $env:GITHUB_ENV -Value "CHANGELOG_SECTION="
Add-Content -Path $env:GITHUB_ENV -Value "HAS_BREAKING_CHANGES=False"
}
- name: Summary - Update check results
shell: pwsh
run: |
$count = [int]$env:COUNT_UPDATED
if ($count -eq 0) {
$summary = @(
'### ✅ No Updates Available'
''
'All vendor dependencies are up to date.'
'### ✅ No Updates Available'
''
'All vendor dependencies are up to date! 🎉'
''
)
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY
} else {
$word = if ($count -eq 1) { 'dependency' } else { 'dependencies' }
$summary = @(
'### 🔄 Updates Found'
''
"**$count** vendor $word updated:"
''
$env:UPDATE_MESSAGE
''
'### 🔄 Updates Found'
''
)
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY
$summary += '📦 **' + $env:SINGLE_DEP_NAME + '** updated from `' + $env:SINGLE_DEP_OLD_VERSION + '` to `' + $env:SINGLE_DEP_NEW_VERSION + '`' + [Environment]::NewLine + [Environment]::NewLine
$summary += '📦 **' + $count + '** vendor ' + $word + ' updated:' + [Environment]::NewLine + [Environment]::NewLine
}
$summary += $env:UPDATE_MESSAGE + [Environment]::NewLine
# Check if we can auto-merge (only minor/patch changes)
$hasBreaking = $env:HAS_BREAKING_CHANGES -eq 'True'
if ($hasBreaking) {
$summary += '> ⚠️ **Note:** This update contains major version changes that may include breaking changes.'
} else {
$summary += '> **Note:** This update only contains minor or patch changes.'
}
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Auto-merge minor updates
if: env.COUNT_UPDATED > 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

View File

@@ -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
}
# 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
}
if ($Env:GITHUB_ACTIONS -eq 'true') {
Write-Output "::notice title=Task Complete::Successfully updated $count dependencies."
}
Write-Host -ForegroundColor green "Successfully updated $count dependencies."

View File

@@ -1,330 +0,0 @@
<#
.SYNOPSIS
Integrate Cmder into the system and optionally add Cmder VS Code terminal profiles.
.DESCRIPTION
This script can perform three primary actions:
- Add/merge Cmder terminal profiles into VS Code's `terminal.integrated.profiles.windows` (when `-VSCode` is used).
- Set the user environment variable `CMDER_ROOT` (when `-SetRootEnv` is used).
- Prepend `CMDER_ROOT` to the user's `Path` variable (when `-PrependPath` is used).
The script attempts to discover a VS Code `settings.json` when `-SettingsJsonPath` is not provided. It will
only create a timestamped backup and write `settings.json` if the merged JSON differs from the original.
.PARAMETER VSCode
Switch to enable adding/merging Cmder profiles into VS Code `settings.json`. Defaults to enabled if the `code` command is found in the PATH.
.PARAMETER SetRootEnv
Switch to set the user environment variable `CMDER_ROOT` (if missing). Defaults to enabled.
.PARAMETER PrependPath
Switch to prepend `CMDER_ROOT` to the user's `Path` (if `cmder.exe` is not already on the Path). Defaults to enabled.
.PARAMETER CmderRoot
Path to the Cmder installation root. Defaults to the `CMDER_ROOT` environment variable if present, otherwise the current directory.
.PARAMETER DefaultProfile
Optional name of the Cmder profile to set as the default VS Code terminal profile. Valid values: 'Cmder - Cmd', 'Cmder - PowerShell', 'Cmder - Bash'.
.PARAMETER Confirm
When supplied, the script will skip the interactive confirmation prompt and proceed non-interactively. If omitted the script prompts in the terminal (default behavior).
.PARAMETER SettingsJsonPath
Explicit path to the VS Code `settings.json` to modify. If omitted the script attempts to discover a suitable file under common locations.
.EXAMPLE
# Dry-run / test (read-only):
.
.\vendor\bin\Add-CmderVSCodeProfiles.ps1 -SettingsJsonPath "$env:APPDATA\Code\User\settings.json" -Confirm
.EXAMPLE
# Interactive use (default):
.
.\vendor\bin\Add-CmderVSCodeProfiles.ps1 -SettingsJsonPath "$env:APPDATA\Code\User\settings.json"
.NOTES
- The script writes a timestamped backup only when changes are required.
- It uses a terminal prompt (`Read-Host`) for confirmation unless `-Confirm` is provided.
- It requires appropriate permissions to modify the user's registry environment variables and to write the `settings.json` file.
Script: vendor/bin/Add-CmderVSCodeProfiles.ps1
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)][switch]$VSCode = $true,
[Parameter(Mandatory=$false)][switch]$SetRootEnv = $true,
[Parameter(Mandatory=$false)][switch]$PrependPath = $true,
[Parameter(Mandatory=$false)]
# default $CmderRoot to the environment variable CMDER_ROOT if set, otherwise to the current directory
[string]$CmderRoot = $env:CMDER_ROOT ? $env:CMDER_ROOT : (Get-Location).ProviderPath,
[Parameter(Mandatory=$false)]
[string]$DefaultProfile,
[Parameter(Mandatory=$false)][switch]$Confirm,
[Parameter(Mandatory=$false)]
[string]$SettingsJsonPath
)
if (-not (get-command 'code')) {
Write-Error "VS Code command 'code' not found in PATH. Ensure VS Code is installed and 'code' is available in the command line."
$VSCode = $false
}
if ($VSCode -and $DefaultProfile) {
if ($DefaultProfile -notin @('Cmder - Cmd','Cmder - PowerShell','Cmder - Bash').Contains($DefaultProfile)) {
Write-Error "Invalid value for -DefaultProfile: '$DefaultProfile'. Valid options are 'Cmder - Cmd', 'Cmder - PowerShell', or 'Cmder - Bash'."
exit 1
}
}
function Merge-ProfilesToObject($target) {
# Collect existing profiles into a plain hashtable (handle IDictionary or PSCustomObject)
$combined = @{}
$existing = $null
if ($target.PSObject.Properties.Name -contains $propName) {
$existing = $target.PSObject.Properties[$propName].Value
}
if ($existing -ne $null) {
if ($existing -is [System.Collections.IDictionary]) {
foreach ($k in $existing.Keys) { $combined[$k] = $existing[$k] }
} else {
foreach ($p in $existing.PSObject.Properties) { $combined[$p.Name] = $p.Value }
}
}
# Overlay/insert Cmder profiles — only add profiles that don't already exist
foreach ($k in $cmderProfiles.Keys) {
if ($combined.ContainsKey($k)) {
Write-Output "- Skipping existing profile '$k'!"
} else {
$combined[$k] = $cmderProfiles[$k]
Write-Output "- Adding missing profile '$k'"
}
}
# Create an ordered hashtable with keys sorted alphabetically
$ordered = [ordered]@{}
foreach ($k in ($combined.Keys | Sort-Object)) { $ordered[$k] = $combined[$k] }
# Remove any existing literal property with the dotted name, then re-add as a note property
if ($target.PSObject.Properties.Name -contains $propName) {
$target.PSObject.Properties.Remove($propName)
}
$target | Add-Member -NotePropertyName $propName -NotePropertyValue $ordered -Force
# If a default profile was requested and exists in the ordered set, set the default profile
if ($DefaultProfile) {
$defaultPropName = 'terminal.integrated.defaultProfile.windows'
if ($ordered.Keys -contains $DefaultProfile) {
if ($target.$defaultPropName -ne $DefaultProfile) {
if ($target.PSObject.Properties.Name -contains $defaultPropName) { $target.PSObject.Properties.Remove($defaultPropName) }
$target | Add-Member -NotePropertyName $defaultPropName -NotePropertyValue $DefaultProfile -Force
Write-Output "- Setting default profile to '$DefaultProfile'"
}
else {
Write-Output "- '$DefaultProfile' is already set as the default, no change needed."
}
}
else {
Write-Output "- Default profile '$DefaultProfile' not found in profiles list, skipping default profile set."
}
}
}
if ($VSCode -and -not $SettingsJsonPath) {
# If the user didn't provide a path, try to discover a VS Code `settings.json` under %APPDATA% and common roots
if (-not $SettingsJsonPath) {
$candidates = @()
$roots = @()
if ($env:APPDATA) { $roots += $env:APPDATA }
if ($env:LOCALAPPDATA) { $roots += $env:LOCALAPPDATA }
if ($env:USERPROFILE) { $roots += $env:USERPROFILE }
if ($env:ProgramFiles) { $roots += $env:ProgramFiles }
if (${env:ProgramFiles(x86)}) { $roots += ${env:ProgramFiles(x86)} }
foreach ($root in $roots | Select-Object -Unique) {
if (-not (Test-Path $root)) { continue }
try {
$found = Get-ChildItem -Path $root -Recurse -Filter settings.json -ErrorAction SilentlyContinue -Force
if ($found) { $candidates += $found }
} catch {}
}
$candidate = $candidates | Where-Object {
$_.FullName -match '\\User\\settings.json$' -and (
$_.FullName -match '\\Code( | - |\\)' -or
$_.FullName -match '\\data\\' -or
$_.FullName -match 'vscode' -or
$_.FullName -match 'Code -'
)
} | Select-Object -First 1
if (-not $candidate) {
$common = @(
Join-Path $env:APPDATA 'Code\\User\\settings.json',
Join-Path $env:APPDATA 'Code - Insiders\\User\\settings.json',
Join-Path $env:APPDATA 'Code - OSS\\User\\settings.json'
)
foreach ($p in $common) { if (Test-Path $p) { $candidate = Get-Item $p; break } }
}
if ($candidate) {
$SettingsJsonPath = $candidate.FullName
} else {
Write-Error "Could not discover a VS Code 'settings.json' (installed or portable). Provide -SettingsJsonPath explicitly."
exit 3
}
}
$SettingsJsonPath = (Resolve-Path -LiteralPath $SettingsJsonPath).ProviderPath
}
$CmderRoot = (Resolve-Path -LiteralPath $CmderRoot)
Write-Output "Configuration Summary:`n"
if ($VSCode) {
Write-Output "Add Missing VS Code Terminal Profiles: $SettingsJsonPath"
if ($DefaultProfile) {
Write-Output "Set Default VS Code Terminal Profile: $DefaultProfile"
}
}
if ($SetRootEnv) {
Write-Output "Add CMDER_ROOT environment variable: Yes (if not already present)"
}
if ($PrependPath) {
Write-Output "Prepend CMDER_ROOT to User Path: Yes (if not already present)"
}
if (-not $Confirm) {
# Prompt the user in the terminal (Read-Host) before making changes — default: No
$prompt = "`nDo you want to continue? [y/N]"
$answer = Read-Host -Prompt $prompt
if (-not $answer) { $answer = 'N' }
if ($answer.ToLower() -notin @('y','yes')) {
Write-Output "Cmder System Integration cancelled by user input. No changes were made."
exit 2
}
}
if ($SetRootEnv) {
Write-Output "`nEnvironment Changes:`n"
# Set user environment variable CMDER_ROOT if not already set in the registry.
$didSet = $false
$regPath = 'HKCU:\Environment'
$regVal = $null
$prop = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue
if ($prop -ne $null -and $prop.PSObject.Properties.Name -contains 'CMDER_ROOT') { $regVal = $prop.CMDER_ROOT }
if ([string]::IsNullOrEmpty($regVal)) {
Write-Output "- No CMDER_ROOT found in registry; will write HKCU:\Environment\CMDER_ROOT -> $CmderRoot"
[Environment]::SetEnvironmentVariable('CMDER_ROOT', $CmderRoot, 'User')
$didSet = $true
}
else {
Write-Output "- User environment variable 'CMDER_ROOT' already exists in registry with value '$regVal', skipping set."
}
$env:CMDER_ROOT = $CmderRoot
}
if ($PrependPath) {
write-Output "`nPath Changes:`n"
# Prepend $ENV:CMDER_ROOT to the current users Path variable if not already present
if ((get-command 'cmder.exe' -ErrorAction SilentlyContinue) -eq $null) {
Write-Output "- 'cmder.exe' not found in current PATH, checking registry user Path variable..."
$pathVal = $null
if ($prop -ne $null -and $prop.PSObject.Properties.Name -contains 'Path') { $pathVal = $prop.Path }
if ($pathVal -ne $null -and -not ($pathVal.Split(';') -contains $env:CMDER_ROOT)) {
Write-Output "- Prepending '$env:CMDER_ROOT' to user Path environment variable in registry."
$newPath = "$env:CMDER_ROOT;$pathVal"
[Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
}
}
else {
$CmderPath = (Get-Command 'cmder.exe' -ErrorAction SilentlyContinue).Source
Write-Output "- 'cmder.exe' found in current PATH at '$CmderPath', skipping Path modification."
}
}
if ($VSCode) {
$cmderProfiles = @{}
if (($DefaultProfile -eq 'Cmder - Cmd') -or $VSCode) {
$cmderProfiles['Cmder - Cmd'] = @{
name = 'Cmder - Cmd'
path = @('${env:windir}\Sysnative\cmd.exe','${env:windir}\System32\cmd.exe')
args = @('/k','${env:cmder_root}\vendor\bin\vscode_init.cmd')
icon = 'terminal-cmd'
color = 'terminal.ansiGreen'
}
}
if (($DefaultProfile -eq 'Cmder - PowerShell') -or $VSCode) {
$cmderProfiles['Cmder - PowerShell'] = @{
name = 'Cmder - PowerShell'
source = 'PowerShell'
args = @('-ExecutionPolicy','Bypass','-NoLogo','-NoProfile','-NoExit','-Command','Invoke-Expression ''. ''''${env:CMDER_ROOT}\vendor\profile.ps1''''''')
icon = 'terminal-powershell'
color = 'terminal.ansiYellow'
}
}
if (($DefaultProfile -eq 'Cmder - Bash') -or $VSCode) {
$cmderProfiles['Cmder - Bash'] = @{
name = 'Cmder - Bash'
path = @('${env:windir}\Sysnative\cmd.exe','${env:windir}\System32\cmd.exe')
args = @('/k','${env:cmder_root}\vendor\start_git_bash.cmd')
icon = 'terminal-bash'
color = 'terminal.ansiBlue'
}
}
Write-Output "`nProfile Changes:`n"
Write-Output "Reading '$SettingsJsonPath'...`n"
$raw = Get-Content -Raw -Path $SettingsJsonPath -ErrorAction Stop
try {
$json = $raw | ConvertFrom-Json -ErrorAction Stop
} catch {
Write-Error "Failed to parse JSON in $($SettingsJsonPath): $_"
exit 3
}
# Normalized copy of original JSON for change detection
$originalNormalized = $json | ConvertTo-Json -Depth 10
# Write-Output "Preparing to merge Cmder profiles into settings"
$propName = 'terminal.integrated.profiles.windows'
if ($json -is [System.Array]) {
foreach ($item in $json) { Merge-ProfilesToObject $item }
} else {
Merge-ProfilesToObject $json
}
# Compare normalized JSON and only back up / write if changes occurred
$newNormalized = $json | ConvertTo-Json -Depth 10
if ($originalNormalized -ne $newNormalized) {
$timestamp = (Get-Date).ToString('yyyyMMdd-HHmmss')
$backup = "$SettingsJsonPath.$timestamp.backup"
Write-Output "- Backing up 'settings.json' to '$backup' before applying changes..."
Copy-Item -Path $SettingsJsonPath -Destination $backup -Force
$pretty = $json | ConvertTo-Json -Depth 10
[System.IO.File]::WriteAllText($SettingsJsonPath, $pretty, [System.Text.Encoding]::UTF8)
Write-Output "- Backed up original to $backup"
Write-Output "- Added Cmder profiles into property '$propName' in $SettingsJsonPath"
Write-Output "`nApplied changes to '$SettingsJsonPath'..."
} else {
Write-Output "`nAll VS Code terminal profiles are already configured in '$SettingsJsonPath'. No changes were made."
}
}

View File

@@ -1,3 +0,0 @@
@echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~n0.ps1" %*

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
powershell -NoProfile -ExecutionPolicy Bypass -File "$SCRIPT_DIR/${0%.*}.ps1" "$@"