coolify/tests/Unit/GitLsRemoteParsingTest.php
Andras Bacsai bf00405971 fix(git): handle Git redirects and improve URL parsing for tangled.sh and other Git hosts
Fixes deployment failures when Git repositories redirect (e.g., tangled.sh → tangled.org)
and improves security by adding proper shell escaping for repository URLs.

**Root Cause:**
Git redirect warnings can appear on the same line as ls-remote output with no newline:
`warning: redirecting to https://tangled.org/...196d3df...	refs/heads/master`

The previous parsing logic split by newlines and extracted text before tabs, which
included the entire warning message instead of just the 40-character commit SHA.

**Changes:**

1. **Fixed commit SHA extraction** (ApplicationDeploymentJob.php):
   - Changed from line-based parsing to regex pattern matching
   - Uses `/([0-9a-f]{40})\s*\t/` to find valid 40-char hex commit SHA before tab
   - Handles warnings on same line, separate lines, multiple warnings, and whitespace
   - Added comprehensive Ray debug logs for troubleshooting

2. **Added security fix** (Application.php):
   - Added `escapeshellarg()` for repository URLs in 'other' deployment type
   - Prevents shell injection and fixes parsing issues with special characters like `@`
   - Added Ray debug logs for deployment type tracking

3. **Comprehensive test coverage** (GitLsRemoteParsingTest.php):
   - Tests normal output without warnings
   - Tests redirect warning on separate line
   - Tests redirect warning on same line (actual tangled.sh format)
   - Tests multiple warning lines
   - Tests extra whitespace handling

**Resolves:**
- Linear issue COOLGH-53: Valid git URLs are rejected as being invalid
- GitHub issue #6568: tangled.sh deployments failing
- Handles Git redirects universally for all Git hosting services

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 11:55:17 +02:00

49 lines
2 KiB
PHP

<?php
uses(\Tests\TestCase::class);
it('extracts commit SHA from git ls-remote output without warnings', function () {
$output = "196d3df7665359a8c8fa3329a6bcde0267e550bf\trefs/heads/master";
preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches);
$commit = $matches[1] ?? null;
expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf');
});
it('extracts commit SHA from git ls-remote output with redirect warning on separate line', function () {
$output = "warning: redirecting to https://tangled.org/@tangled.org/core/\n196d3df7665359a8c8fa3329a6bcde0267e550bf\trefs/heads/master";
preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches);
$commit = $matches[1] ?? null;
expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf');
});
it('extracts commit SHA from git ls-remote output with redirect warning on same line', function () {
// This is the actual format from tangled.sh - warning and result on same line, no newline
$output = "warning: redirecting to https://tangled.org/@tangled.org/core/196d3df7665359a8c8fa3329a6bcde0267e550bf\trefs/heads/master";
preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches);
$commit = $matches[1] ?? null;
expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf');
});
it('extracts commit SHA from git ls-remote output with multiple warning lines', function () {
$output = "warning: redirecting to https://example.org/repo/\ninfo: some other message\n196d3df7665359a8c8fa3329a6bcde0267e550bf\trefs/heads/main";
preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches);
$commit = $matches[1] ?? null;
expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf');
});
it('handles git ls-remote output with extra whitespace', function () {
$output = " 196d3df7665359a8c8fa3329a6bcde0267e550bf \trefs/heads/master";
preg_match('/([0-9a-f]{40})\s*\t/', $output, $matches);
$commit = $matches[1] ?? null;
expect($commit)->toBe('196d3df7665359a8c8fa3329a6bcde0267e550bf');
});