Compare commits

..

51 Commits

Author SHA1 Message Date
dependabot[bot]
ddaa2f1c4e Bump softprops/action-gh-release from 2 to 3
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-13 17:07:56 +00:00
David Refoua
00a140dac9 Bump peter-evans/create-pull-request from 7 to 8 2026-04-12 05:18:44 +03:30
dependabot[bot]
75cd20b7ff Bump peter-evans/create-pull-request from 7 to 8
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7 to 8.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v7...v8)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-12 00:43:41 +00:00
David Refoua
dc7e1c144f Fix GitHub Actions step summary generation issues 2026-04-12 04:13:02 +03:30
copilot-swe-agent[bot]
55251f7cc3 Show actual branch name and separate PR row in repository information
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/7ac9b75c-de48-4c0b-98db-108cc3423c0e

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-12 00:29:30 +00:00
copilot-swe-agent[bot]
0983e9b763 Add duration tracking to test results and change hashes.txt separator to tab
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/48204621-5da0-4649-9715-ac9df45f1153

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-12 00:24:53 +00:00
copilot-swe-agent[bot]
cb59bb54b0 Fix variable name casing inconsistency in vendor.yml (Summary -> summary)
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/7c117654-3cc9-428c-846a-01931a2f9b5b

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-12 00:20:53 +00:00
David Refoua
c882ade42d fix multi-line EOF syntax according to GitHub
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-12 03:47:52 +03:30
David Refoua
dcbb0e9203 fix: Handle multi-line JSON
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-12 03:46:47 +03:30
David Refoua
f3fa589ac3 use double-quote for "`n"
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-12 03:45:54 +03:30
David Refoua
32cf8767f5 fix: Derive directories from the array entries
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-12 03:44:49 +03:30
David Refoua
03deb9d859 fix: handle links to vendor repo archive URL
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-12 03:43:54 +03:30
David Refoua
01d01c6a57 parse entire JSON string at once
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-12 03:42:33 +03:30
copilot-swe-agent[bot]
25ea725338 Fix Format-FileSize undefined error by sourcing utils.ps1 in artifacts upload step
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/bf167f7e-397b-4635-a7d2-2c2680207e67

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 22:33:42 +00:00
copilot-swe-agent[bot]
cbc7f53cd3 Add workflow_dispatch to enable manual build workflow runs
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/49b3cbe7-8c16-4e18-a4c4-e0587448245e

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 22:27:24 +00:00
copilot-swe-agent[bot]
31e73cce59 Fix vendor package release links and artifact download URLs
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/ff648493-d8fd-4117-9a78-2933758d2280

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 22:16:56 +00:00
copilot-swe-agent[bot]
2de93d1d55 Move Format-FileSize and Get-ArtifactDownloadUrl functions to utils.ps1
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/9334534b-9a07-4053-a214-f394e6e92aaa

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 21:41:27 +00:00
copilot-swe-agent[bot]
aa801c2c17 Make artifact names clickable, use human-readable file sizes, and add rar to compression formats
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/ce43a069-b966-4141-b4e1-3d201bc3ddbf

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 21:35:15 +00:00
copilot-swe-agent[bot]
1418da1c18 Dynamically discover all build artifacts instead of hardcoding filenames
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/8667c9a1-2ae6-4286-bcf4-f58735eb094e

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 21:30:51 +00:00
copilot-swe-agent[bot]
05b24c2173 Wrap buildTime in code formatting backticks while keeping small tag
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/915ff38b-d73d-4ed8-bc2d-1fd1efa26f9b

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 21:03:52 +00:00
copilot-swe-agent[bot]
f69c1db205 Remove separator before artifacts, add sources.json link, and link vendor versions to releases
Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/6ed72053-91c6-4e75-8317-ac54af872629

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 20:52:47 +00:00
David Refoua
165ca3b05b Merge pull request #3076 from cmderdev/master
Update with upstream
2026-04-12 00:12:11 +03:30
David Refoua
be3d66d8a3 Merge pull request #3075 from cmderdev/copilot/fix-double-zip-problem
fix: resolve double-zip problem with github artifact upload
2026-04-12 00:10:28 +03:30
David Refoua
35c1cd6f42 Revert GitHub Actions checkout action version to v6 (latest) 2026-04-12 00:04:19 +03:30
copilot-swe-agent[bot]
07a2c6e5cd fix: correct checkout to v4 and add archive: false to fix double-zip
- actions/checkout@v6 does not exist; correct to @v4
- Add archive: false to all actions/upload-artifact@v7 steps so .zip
  and .7z files are uploaded directly without being wrapped in an
  extra zip container (fixes the double-zip problem described in
  #2725 and #2805)

Agent-Logs-Url: https://github.com/cmderdev/cmder/sessions/1d806690-a6f7-49d1-bef5-cefe50fc371e

Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2026-04-11 20:17:05 +00:00
David Refoua
7cfa69fe74 Merge pull request #3069 from cmderdev/dependabot/github_actions/actions/upload-artifact-7
Bump actions/upload-artifact from 6 to 7
2026-04-11 23:37:07 +03:30
David Refoua
74b089662c Merge pull request #3070 from cmderdev/dependabot/github_actions/microsoft/setup-msbuild-3
Bump microsoft/setup-msbuild from 2 to 3
2026-04-11 23:35:34 +03:30
dependabot[bot]
ed5ebfe5ba Bump microsoft/setup-msbuild from 2 to 3
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 2 to 3.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v2...v3)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-23 16:19:05 +00:00
dependabot[bot]
86d1cbcfa0 Bump actions/upload-artifact from 6 to 7
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 17:43:22 +00:00
Dax T Games
adbd6322f6 Merge branch 'master' into copilot/fix-github-step-summary 2026-02-28 08:06:34 -05:00
Dax T. Games
0c6b2d9900 Add back comments 2026-02-22 13:45:47 -05:00
Dax T. Games
66ab9ad6f7 remove nodejs files 2026-02-22 18:11:34 -05:00
Dax T. Games
6137073ba3 fix path to sources.json 2026-02-22 17:58:59 -05:00
Dax T. Games
6858619614 x 2026-02-22 17:56:27 -05:00
Dax T Games
002282636a Merge branch 'master' into copilot/fix-github-step-summary 2026-02-22 12:36:55 -05:00
Dax T. Games
48cc28a634 Fix yaml errors 2026-02-22 17:27:45 -05:00
Dax T. Games
e71c7679f6 Fixes and Cleanup 2026-02-22 16:22:17 -05:00
copilot-swe-agent[bot]
dc93fa5d1b Add real artifact download URLs with retry logic and fallback to run page
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-25 05:40:39 +00:00
copilot-swe-agent[bot]
684185ca8a Fix vendor workflow Unicode escape error by converting echo to PowerShell here-strings
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-25 05:37:09 +00:00
David Refoua
2780a43323 Update .github/workflows/tests.yml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-15 06:33:39 +03:30
David Refoua
641ce7b1e8 Update .github/workflows/build.yml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-15 06:23:04 +03:30
David Refoua
a52b0b9e10 Update .github/workflows/tests.yml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-15 06:20:35 +03:30
copilot-swe-agent[bot]
825df3aace Fix branch link for PR merge refs to point to PR instead of invalid tree URL
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 02:48:18 +00:00
David Refoua
a937901e82 Change emoji for Vendor Packages section 2025-12-15 06:06:08 +03:30
copilot-swe-agent[bot]
27c7a0cdc6 Improve build summary: simplify message, reorder columns, add file type emojis
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 01:59:35 +00:00
copilot-swe-agent[bot]
838c1cfaa3 Add backticks to clickable links for code formatting in Repository Information
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 01:56:14 +00:00
copilot-swe-agent[bot]
bff3862ad4 Use 🗃️ emoji for Vendor Packages and Artifacts sections
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 01:41:42 +00:00
copilot-swe-agent[bot]
2057ee58b0 Fix incomplete summary by initializing $summary variable before appending
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-15 01:13:19 +00:00
copilot-swe-agent[bot]
0bc7fd3aaa Improve build workflow summary: add links, vendor packages, full hashes, and merge artifact sections
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-14 22:30:03 +00:00
copilot-swe-agent[bot]
1e04711a21 Change test emoji from 🧪 to in workflow summary
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-12-14 22:08:39 +00:00
copilot-swe-agent[bot]
3810b8d258 Initial plan 2025-12-14 21:42:23 +00:00
10 changed files with 483 additions and 505 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

