From 8b9e852fd6771754ea4ce1b7b40cf8ceb6f82e59 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sat, 30 May 2026 10:37:39 -0500 Subject: [PATCH] fix(cli): cross-platform cd command for Windows/Linux compatibility Use cd /d on Windows, cd on Linux for shell_exec directory changes. Also resolve path early with realpath() for Windows native paths. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- cli/release_publish.php | 33 ++++++++++++++++++--------------- cli/version_auto_bump.php | 16 ++++++++-------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/cli/release_publish.php b/cli/release_publish.php index 7b6b19c..9975323 100644 --- a/cli/release_publish.php +++ b/cli/release_publish.php @@ -69,9 +69,12 @@ $cli = __DIR__; $php = '"' . PHP_BINARY . '"'; $giteaUrl = rtrim($giteaUrl, '/'); +// Resolve path early for shell commands (Windows needs native paths) +$resolvedPath = realpath($path) ?: $path; + // Auto-detect org/repo from git remote if not set if (empty($org) || empty($repo)) { - $remote = trim((string) @shell_exec("cd " . escapeshellarg($path) . " && git remote get-url origin 2>/dev/null")); + $remote = trim((string) @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($resolvedPath) . " && git remote get-url origin 2>/dev/null")); if (preg_match('#/([^/]+)/([^/.]+?)(?:\.git)?$#', $remote, $m)) { if (empty($org)) $org = $m[1]; if (empty($repo)) $repo = $m[2]; @@ -86,7 +89,7 @@ if (empty($repoUrl) && !empty($token) && !empty($org) && !empty($repo)) { // Auto-detect branch if (empty($branch)) { - $branch = getenv('GITHUB_REF_NAME') ?: trim((string) @shell_exec("cd " . escapeshellarg($path) . " && git rev-parse --abbrev-ref HEAD 2>/dev/null")); + $branch = getenv('GITHUB_REF_NAME') ?: trim((string) @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($resolvedPath) . " && git rev-parse --abbrev-ref HEAD 2>/dev/null")); } $apiBase = "{$giteaUrl}/api/v1/repos/{$org}/{$repo}"; @@ -167,15 +170,15 @@ if (!$dryRun) { $root = realpath($path) ?: $path; if (!$dryRun) { // Configure git - @shell_exec("cd " . escapeshellarg($root) . " && git config --local user.email \"gitea-actions[bot]@mokoconsulting.tech\""); - @shell_exec("cd " . escapeshellarg($root) . " && git config --local user.name \"gitea-actions[bot]\""); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git config --local user.email \"gitea-actions[bot]@mokoconsulting.tech\""); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git config --local user.name \"gitea-actions[bot]\""); if (!empty($repoUrl)) { - @shell_exec("cd " . escapeshellarg($root) . " && git remote set-url origin " . escapeshellarg($repoUrl)); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git remote set-url origin " . escapeshellarg($repoUrl)); } // Ensure we're on the actual branch (not detached HEAD from PR merge) - @shell_exec("cd " . escapeshellarg($root) . " && git fetch origin " . escapeshellarg($branch) . " 2>/dev/null"); - @shell_exec("cd " . escapeshellarg($root) . " && git checkout -B " . escapeshellarg($branch) . " FETCH_HEAD 2>/dev/null"); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git fetch origin " . escapeshellarg($branch) . " 2>/dev/null"); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git checkout -B " . escapeshellarg($branch) . " FETCH_HEAD 2>/dev/null"); // Re-apply version changes on the checked-out branch passthru("{$php} {$cli}/version_set_platform.php --path " . escapeshellarg($path) @@ -185,12 +188,12 @@ if (!$dryRun) { passthru("{$php} {$cli}/version_check.php --path " . escapeshellarg($path) . " --fix 2>/dev/null"); passthru("{$php} {$cli}/badge_update.php --path " . escapeshellarg($path) . " --version " . escapeshellarg($baseVersion) . " 2>/dev/null"); - $diffCheck = trim((string) @shell_exec("cd " . escapeshellarg($root) . " && git diff --quiet && git diff --cached --quiet 2>&1 && echo clean || echo dirty")); + $diffCheck = trim((string) @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git diff --quiet && git diff --cached --quiet 2>&1 && echo clean || echo dirty")); if ($diffCheck === 'dirty') { - @shell_exec("cd " . escapeshellarg($root) . " && git add -A"); - @shell_exec("cd " . escapeshellarg($root) . " && git commit -m " . escapeshellarg("chore(release): build {$releaseVersion} [skip ci]") + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git add -A"); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git commit -m " . escapeshellarg("chore(release): build {$releaseVersion} [skip ci]") . " --author=\"gitea-actions[bot] \""); - $pushResult = @shell_exec("cd " . escapeshellarg($root) . " && git push origin " . escapeshellarg($branch) . " 2>&1"); + $pushResult = @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git push origin " . escapeshellarg($branch) . " 2>&1"); echo " Committed release changes\n"; echo " Push: " . trim($pushResult ?? '') . "\n"; } @@ -313,12 +316,12 @@ echo "\n--- Step 6: Commit and sync updates.xml ---\n"; $root = realpath($path) ?: $path; if (!$dryRun) { - $diffCheck = trim((string) @shell_exec("cd " . escapeshellarg($root) . " && git diff --quiet updates.xml 2>&1 && echo clean || echo dirty")); + $diffCheck = trim((string) @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git diff --quiet updates.xml 2>&1 && echo clean || echo dirty")); if ($diffCheck === 'dirty') { - @shell_exec("cd " . escapeshellarg($root) . " && git add updates.xml"); - @shell_exec("cd " . escapeshellarg($root) . " && git commit -m " . escapeshellarg("chore: update channels for {$releaseVersion} [skip ci]") + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git add updates.xml"); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git commit -m " . escapeshellarg("chore: update channels for {$releaseVersion} [skip ci]") . " --author=\"gitea-actions[bot] \""); - @shell_exec("cd " . escapeshellarg($root) . " && git push origin " . escapeshellarg($branch) . " 2>&1"); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git push origin " . escapeshellarg($branch) . " 2>&1"); echo " Committed updates.xml\n"; } diff --git a/cli/version_auto_bump.php b/cli/version_auto_bump.php index 3b3ff66..27760e1 100644 --- a/cli/version_auto_bump.php +++ b/cli/version_auto_bump.php @@ -81,7 +81,7 @@ $shouldBump = true; if (!empty($watchPath)) { $root = realpath($path) ?: $path; $diffOutput = trim((string) @shell_exec( - "cd " . escapeshellarg($root) . " && git diff --name-only HEAD~1 HEAD -- " . escapeshellarg($watchPath) . " 2>/dev/null" + (PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git diff --name-only HEAD~1 HEAD -- " . escapeshellarg($watchPath) . " 2>/dev/null" )); if (empty($diffOutput)) { echo "No changes in {$watchPath} — skipping version bump\n"; @@ -145,28 +145,28 @@ if ($dryRun) { $root = realpath($path) ?: $path; // Check if anything changed -$diffStatus = trim((string) @shell_exec("cd " . escapeshellarg($root) . " && git diff --quiet && git diff --cached --quiet 2>&1 && echo clean || echo dirty")); +$diffStatus = trim((string) @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git diff --quiet && git diff --cached --quiet 2>&1 && echo clean || echo dirty")); if ($diffStatus === 'clean') { echo "No version changes to commit\n"; exit(0); } // Configure git -@shell_exec("cd " . escapeshellarg($root) . " && git config --local user.email \"gitea-actions[bot]@mokoconsulting.tech\""); -@shell_exec("cd " . escapeshellarg($root) . " && git config --local user.name \"gitea-actions[bot]\""); +@shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git config --local user.email \"gitea-actions[bot]@mokoconsulting.tech\""); +@shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git config --local user.name \"gitea-actions[bot]\""); if (!empty($repoUrl)) { - @shell_exec("cd " . escapeshellarg($root) . " && git remote set-url origin " . escapeshellarg($repoUrl)); + @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git remote set-url origin " . escapeshellarg($repoUrl)); } -@shell_exec("cd " . escapeshellarg($root) . " && git add -A"); +@shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git add -A"); $commitMsg = $shouldBump ? "chore(version): auto-bump patch {$displayVersion} [skip ci]" : "chore(version): set {$stability} suffix {$displayVersion} [skip ci]"; -@shell_exec("cd " . escapeshellarg($root) . " && git commit -m " . escapeshellarg($commitMsg) +@shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git commit -m " . escapeshellarg($commitMsg) . " --author=\"gitea-actions[bot] \""); -$pushResult = @shell_exec("cd " . escapeshellarg($root) . " && git push origin " . escapeshellarg($branch) . " 2>&1"); +$pushResult = @shell_exec((PHP_OS_FAMILY === 'Windows' ? "cd /d " : "cd ") . escapeshellarg($root) . " && git push origin " . escapeshellarg($branch) . " 2>&1"); echo $pushResult ?? ''; echo "Bumped to {$displayVersion}\n";