Skip to content

Add Phase 2 remote bundle jobs (server + client) - #129

Merged
livrasand merged 7 commits into
mainfrom
Add-Phase-2-remote-bundle-jobs-(server-+-client)
Aug 1, 2026
Merged

Add Phase 2 remote bundle jobs (server + client)#129
livrasand merged 7 commits into
mainfrom
Add-Phase-2-remote-bundle-jobs-(server-+-client)

Conversation

@livrasand

@livrasand livrasand commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Introduce Phase 2 remote-job flow: server-side bundling and Openbin upload, plus client support to use those bundles with byte-range resume.

Key changes:

  • internal/git: Add CreateBundle to clone by layers, complete history and produce a .bundle file.
  • internal/http: Add v2 /jobs endpoints and worker (presign PUT to Openbin, confirm) to create/store bundles (jobs2.go) and register routes (router.go).
  • internal/jobs: Add client-side bundle clone flow (runCloneBundle, download with Range, sha256 verification, materialize repo), fallback to layered clone if server lacks /v2/jobs; include tests for resume/hash behavior (clone_bundle.go, clone_bundle_test.go).
  • web/index.html: adjust layout / right sidebar and sponsor block.

This enables creating bundles server-side, serving them via CDN (Openbin/Filebase), and robust client downloads with resume and integrity checks.

Summary by CodeRabbit

  • New Features
    • Added remote repository download jobs with creation, status tracking, and cancellation.
    • Downloads support resumable transfers, integrity verification, retries, and automatic fallback when remote bundling is unavailable.
    • Completed repositories preserve their history and original remote configuration.
    • Added request protection with rate limits, size limits, and optional API-key authentication.
  • Bug Fixes
    • Improved handling and reporting of repository download and upload failures.
  • Style
    • Simplified the page layout by removing the sidebar panels and related informational content.

Introduce Phase 2 remote-job flow: server-side bundling and Openbin upload, plus client support to use those bundles with byte-range resume.

Key changes:
- internal/git: Add CreateBundle to clone by layers, complete history and produce a .bundle file.
- internal/http: Add v2 /jobs endpoints and worker (presign PUT to Openbin, confirm) to create/store bundles (jobs2.go) and register routes (router.go).
- internal/jobs: Add client-side bundle clone flow (runCloneBundle, download with Range, sha256 verification, materialize repo), fallback to layered clone if server lacks /v2/jobs; include tests for resume/hash behavior (clone_bundle.go, clone_bundle_test.go).
- web/index.html: adjust layout / right sidebar and sponsor block.

This enables creating bundles server-side, serving them via CDN (Openbin/Filebase), and robust client downloads with resume and integrity checks.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@livrasand, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 75f531e3-ede7-4204-bf30-8b78d4caed97

📥 Commits

Reviewing files that changed from the base of the PR and between faf6117 and 2348d88.

📒 Files selected for processing (19)
  • internal/cli/cli.go
  • internal/cli/proc_unix.go
  • internal/cli/proc_windows.go
  • internal/cli/rewrite.go
  • internal/cli/rewrite_test.go
  • internal/git/bundle.go
  • internal/git/git_test.go
  • internal/git/push.go
  • internal/git/receive.go
  • internal/git/rewrite.go
  • internal/git/squash.go
  • internal/github/github_test.go
  • internal/github/ntfy.go
  • internal/github/pr.go
  • internal/http/appeal.go
  • internal/http/e2e_test.go
  • internal/http/ethicalmetrics.go
  • internal/http/handlers.go
  • internal/http/handlers_upload_test.go
📝 Walkthrough

Walkthrough

Adds remote Git bundle jobs with protected API routes, Openbin uploads, resumable client downloads, checksum validation, and layered-clone fallback. It also removes obsolete sidebar metrics and sponsor markup and sponsor width overrides.

Changes

Remote bundle jobs