@@ -12,6 +12,7 @@ on:
- "v*"
pull_request:
branches: [ "master", "development" ]
workflow_dispatch:
#---------------------------------#
# environment configuration #
@@ -42,20 +43,97 @@ 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
# Get Cmder version
. scripts/utils.ps1
$cmderVersion = Get-VersionStr
$buildTime = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
# Determine branch and PR information
$refName = "${{ github.ref_name }}"
$headRef = "${{ github.head_ref }}"
$eventName = "${{ github.event_name }}"
$prNumber = $null
$actualBranchName = $refName
$branchLink = ""
$prLink = ""
# Check if this is a PR merge ref (e.g., "3061/merge")
if ($refName -match '^(\d+)/(merge|head)$') {
$prNumber = $Matches[1]
# Use head_ref for the actual branch name if available
if ($headRef) {
$actualBranchName = $headRef
}
$branchLink = "https://github.com/${{ github.repository }}/tree/$actualBranchName"
$prLink = "https://github.com/${{ github.repository }}/pull/$prNumber"
} elseif ($eventName -eq "pull_request") {
# This is a pull request event
$prNumber = "${{ github.event.pull_request.number }}"
if ($headRef) {
$actualBranchName = $headRef
}
$branchLink = "https://github.com/${{ github.repository }}/tree/$actualBranchName"
$prLink = "https://github.com/${{ github.repository }}/pull/$prNumber"
} else {
# Regular branch, link to the branch tree
$branchLink = "https://github.com/${{ github.repository }}/tree/$refName"
}
$summary = @"
## 📦 Build Cmder - Workflow Summary
<small>Build started: ``$buildTime``</small>
### Repository Information
| Property | Value |
| --- | --- |
| Repository | [``${{ github.repository }}``](https://github.com/${{ github.repository }}) |
| Branch | [``$actualBranchName``]($branchLink) |
$(if ($prNumber) { "| Pull Request | [#$prNumber]($prLink) |" })
| 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** |
---
### 🗃️ Vendor Packages ([sources.json](vendor/sources.json))
| Package | Version |
| --- | --- |
"@
# Read vendor sources.json and add to summary
$vendorSources = Get-Content -Raw "vendor/sources.json" | ConvertFrom-Json
if ($vendorSources.Count -eq 0) {
$summary += "`n| _No vendor packages found_ | |"
} else {
foreach ($vendor in $vendorSources) {
# Create release link based on vendor package
$versionLink = "$($vendor.version)"
if ($vendor.url) {
# Extract owner/repo/tag from the URL and create release link
# Handle both /releases/download/ and /archive/ URLs
if ($vendor.url -match 'github\.com/([^/]+)/([^/]+)/(releases/download|archive)/([^/]+)') {
$owner = $Matches[1]
$repo = $Matches[2]
$pathType = $Matches[3]
$tag = $Matches[4]
if ($pathType -eq 'archive') {
$tag = $tag -replace '\.(?:tar\.gz|tgz|zip)$', ''
}
$versionLink = "[$($vendor.version)](https://github.com/$owner/$repo/releases/tag/$tag)"
}
}
$summary += "`n| ``$($vendor.name)`` | $versionLink |"
}
}
$summary += "`n"
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2
uses: microsoft/setup-msbuild@v3
- name: Build Cmder Launcher
shell: pwsh
@@ -66,76 +144,105 @@ 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 = @"
---
✅ Cmder built successfully.
"@
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Pack the built files
shell: pwsh
working-directory: scripts
run: .\pack.ps1 -verbose
- name: Summary - Package artifacts
if: success()
shell: pwsh
run: |
echo "### 📦 Artifacts Created" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "| Artifact | Size | Hash (SHA256) |" >> $env:GITHUB_STEP_SUMMARY
echo "| --- | --- | --- |" >> $env:GITHUB_STEP_SUMMARY
$artifacts = @("cmder.zip", "cmder.7z", "cmder_mini.zip")
foreach ($artifact in $artifacts) {
$path = "build/$artifact"
if (Test-Path $path) {
$size = (Get-Item $path).Length / 1MB
# Truncate hash to first 16 chars for summary readability (full hash in hashes.txt)
$hash = (Get-FileHash $path -Algorithm SHA256).Hash.Substring(0, 16)
echo "| \`$artifact\` | $([math]::Round($size, 2)) MB | \`$hash...\` |" >> $env:GITHUB_STEP_SUMMARY
}
}
echo "" >> $env:GITHUB_STEP_SUMMARY
- name: Upload artifact (cmder.zip)
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
path: build/cmder.zip
name: cmder.zip
archive: false
if-no-files-found: error
- name: Upload artifact (cmder.7z)
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
path: build/cmder.7z
name: cmder.7z
archive: false
- name: Upload artifact (cmder_mini.zip)
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
path: build/cmder_mini.zip
name: cmder_mini.zip
archive: false
- name: Upload artifact (hashes.txt)
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
path: build/hashes.txt
name: hashes.txt
archive: false
- name: Summary - Artifacts uploaded
if: success()
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
echo "### ☁️ Upload Status" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "All artifacts successfully uploaded to GitHub Actions:" >> $env:GITHUB_STEP_SUMMARY
echo '- ✅ `cmder.zip`' >> $env:GITHUB_STEP_SUMMARY
echo '- ✅ `cmder.7z`' >> $env:GITHUB_STEP_SUMMARY
echo '- ✅ `cmder_mini.zip`' >> $env:GITHUB_STEP_SUMMARY
echo '- ✅ `hashes.txt`' >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
# Source utility functions
. scripts/utils.ps1
$summary = @"
### 🗃️ Artifacts
| Artifact | Size | Hash (SHA256) |
| --- | --- | --- |
"@
# Get all files from the build directory (excluding directories and hidden files)
if (Test-Path "build") {
$buildFiles = Get-ChildItem -Path "build" -File | Where-Object { -not $_.Name.StartsWith('.') } | Sort-Object Name
foreach ($file in $buildFiles) {
$artifact = $file.Name
$path = $file.FullName
$sizeFormatted = Format-FileSize -Bytes $file.Length
$hash = (Get-FileHash $path -Algorithm SHA256).Hash
# Try to get the actual artifact download URL
$downloadUrl = Get-ArtifactDownloadUrl -ArtifactName $artifact -Repository "${{ github.repository }}" -RunId "${{ github.run_id }}"
$warning = ""
if (-not $downloadUrl) {
# Fallback to workflow run page if artifact URL fetch fails
$downloadUrl = "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
$warning = " ⚠️"
}
# Determine emoji based on file type
if ($artifact -match '\.txt$') {
$emoji = "📄"
} elseif ($artifact -match '\.(zip|rar|7z)$') {
$emoji = "🗄️"
} else {
$emoji = "📦"
}
$summary += "`n| $emoji [``$artifact``$warning]($downloadUrl) | $sizeFormatted | ``$hash`` |"
}
}
$summary += "`n"
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Create Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
with:
files: |
build/cmder.zip
@@ -150,14 +257,20 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
shell: pwsh
run: |
echo "### 🚀 Release Information" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "Draft release created for tag: **\`${{ github.ref_name }}\`**" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "Release includes:" >> $env:GITHUB_STEP_SUMMARY
echo "- Full version (\`cmder.zip\`, \`cmder.7z\`)" >> $env:GITHUB_STEP_SUMMARY
echo "- Mini version (\`cmder_mini.zip\`)" >> $env:GITHUB_STEP_SUMMARY
echo "- File hashes (\`hashes.txt\`)" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "> ⚠️ Release is in **draft** mode. Please review and publish manually." >> $env:GITHUB_STEP_SUMMARY
$summary = @"
---
### Release Information
🚀 Draft release created for tag: **``${{ github.ref_name }}``**
Release includes:
- Full version (``cmder.zip``, ``cmder.7z``)
- Mini version (``cmder_mini.zip``)
- File hashes (``hashes.txt``)
> ⚠️ Release is in **draft** mode. Please review and publish manually.
"@
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8

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
@@ -78,7 +79,7 @@ jobs:
# queries: security-extended,security-and-quality
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2
uses: microsoft/setup-msbuild@v3
- name: Build Cmder Launcher
shell: pwsh
@@ -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,20 +39,33 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Summary - Test execution started
shell: pwsh
run: |
echo "## 🧪 Run Tests - Workflow Summary" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "### Test Environment" >> $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 "| Runner OS | \`${{ runner.os }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
# Get Cmder version
. scripts/utils.ps1
$cmderVersion = Get-VersionStr
$summary = @"
## ✅ Run Tests - Workflow Summary
### Test Environment
| Property | Value |
| --- | --- |
| Repository | ``${{ github.repository }}`` |
| Branch | ``${{ github.ref_name }}`` |
| Commit | ``${{ github.sha }}`` |
| Runner OS | ``${{ runner.os }}`` |
| Cmder Version | **$cmderVersion** |
| PowerShell Version | **$($PSVersionTable.PSVersion)** |
| Event | ``${{ github.event_name }}`` |
"@
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Initialize vendors
shell: pwsh
@@ -63,53 +76,127 @@ jobs:
if: success()
shell: pwsh
run: |
echo "### ⚙️ Vendor Initialization" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "✅ Vendor dependencies initialized successfully." >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
# Get vendor versions from sources.json
$vendorInfo = @()
$sources = Get-Content "vendor\sources.json" -Raw | ConvertFrom-Json
foreach ($source in $sources) {
$dir = $source.name
if (-not $dir) {
continue
}
$versionFile = "vendor/$dir/.cmderver"
if (Test-Path $versionFile) {
$version = Get-Content $versionFile -Raw
$vendorInfo += "- **$dir**: $($version.Trim())"
}
}
$summary = @"
### ⚙️ Vendor Initialization
✅ Vendor dependencies initialized successfully.
**Vendor Versions:**
"@
$(
if ($vendorInfo.Count -eq 0) {
$summary += "_No vendor version information available._"
} else {
$summary += $vendorInfo -join "`n"
}
)
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Summary - Test results table header
if: success()
shell: pwsh
run: |
echo "### 📋 Test Results" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "| Test | Status |" >> $env:GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $env:GITHUB_STEP_SUMMARY
$summary = @"
### 📋 Test Results
| Test | Status | Duration |
| --- | --- | --- |
"@
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Testing Clink Shell
id: test-clink
shell: pwsh
run: |
$startTime = Get-Date
cmd /c vendor\init.bat /v /d /t
$duration = [math]::Round(((Get-Date) - $startTime).TotalSeconds, 2)
echo "duration=$duration" >> $env:GITHUB_OUTPUT
- name: Summary - Clink Shell test
if: success()
shell: pwsh
run: |
echo "| Clink Shell | ✅ Passed |" >> $env:GITHUB_STEP_SUMMARY
$duration = "${{ steps.test-clink.outputs.duration }}"
if ($duration) {
$duration = "$duration s"
} else {
$duration = "N/A"
}
"| Clink Shell | ✅ Passed | $duration |" | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Testing PowerShell
id: test-powershell
shell: pwsh
run: |
$startTime = Get-Date
PowerShell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -Command "$env:CMDER_DEBUG='1'; . 'vendor\profile.ps1'"
$duration = [math]::Round(((Get-Date) - $startTime).TotalSeconds, 2)
echo "duration=$duration" >> $env:GITHUB_OUTPUT
- name: Summary - PowerShell test
if: success()
shell: pwsh
run: |
echo "| PowerShell | ✅ Passed |" >> $env:GITHUB_STEP_SUMMARY
$duration = "${{ steps.test-powershell.outputs.duration }}"
if ($duration) {
$duration = "$duration s"
} else {
$duration = "N/A"
}
"| PowerShell | ✅ Passed | $duration |" | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Testing Bash
id: test-bash
shell: pwsh
run: |
$startTime = Get-Date
bash vendor/cmder.sh
$duration = [math]::Round(((Get-Date) - $startTime).TotalSeconds, 2)
echo "duration=$duration" >> $env:GITHUB_OUTPUT
- name: Summary - Bash test
if: success()
shell: pwsh
run: |
echo "| Bash | ✅ Passed |" >> $env:GITHUB_STEP_SUMMARY
$duration = "${{ steps.test-bash.outputs.duration }}"
if ($duration) {
$duration = "$duration s"
} else {
$duration = "N/A"
}
"| Bash | ✅ Passed | $duration |" | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- name: Summary - All tests completed
if: success()
shell: pwsh
run: |
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "### ✅ All Tests Completed" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "All shell environments tested successfully!" >> $env:GITHUB_STEP_SUMMARY
$summary = @"
### ✅ All Tests Completed
All shell environments tested successfully!
**Test Coverage:**
- ✅ Clink shell environment (Windows cmd.exe with Clink)
- ✅ PowerShell environment (with Cmder profile)
- ✅ Bash environment (Git Bash integration)
"@
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8

View File

@@ -31,61 +31,63 @@ jobs:
- name: Summary - Workflow started
shell: pwsh
run: |
$summary = @(
'## 📦 Update Vendor - Workflow Summary'
''
'Checking for vendor dependency updates...'
''
)
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY
$summary = @"
## 📦 Update Vendor - Workflow Summary
Checking for vendor dependency updates...
"@
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- id: make-changes
name: Checking for updates
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
$currentVersion = (Get-Content .\vendor\sources.json | ConvertFrom-Json)
. .\scripts\update.ps1 -verbose
Set-GHVariable -Name COUNT_UPDATED -Value $count
$newVersion = (Get-Content .\vendor\sources.json | ConvertFrom-Json)
$listUpdated = ""
$updateMessage = "| Name | Old Version | New Version |`n| :--- | ---- | ---- |`n"
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"
$listUpdated += "$($s.name) v$($s.version), "
$updateMessage += "| **[$($s.name)]($repoUrl)** | $oldVersion | **$($s.version)** |`n"
}
$currentVersion = (Get-Content -Raw .\vendor\sources.json | ConvertFrom-Json)
. .\scripts\update.ps1 -verbose
Set-GHVariable -Name COUNT_UPDATED -Value $count
$newVersion = (Get-Content -Raw .\vendor\sources.json | ConvertFrom-Json)
$listUpdated = ""
$updateMessage = "| Name | Old Version | New Version |`n| :--- | ---- | ---- |`n"
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"
$listUpdated += "$($s.name) v$($s.version), "
$updateMessage += "| **[$($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
}
if ($count -eq 0) { return }
Set-GHVariable -Name LIST_UPDATED -Value $listUpdated.Trim(', ')
echo "UPDATE_MESSAGE<<EOF`n$updateMessage`nEOF" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
- 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.'
)
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY
$summary = @"
### ✅ No Updates Available
All vendor dependencies are up to date.
"@
} else {
$word = if ($count -eq 1) { 'dependency' } else { 'dependencies' }
$summary = @(
'### 🔄 Updates Found'
''
"**$count** vendor $word updated:"
''
$env:UPDATE_MESSAGE
''
)
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY
$summary = @"
### 🔄 Updates Found
**$count** vendor $word updated:
$env:UPDATE_MESSAGE
"@
}
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8
- uses: peter-evans/create-pull-request@v8
if: env.COUNT_UPDATED > 0
with:
@@ -103,15 +105,16 @@ jobs:
if: env.COUNT_UPDATED > 0
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
$summary = @"
### 🎉 Pull Request Created
A pull request has been created to update the vendor dependencies.
**Branch:** ``update-vendor``
**Updated dependencies:** $env:LIST_UPDATED
> Please review and merge the pull request to apply the updates.
"@
$summary | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8

