-
Notifications
You must be signed in to change notification settings - Fork 0
Codex-generated pull request #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Codex-generated pull request #129
Conversation
🚀 Preview DeploymentYour documentation preview is ready! Preview URL: https://pr-129.comapeo-docs.pages.dev 🔄 Content: Regenerated 5 pages from Notion (script changes detected)
This preview will update automatically when you push new commits to this PR. Built with commit c98437d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6d4039f6f9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex @greptile review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
6 files reviewed, 1 comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
comapeo-docs/scripts/api-server/job-executor.ts
Lines 294 to 297 in 34ad416
| // Register the process so it can be killed on cancellation | |
| jobTracker.registerProcess(jobId, { | |
| kill: () => childProcess?.kill("SIGTERM"), | |
| }); |
For content-mutating jobs, process cancellation is only wired once runJobProcess registers the child process, but that runner is invoked inside runContentTask after lock wait/fetch/reset work; if a user cancels during that pre-spawn window (for example while queued behind another mutating job), cancelJob marks the job failed yet execution can still continue and eventually push content changes. This makes cancellation non-authoritative and can produce commits after an explicit cancel request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7 files reviewed, 1 comment
The lock acquisition must happen AFTER directory creation to avoid 30-minute timeout when dirname(WORKDIR) doesn't exist. This regression was introduced when serialization logic was added in commit 13ab1e7. The acquireRepoLock() call would fail with ENOENT and retry as if it were lock contention, rather than immediately failing or succeeding. Fixes the order to: 1. initializeContentRepo() - creates dirname(workdir) with mkdir -p 2. acquireRepoLock() - creates lock file in now-existing directory
3dae2c4 to
75b9cf3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7 files reviewed, 4 comments
Replace boolean `initialized` flag with promise-based lock to prevent concurrent initialization race conditions in git config operations. - Use `initPromise` to ensure single initialization across concurrent calls - Reset promise on failure to allow retry after transient errors - Addresses code review feedback on lines 203-259 Reviewed-by: OpenAI Codex
* fix(api-server): address pr review race and path issues * fix(ci): align docker publish workflow with validation and tests * fix(ci): use version tags for docker publish actions * fix(api-server): address pr 133 review regressions * fix(ci-validation): restore docker action pinning policy checks * fix(content-repo): reintroduce safe init singleton * fix(ci): disable docker push when registry secrets are unavailable * test(ci): cover docker publish secret-gating behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
12 files reviewed, 1 comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
13 files reviewed, 3 comments
…po locking (#135) * test(api-server): add focused content-repo lock and init race coverage * docs(api-server): document content-repo envs for docker runtime * feat(test-docker): add docker-compose fetch-all smoke script
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
🧹 Preview Deployment CleanupThe preview deployment for this PR has been cleaned up. Preview URL was: Note: Cloudflare Pages deployments follow automatic retention policies. Old previews are cleaned up automatically. |
* fix(notion-fetch): isolate per-page failures in batch processing * fix(api-server): defer content repo init and relax health readiness * fix(api-server): serialize init and honor pre-spawn cancellation * fix(content-repo): initialize repo before acquiring lock The lock acquisition must happen AFTER directory creation to avoid 30-minute timeout when dirname(WORKDIR) doesn't exist. This regression was introduced when serialization logic was added in commit 13ab1e7. The acquireRepoLock() call would fail with ENOENT and retry as if it were lock contention, rather than immediately failing or succeeding. Fixes the order to: 1. initializeContentRepo() - creates dirname(workdir) with mkdir -p 2. acquireRepoLock() - creates lock file in now-existing directory * fix(content-repo): prevent initialization race condition Replace boolean `initialized` flag with promise-based lock to prevent concurrent initialization race conditions in git config operations. - Use `initPromise` to ensure single initialization across concurrent calls - Reset promise on failure to allow retry after transient errors - Addresses code review feedback on lines 203-259 Reviewed-by: OpenAI Codex * Codex-generated pull request (#133) * fix(api-server): address pr review race and path issues * fix(ci): align docker publish workflow with validation and tests * fix(ci): use version tags for docker publish actions * fix(api-server): address pr 133 review regressions * fix(ci-validation): restore docker action pinning policy checks * fix(content-repo): reintroduce safe init singleton * fix(ci): disable docker push when registry secrets are unavailable * test(ci): cover docker publish secret-gating behavior * doc: review findings * fix(api-server): harden content repo lock and script path handling (#134) * test(api-server): complete PR 129 reliability coverage for content repo locking (#135) * test(api-server): add focused content-repo lock and init race coverage * docs(api-server): document content-repo envs for docker runtime * feat(test-docker): add docker-compose fetch-all smoke script
Codex generated this pull request, but encountered an unexpected error after generation. This is a placeholder PR message.
Codex Task
Greptile Overview
Greptile Summary
This PR implements content repository management infrastructure for the API server, enabling content-mutating jobs (
notion:fetch,notion:fetch-all,notion:translate) to commit and push changes to a dedicated git branch.Key Changes
content-repo.tsmodule: Implements git repository lifecycle management with lock-based serialization, cancellation support, and secure credential handling viaGIT_ASKPASSEEXIST(retry) from other filesystem errors (fail fast), honorsshouldAbortcallback during lock wait to enable prompt cancellationPROJECT_ROOTconstantcontent-repo.test.tsvalidates lock retry, error handling, cancellation, and concurrent initialization scenarioscommunityfirst/comapeo-docs-apiimage name, adds publish mode logic for graceful credential handling.env.examplegenerateBlocks.tsnow catches page processing errors to prevent batch failuresReview Notes
The implementation addresses the P1 and P2 issues documented in
PR_129_REVIEW_FINDINGS.md:EEXIST, fails fast on other errorsshouldAbortcallbackPROJECT_ROOTinstead of runtimeprocess.cwd()The code quality is strong with proper separation of concerns, comprehensive error handling, and good test coverage.
Confidence Score: 4/5
Important Files Changed
Sequence Diagram
sequenceDiagram participant Client participant JobExecutor participant ContentRepo participant LockMgr as Lock Manager participant Git participant Remote as GitHub Remote Client->>JobExecutor: executeJob(notion:fetch) JobExecutor->>JobExecutor: isContentMutatingJob() → true JobExecutor->>ContentRepo: runContentTask(taskName, requestId, taskRunner, {shouldAbort}) ContentRepo->>LockMgr: acquireRepoLock(lockPath, shouldAbort) loop Lock Acquisition LockMgr->>LockMgr: assertNotAborted(shouldAbort) LockMgr->>LockMgr: open(lockPath, "wx") alt Lock Available LockMgr-->>ContentRepo: {release: fn} else EEXIST (Lock Held) LockMgr->>LockMgr: sleep(200ms) else Other Error LockMgr-->>ContentRepo: throw ContentRepoError end end ContentRepo->>ContentRepo: initializeContentRepo() ContentRepo->>Git: config user.name/email ContentRepo->>Git: remote set-url origin ContentRepo->>ContentRepo: assertNotAborted() ContentRepo->>Git: fetch origin content ContentRepo->>Git: checkout -B content origin/content ContentRepo->>Git: reset --hard origin/content ContentRepo->>Git: clean -fd ContentRepo->>ContentRepo: assertNotAborted() ContentRepo->>JobExecutor: taskRunner(workdir) JobExecutor->>JobExecutor: spawn(bun, script, {cwd: workdir}) JobExecutor-->>ContentRepo: output ContentRepo->>ContentRepo: assertNotAborted() ContentRepo->>Git: status --porcelain alt Changes Detected ContentRepo->>Git: add -A ContentRepo->>Git: commit -m "content-bot: ..." ContentRepo->>ContentRepo: assertNotAborted() ContentRepo->>Git: push origin content ContentRepo->>Git: rev-parse HEAD Git-->>ContentRepo: commitSha ContentRepo-->>JobExecutor: {output, noOp: false, commitSha} else No Changes ContentRepo-->>JobExecutor: {output, noOp: true} end ContentRepo->>LockMgr: lock.release() LockMgr->>LockMgr: close(lockFile) LockMgr->>LockMgr: rm(lockPath) JobExecutor-->>Client: Job completed