Layer / File(s) Summary
Git bundle creation
internal/git/bundle.go
CreateBundle validates HTTPS repository URLs, deepens shallow mirror clones, resolves the default branch, and creates complete all-ref bundles.
Remote job API and upload workflow
internal/http/jobs2.go, internal/http/router.go
The API validates requests, manages bounded jobs, creates bundles, uploads them to Openbin, and exposes protected /v2 endpoints with rate limiting.
Bundle download and repository materialization
internal/jobs/clone_bundle.go, internal/jobs/clone_bundle_test.go
The client polls remote jobs, resumes cached range downloads, verifies SHA-256 hashes, retries corrupted downloads, and materializes repositories. Tests cover full cloning, range requests, and hash retries.
Clone fallback and URL-safe layered fetches
internal/jobs/clone.go
runClone selects bundle cloning and uses layered cloning only when remote jobs are unsupported. Layered Git commands place URLs after --.

Web sidebar cleanup

Layer / File(s) Summary
Sidebar markup and sizing cleanup
web/index.html
The page removes sponsor width overrides and deletes the former sidebar sponsor, pageview, and metrics markup.

Estimated code review effort: 5 (Critical) | ~90+ minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client as runCloneBundle
  participant API as Remote job API
  participant Openbin
  participant Repository as Local repository
  Client->>API: Create and poll bundle job
  API->>Openbin: Upload generated bundle
  Openbin-->>API: Return bundle metadata
  API-->>Client: Return ready job and checksum
  Client->>Openbin: Resume bundle download
  Client->>Repository: Materialize bundle and set origin
Loading

Possibly related PRs

  • livrasand/gitGost#126: Both changes modify internal/jobs/clone.go and extend layered cloning with bundle-based cloning and fallback behavior.

Suggested labels: enhancement

Suggested reviewers: gitgost-anonymous

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding Phase 2 remote bundle jobs for both the server and client.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch Add-Phase-2-remote-bundle-jobs-(server-+-client)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread internal/git/bundle.go Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🧹 Nitpick comments (4)
internal/git/bundle.go (1)

103-114: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Do not parse CombinedOutput as a git value.

gitOutput merges stderr into stdout. revCount calls strconv.Atoi on that text, and Line 52 uses it as the default branch name. Any git warning on stderr (for example a hint or a redirect notice) then produces a wrong commit count or a wrong branch name. Capture stdout and stderr separately.