View File

@@ -70,7 +70,7 @@ if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
foreach ($t in $targets.GetEnumerator()) {
Create-Archive "$cmderRoot" "$saveTo\$($t.Name)" $t.Value
$hash = (Digest-Hash "$saveTo\$($t.Name)")
Add-Content -path "$saveTo\hashes.txt" -value ($t.Name + ' ' + $hash)
Add-Content -path "$saveTo\hashes.txt" -value ($t.Name + "`t" + $hash)
}
Pop-Location

View File

@@ -249,3 +249,107 @@ function Download-File {
$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;
$wc.DownloadFile($Url, $File)
}
function Format-FileSize {
<#
.SYNOPSIS
Formats a file size in bytes to a human-readable string using binary units.
.DESCRIPTION
Converts file sizes to appropriate binary units (B, KiB, MiB, GiB) for better readability.
.PARAMETER Bytes
The file size in bytes to format.
.EXAMPLE
Format-FileSize -Bytes 1024
Returns "1.00 KiB"
.EXAMPLE
Format-FileSize -Bytes 15728640
Returns "15.00 MiB"
#>
param(
[Parameter(Mandatory = $true)]
[double]$Bytes
)
if ($Bytes -ge 1GB) {
return "{0:N2} GiB" -f ($Bytes / 1GB)
} elseif ($Bytes -ge 1MB) {
return "{0:N2} MiB" -f ($Bytes / 1MB)
} elseif ($Bytes -ge 1KB) {
return "{0:N2} KiB" -f ($Bytes / 1KB)
} else {
return "{0:N0} B" -f $Bytes
}
}
function Get-ArtifactDownloadUrl {
<#
.SYNOPSIS
Retrieves the download URL for a GitHub Actions artifact with retry logic.
.DESCRIPTION
Uses the GitHub CLI to fetch artifact information from the GitHub API with automatic retries.
Falls back to returning $null if all attempts fail.
.PARAMETER ArtifactName
The name of the artifact to retrieve the download URL for.
.PARAMETER Repository
The GitHub repository in the format "owner/repo".
.PARAMETER RunId
The GitHub Actions workflow run ID.
.PARAMETER MaxRetries
Maximum number of retry attempts. Default is 3.
.PARAMETER DelaySeconds
Delay in seconds between retry attempts. Default is 2.
.EXAMPLE
Get-ArtifactDownloadUrl -ArtifactName "cmder.zip" -Repository "cmderdev/cmder" -RunId "123456789"
.EXAMPLE
Get-ArtifactDownloadUrl -ArtifactName "build-output" -Repository "owner/repo" -RunId "987654321" -MaxRetries 5 -DelaySeconds 3
#>
param(
[Parameter(Mandatory = $true)]
[string]$ArtifactName,
[Parameter(Mandatory = $true)]
[string]$Repository,
[Parameter(Mandatory = $true)]
[string]$RunId,
[int]$MaxRetries = 3,
[int]$DelaySeconds = 2
)
for ($i = 0; $i -lt $MaxRetries; $i++) {
try {
# Use GitHub CLI to get artifact information
$artifactsJson = gh api "repos/$Repository/actions/runs/$RunId/artifacts" --jq ".artifacts[] | select(.name == `"$ArtifactName`")"
if ($artifactsJson) {
$artifact = $artifactsJson | ConvertFrom-Json
if ($artifact.id) {
# Construct browser-accessible GitHub Actions artifact download URL
# Format: https://github.com/owner/repo/actions/runs/{run_id}/artifacts/{artifact_id}
return "https://github.com/$Repository/actions/runs/$RunId/artifacts/$($artifact.id)"
}
}
} catch {
Write-Host "Attempt $($i + 1) failed to get artifact URL for $ArtifactName : $_"
}
if ($i -lt ($MaxRetries - 1)) {
Start-Sleep -Seconds $DelaySeconds
}
}
return $null
}

View File

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

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