♻️ Proposed refactor
 func gitOutput(dir string, args ...string) (string, error) {
 	cmd := exec.Command("git", args...)
 	cmd.Dir = dir
-	out, err := cmd.CombinedOutput()
-	if err != nil {
-		if msg := strings.TrimSpace(string(out)); msg != "" {
-			return string(out), fmt.Errorf("%w: %s", err, msg)
-		}
-	}
-	return string(out), err
+	var stderr bytes.Buffer
+	cmd.Stderr = &stderr
+	out, err := cmd.Output()
+	if err != nil {
+		if msg := strings.TrimSpace(stderr.String()); msg != "" {
+			return string(out), fmt.Errorf("%w: %s", err, msg)
+		}
+	}
+	return string(out), err
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/git/bundle.go` around lines 103 - 114, Update gitOutput to capture
stdout and stderr separately instead of using CombinedOutput, preserving stdout
as the returned git value while incorporating stderr into errors only when the
command fails. Ensure callers such as revCount and the default-branch lookup
receive clean stdout without warnings or notices.
internal/http/jobs2.go (1)

159-177: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Reuse the computed size and hash instead of recomputing them.

runRemoteJob computes size and hash on Lines 159-168. openbinUpload computes both again on Lines 197-204, which reads the whole bundle a second time. Lines 176-177 then overwrite the values that openbinUpload already set. Pass the size and hash into openbinUpload.

♻️ Proposed refactor
-func openbinUpload(bundlePath, filename string) (*remoteJobResult, error) {
+func openbinUpload(bundlePath, filename, hash string, size int64) (*remoteJobResult, error) {
@@
-	hash, err := sha256File(bundlePath)
-	if err != nil {
-		return nil, fmt.Errorf("calcular sha256 del bundle: %w", err)
-	}
-	size, err := fileSize(bundlePath)
-	if err != nil {
-		return nil, fmt.Errorf("tamaño del bundle: %w", err)
-	}
-	result, err := openbinUpload(bundlePath, bundleFilename(job.URL))
+	result, err := openbinUpload(bundlePath, bundleFilename(job.URL), hash, size)
 	if err != nil {
 		publish(rjFailed, "", err.Error(), nil)
 		return
 	}
-	result.Size = size
-	result.Sha256 = hash
 	result.DefaultBranch = defaultBranch

Also applies to: 197-204

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/http/jobs2.go` around lines 159 - 177, Update runRemoteJob and
openbinUpload to pass the already computed size and hash into openbinUpload,
removing its duplicate file-size and SHA-256 calculations and the redundant
result assignments in runRemoteJob. Preserve the existing upload behavior and
error handling while ensuring the returned result uses the supplied values.
internal/jobs/clone_bundle_test.go (1)

30-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Return a guarded accessor instead of *[]string.

The handler appends to ranges under mu, but Lines 202-207 read the slice through the returned pointer without the lock. Under go test -race a late or retried request can trip the detector. Return a snapshot function that takes the same lock.

♻️ Proposed refactor
-func fakeBundleServer(t *testing.T, bundlePath string) (*httptest.Server, *[]string) {
+func fakeBundleServer(t *testing.T, bundlePath string) (*httptest.Server, func() []string) {
@@
 	t.Cleanup(srv.Close)
-	return srv, &ranges
+	return srv, func() []string {
+		mu.Lock()
+		defer mu.Unlock()
+		return append([]string(nil), ranges...)
+	}
 }

Also applies to: 66-66, 202-208

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/jobs/clone_bundle_test.go` around lines 30 - 32, Update the test
helper around the shared ranges variable to return a snapshot accessor rather
than a pointer to the slice. Have the accessor lock mu, copy the current ranges
contents, unlock, and return the snapshot; update all callers, including the
checks near lines 66 and 202-208, to use the accessor so every read is
synchronized.
internal/jobs/clone_bundle.go (1)

49-58: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Align the origin URL and the default branch with the layered path.

Two contract gaps exist here:

  1. runCloneLayered prefers job.Origin and falls back to the effective URL. materializeClone always uses the reconstructed https URL. A user who cloned with an scp-like URL gets a different origin depending on which path ran.
  2. The server publishes defaultBranch in remoteJobResult (internal/http/jobs2.go Line 52), but remoteJobBundleInfo has no matching field, so the value is dropped. git clone <bundle> then depends on the bundle carrying a usable HEAD. If it does not, the destination ends in a detached or unexpected branch.

Prefer job.Origin when it is set, and use the reported defaultBranch to check out the expected branch.

Also applies to: 356-370

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/jobs/clone_bundle.go` around lines 49 - 58, Update
remoteJobBundleInfo and the bundle materialization flow to preserve the server’s
defaultBranch value and check out that branch after cloning. Make
materializeClone use job.Origin when set, falling back to the effective
reconstructed URL, matching runCloneLayered’s origin behavior; retain the
existing fallback when Origin is empty.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/git/bundle.go`:
- Around line 19-23: Thread a context.Context from runRemoteJob through
CreateBundle into runGit and gitOutput, creating it with context.WithTimeout in
runRemoteJob and using exec.CommandContext for every git subprocess. Enforce a
maximum accepted bundle size before the upload step, rejecting oversized bundles
and preserving cleanup/error propagation.
- Around line 64-72: Update shallowFile to support both repository layouts:
check the bare-repository marker at <dir>/shallow and the non-bare marker at
<dir>/.git/shallow, returning the contents of whichever exists. Preserve the
existing empty-string result when neither marker can be read so the no-progress
guard remains effective for mirror clones.

In `@internal/http/jobs2.go`:
- Around line 92-96: The POST /v2/jobs endpoint allows unbounded job creation
and lacks request limiting. In internal/http/jobs2.go lines 92-96, gate
runRemoteJob using a worker semaphore and return HTTP 429 when no slot is
available; in internal/http/router.go lines 303-311, add sizeLimitMiddleware()
and the existing per-IP limiter such as prCheckLimiter() to the v2 route group.
- Around line 331-347: Update validRepoURL to accept only the https scheme and
reject URLs containing embedded userinfo credentials before returning true;
preserve the existing supported-host and repository-path validation.
- Around line 131-152: Update the remote-job worker’s publish closure to retain
and propagate the temporary directory through every status update, using the
closure’s directory state rather than the original job copy. In
DeleteRemoteJobHandler, mark the job as cancelled without removing TmpDir while
the worker is running, so the worker’s existing defer os.RemoveAll(dir) performs
cleanup after termination.
- Around line 305-329: Update openbinUpload and openbinPut to pass the existing
fileSize(bundlePath) result into openbinPut, set req.ContentLength to that size,
and avoid chunked transfer encoding. Only set Content-Type when the presigned
URL was signed with that header, preserving the existing upload and response
error handling.

In `@internal/jobs/clone_bundle_test.go`:
- Around line 46-60: Fix the fake server’s Range parsing in the /bundle GET
handler: remove the trailing “-” from the byte range before parsing, and fail
loudly when parsing the range header is invalid instead of ignoring the error.
Preserve the partial-content response and write only data starting at the parsed
offset so TestDownloadBundleResumes exercises the actual resume path.

In `@internal/jobs/clone_bundle.go`:
- Around line 209-246: Update downloadBundle so a cached file whose size equals
size but whose hash does not match is removed before downloadWithRetry runs.
Update downloadRange to treat a partial offset at or beyond size as a restart
from zero, avoiding an invalid range request and allowing the download to
recover automatically.
- Around line 160-189: Update waitRemoteJob to enforce an overall polling
deadline and track consecutive errors from getRemoteJob, resetting the error
count after a successful response. Continue polling through a small bounded
number of transient errors, then return the final error; also return a clear
timeout error when queued/running polling exceeds the deadline while preserving
the existing ready, failed, and progress-update behavior.
- Around line 101-112: After materializeClone succeeds in the clone flow, delete
the cached bundle at cacheFile before marking progress complete; handle any
deletion failure through the function’s existing error-return pattern, while
preserving the current download and materialization behavior.
- Around line 133-158: Update createRemoteJob and the corresponding remote job
status request to send the GITGOST_API_KEY value in the X-Gitgost-Key header and
use an HTTP client configured with a finite timeout instead of
http.Post/http.Get defaults. Treat HTTP 401 and 403 like 404 by returning
errRemoteJobsUnsupported, preserving existing response handling and fallback
behavior.

In `@web/index.html`:
- Around line 1683-1685: In the stats note’s text, replace the grammatically
incorrect phrase “Data are storage in Zurich.” with “Data are stored in Zurich.”
- Around line 1679-1681: Update the element identified by ethicalmetrics-chart
to include a nameable semantic role, such as role="img", alongside its existing
aria-label so accessibility APIs expose the chart’s accessible name.

---

Nitpick comments:
In `@internal/git/bundle.go`:
- Around line 103-114: Update gitOutput to capture stdout and stderr separately
instead of using CombinedOutput, preserving stdout as the returned git value
while incorporating stderr into errors only when the command fails. Ensure
callers such as revCount and the default-branch lookup receive clean stdout
without warnings or notices.

In `@internal/http/jobs2.go`:
- Around line 159-177: Update runRemoteJob and openbinUpload to pass the already
computed size and hash into openbinUpload, removing its duplicate file-size and
SHA-256 calculations and the redundant result assignments in runRemoteJob.
Preserve the existing upload behavior and error handling while ensuring the
returned result uses the supplied values.

In `@internal/jobs/clone_bundle_test.go`:
- Around line 30-32: Update the test helper around the shared ranges variable to
return a snapshot accessor rather than a pointer to the slice. Have the accessor
lock mu, copy the current ranges contents, unlock, and return the snapshot;
update all callers, including the checks near lines 66 and 202-208, to use the
accessor so every read is synchronized.

In `@internal/jobs/clone_bundle.go`:
- Around line 49-58: Update remoteJobBundleInfo and the bundle materialization
flow to preserve the server’s defaultBranch value and check out that branch
after cloning. Make materializeClone use job.Origin when set, falling back to
the effective reconstructed URL, matching runCloneLayered’s origin behavior;
retain the existing fallback when Origin is empty.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ff11380d-23f8-4210-a19f-92a08e1bb4df

📥 Commits

Reviewing files that changed from the base of the PR and between 8bbe0a7 and de295d5.

📒 Files selected for processing (7)
  • internal/git/bundle.go
  • internal/http/jobs2.go
  • internal/http/router.go
  • internal/jobs/clone.go
  • internal/jobs/clone_bundle.go
  • internal/jobs/clone_bundle_test.go
  • web/index.html

Comment thread internal/git/bundle.go Outdated
Comment thread internal/git/bundle.go Outdated
Comment thread internal/http/jobs2.go
Comment thread internal/http/jobs2.go
Comment thread internal/http/jobs2.go
Comment thread internal/jobs/clone_bundle.go
Comment thread internal/jobs/clone_bundle.go
Comment thread internal/jobs/clone_bundle.go
Comment thread web/index.html Outdated
Comment thread web/index.html Outdated
Add context/timeouts to git commands, prevent git args injection with '--', and improve git output handling. Introduce concurrency semaphore, per-job timeout, cancellation, and max bundle size checks for remote jobs. Add per-IP v2 rate limiter and size middleware in router. Improve Openbin upload to accept precomputed size/hash, set mime and Content-Length, and use a timed HTTP client with optional API key. Fix range-download edge cases, ensure default-branch checkout and origin handling, remove cached bundles after materialization, and update tests and minor web copy typo.
Comment thread internal/git/bundle.go Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/http/jobs2.go (1)

138-224: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Cancelling a job does not stop the running clone or upload.

runRemoteJob creates ctx with only a 30-minute timeout (Line 163-164); nothing ties it to job cancellation. jobCancelled(job.ID) is checked at Line 193 and Line 218, but both checks run only after the expensive step (git.CreateBundle, openbinUpload) has already completed. DeleteRemoteJobHandler (Line 141-150) only flips Status to rjCancelled — it never signals the running goroutine to stop.

As a result, DELETE /v2/jobs/:id does not free the worker's concurrency slot early, does not stop the mirror clone, and does not stop the Openbin upload. It only prevents publishing the final ready result. This defeats the purpose of exposing cancellation on a resource-bounded (3 concurrent workers) endpoint: a caller cannot actually abort a stuck or unwanted job to make room for another.

Store the job's context.CancelFunc where DeleteRemoteJobHandler can reach it (for example, a small map[string]context.CancelFunc guarded by a mutex, or a field alongside the job in remoteJobs), and call it from the delete handler. exec.CommandContext-backed git commands in bundle.go will then stop promptly.

🛡️ Proposed direction
+var (
+	remoteJobCancelsMu sync.Mutex
+	remoteJobCancels   = map[string]context.CancelFunc{}
+)
+
 func runRemoteJob(job *remoteJob) {
 	defer func() { <-remoteJobSlots }()

 	ctx, cancel := context.WithTimeout(context.Background(), remoteJobTimeout)
 	defer cancel()
+	remoteJobCancelsMu.Lock()
+	remoteJobCancels[job.ID] = cancel
+	remoteJobCancelsMu.Unlock()
+	defer func() {
+		remoteJobCancelsMu.Lock()
+		delete(remoteJobCancels, job.ID)
+		remoteJobCancelsMu.Unlock()
+	}()
 func DeleteRemoteJobHandler(c *gin.Context) {
 	id := c.Param("id")
 	if job, ok := remoteJobs.Get(id); ok && job.Status != rjCancelled {
 		next := *job
 		next.Status = rjCancelled
 		next.Progress = "Cancelado"
 		remoteJobs.Set(id, &next)
+		remoteJobCancelsMu.Lock()
+		if cancel, ok := remoteJobCancels[id]; ok {
+			cancel()
+		}
+		remoteJobCancelsMu.Unlock()
 	}
 	c.Status(http.StatusNoContent)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/http/jobs2.go` around lines 138 - 224, Connect job cancellation to
the running operation: store each runRemoteJob context.CancelFunc in a
concurrency-safe registry accessible by DeleteRemoteJobHandler, invoke and
remove it when the job is deleted, and clean it up when runRemoteJob exits. Keep
the existing status update and timeout behavior, while ensuring the context
passed to git.CreateBundle and the upload path is cancelled promptly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/git/bundle.go`:
- Around line 22-67: Update CreateBundle after the shallow-history completion
logic and before bundle create to explicitly fetch tags from origin using git
fetch --tags origin. Keep the existing history deepening and bundle creation
flow unchanged, ensuring tags for newly reached commits are included in the
generated bundle.

---

Outside diff comments:
In `@internal/http/jobs2.go`:
- Around line 138-224: Connect job cancellation to the running operation: store
each runRemoteJob context.CancelFunc in a concurrency-safe registry accessible
by DeleteRemoteJobHandler, invoke and remove it when the job is deleted, and
clean it up when runRemoteJob exits. Keep the existing status update and timeout
behavior, while ensuring the context passed to git.CreateBundle and the upload
path is cancelled promptly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 377c6614-9457-4967-9e3d-dae152bbe40c

📥 Commits

Reviewing files that changed from the base of the PR and between de295d5 and 6e52614.

📒 Files selected for processing (7)
  • internal/git/bundle.go
  • internal/http/jobs2.go
  • internal/http/router.go
  • internal/jobs/clone.go
  • internal/jobs/clone_bundle.go
  • internal/jobs/clone_bundle_test.go
  • web/index.html
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/jobs/clone.go
  • web/index.html
  • internal/jobs/clone_bundle.go

Comment thread internal/git/bundle.go
livrasand and others added 2 commits August 1, 2026 10:06
Add URL validation in internal/git to avoid git option injection and restrict clone hosts/paths; fetch tags after shallow mirror clones so tags are included in bundles. Add cancelation support for remote jobs: store per-job CancelFunc in a sync.Map, let DELETE cancel running workers, and avoid overwriting a "Canceled" state when context.Canceled occurs. Propagate context through openbinUpload/openbinPost/openbinPut so uploads can be canceled. Remove the right sidebar from web/index.html. Minor import additions (net/url, sync).
Replace the boolean validCloneURL with safeCloneURL which validates and returns a normalized URL string or an error. CreateBundle now calls safeCloneURL and passes the sanitized URL to git clone, ensuring the raw user input is never used as a command argument. Preserves the same hosts/path checks and rejection of credentials/non-HTTPS, and clarifies comments about import-cycle constraints. Improves error reporting when the repository URL is invalid.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Strip all Spanish-language inline comments from internal/cli (cli.go, proc_unix.go, proc_windows.go, rewrite.go, rewrite_test.go) and internal/git (bundle.go, push.go, receive.go). Replace safeCloneURL's url.Parse validation with a single regex pattern (repoURLPattern) that validates and captures allowed hosts (github.com, gitlab.com, codeberg.org), optional port, and exactly two path segments (owner/repo), then reconstructs the URL from matched groups to ensure user input
…ive URL safety tests

Extract git clone into dedicated gitClone function that validates URL at the exact point it becomes a git argument, preventing option injection across all call paths. Add explicit regex barrier in safeCloneURL with early MatchString check before FindStringSubmatch to satisfy static analysis. Remove Spanish comments from bundle.go, handlers.go. Add 16 test cases covering host validation, path traversal, option injection, userinfo/fragment rejection, port
Strip all Spanish-language inline comments from handlers.go (isPanicMode, isGlobalBurstAlertActive, recordGlobalBurst, notifyAdminGlobalBurst, checkRateLimit, notifyAdminRateLimit, PanicHandler, ServiceStatusHandler, RollbackBurstHandler, InitDatabase, RecordPR, StatsHandler, RecentPRsHandler, CreateAnonymousIssueHandler, GitLabIssueNotesProxyHandler, GitLabCommitCountHandler, GitLabAvatarHandler, GitLabCommitsHandler, GitLabCommitDetailHandler, GitHubDiscussionsProxyHandler, GitHubDiscussionDetailPro
@livrasand
livrasand merged commit 3e549c0 into main Aug 1, 2026
5 checks passed
@livrasand
livrasand deleted the Add-Phase-2-remote-bundle-jobs-(server-+-client) branch August 1, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants