Skip to content

Automate release tagging and make index builds resilient - #191

Merged
Shengyu Fu (shengyfu) merged 48 commits into
mainfrom
shengyfu-managed-shared-index-lifecycle
Oct 11, 2026
Merged

Shengyu Fu (shengyfu) merged 48 commits into
mainfrom
shengyfu-managed-shared-index-lifecycle

Conversation

@shengyfu

@shengyfu Shengyu Fu (shengyfu) commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Add Actions > Release > Run workflow on main with a required tag input. Validate the tag against the captured commit's workspace version, create it without force, and build/publish that exact commit in the same workflow. Preserve tag-push releases, matching lightweight/annotated-tag retries, per-tag concurrency, and publication-time revalidation. Peel captured annotated-tag object IDs to commits rather than resolving mutable tag names. Checkouts use trusted github.sha; downloaded archives remain separate from checked-out source when generating checksums.
  • Make ordinary index and serve share serve.lock. Under that lock, recover journaled interrupted publications before cleaning recognized stale spill and staging artifacts. Preserve published files, unrelated entries, legacy unjournaled backups, and managed shared storage. Invalid/ambiguous journals, incomplete scratch enumeration, and linked/unremovable/invalid fixed staging entries stop startup before writers can reuse them. Spill cleanup can warn and defer because spill writers allocate fresh names. Windows-mapped files are not force-unlinked.
  • Check destination free space before extraction and staged writes, with checked estimates for source bytes, output sizes, per-path overhead, and headroom. Do not invalidate an existing index when admission fails. Mark destination/spill I/O errors, including JSON output failures, so a cold build does not retry in heap when storage is unusable. Preserve native causes and managed commitment/retry state rather than classifying unrelated input failures as storage errors. Keep cold-start skeleton creation minimal so a rejected background build can expose its error through status and leave clients able to scan.
  • Run initial, resumed, fallback, reload, and stale-delta builds in dedicated --max-cpu indexing pools. Do not change RAYON_NUM_THREADS or resize the global search pool. Pool-creation failures are surfaced explicitly.
  • Save first-build progress through the existing external sorter and streaming publication path: after the first bounded extraction batch, approximately every 30 seconds between subsequent batches, and at completion. Resume persisted reader paths, reconcile edits/deletions/ignore changes before indexed queries, and recover process termination during publication. Read evidence alone cannot hide text missing from the reader.
  • Keep rollback armed until publication commits. If rollback itself fails, preserve its journal and latch recovery-required state under the publication lock: later publishers, reloads, autosaves/checkpoints, filename-only saves, and bootstrap resets cannot overwrite unresolved recovery state. Status and reload diagnostics require a restart; existing in-memory readers remain available. Startup recovery completes before publication is admitted again.
  • Harden owned-child cleanup and test clients. On Darwin, a zombie-only group can return EPERM; reap the owned child and require kernel-confirmed group disappearance within three seconds rather than ignoring permission errors. Persistent errors remain fatal. macOS descendant assertions use native process status, not absent procfs. Managed owner fixtures retry only explicitly retryable, uncommitted catalog contention, using the same claim and a ten-second deadline; a real SQLite writer-lock handshake covers that behavior.

The separate Azure DevOps Windows signing pipeline is unchanged. No release tag or public release has been created by this PR.

Operational limits

--max-cpu is a worker-count budget, not an OS CPU quota. External builds retain the 64 MiB posting buffer; --max-memory controls only the exceptional in-memory fallback. That fallback is prohibited after checkpoint publication is attempted or for destination, spill, and disk-space failures. Existing checkpoint progress is never discarded to enter it.

Checkpointing streams prior postings into replacements, adding disk I/O without materializing all postings in heap. The walk, one extraction batch, checkpoint publication, or final reconciliation can exceed the checkpoint interval. --no-watch retains full catch-up reads. Recovery covers process termination, not storage loss or power-failure durability. Free-space checks are estimates, not reservations or worst-case guarantees. No large-repository performance claim is made.

Validation

Final head 39e5d9ec3a68eca19a43411a5254b0a05f982bcd (tree 4757bb045ede898863549d49b9468a2fd2f02c57) passed the Windows/Linux/macOS CI matrix, including all three native managed lifecycle measurement jobs, and all four CodeQL analyses. The bounded CI measurements are not quiet-host or large-repository performance evidence. Copilot's review of this exact head reports 0 open findings, with no unresolved inline threads. It still recommends final human review; automated results do not replace the required approval.

The full local core and affected CLI qualification below was executed at production-changing commit 477120018e77bae2c958bcfac8f51f69f368ff15 (tree 4da07c882a5a885b159871a07bbee79661365d6d), before the test-only follow-up:

Suite Windows Native Linux
Core unit/integration tests 528 passed 540 passed
CLI unit tests 319 passed / 2 ignored 340 passed / 2 ignored
Indexed containment 5 passed 6 passed
ripgrep compatibility 243 passed 243 passed
Shared-daemon integration 64 passed / 4 ignored 69 passed / 4 ignored
Warm-start integration 2 passed 2 passed
Standalone Python scripts 44 passed / 3 Unix-only skips 46 passed / 1 Windows-only skip

Ignored Rust entries are supervised subprocess helpers or the opt-in quiet-host measurement, not additional standalone passes. Counts exclude nested child-run summaries and focused reruns. The original tgrep 1.1.0 CLI and reader controls were used for compatibility checks and their hashes remained unchanged. Owned validation processes were cleaned up; the native source snapshot still matched all 208 archived files after qualification.

  • cargo test --locked -p tgrep-core --features managed-test-hooks -- --test-threads=2
  • cargo test --locked -p tgrep-cli --features managed-test-hooks --bin tgrep --test indexed_containment --test warm_start_gitignore --test ripgrep_compat --test shared_daemon -- --test-threads=2
  • cargo fmt --all -- --check
  • cargo clippy --locked --workspace --all-targets --features tgrep-cli/managed-test-hooks -- -D warnings
  • python -B -m unittest discover -s scripts -p 'test_*.py' -v

All five command families passed on both platforms (python3 on Linux). Earlier full workspace qualification at 32fea82 passed 1,288 tests on Windows and 1,330 on native Linux, with six ignored entries per platform. Those earlier counts are not attributed to either later source.

The test-only follow-up 39e5d9e corrects the simulated-restart fixture after an Ubuntu CI writer-lock failure. It disables a nonexistent watcher so catch-up finishes synchronously, retains a duplicate writer handle as a deterministic control, proves that a live writer still excludes another writer, and explicitly unlocks only after fixture work is quiescent. All three rollback/restart tests failed with the duplicate-handle control before this correction. This commit changes only the test module; production logic remains that of 4771200.

At 39e5d9e, all CLI unit tests were rerun locally: 319 passed / 2 ignored on Windows, and 340 passed / 2 ignored on native Linux. Formatting and strict CLI/test Clippy also passed on both platforms, and all 208 native archived source files still matched. The full core/shared/compatibility suites were not rerun locally on this test-only follow-up; the final exact-head CI linked above supplies the full native matrix.

  • cargo test --locked -p tgrep-cli --features managed-test-hooks --bin tgrep -- --test-threads=2
  • cargo fmt --all -- --check
  • cargo clippy --locked -p tgrep-cli --features managed-test-hooks --bin tgrep --tests -- -D warnings

Coverage includes an owned server terminated after a 1,024-file checkpoint and restarted to serve real indexed RPC results; scan fallback while incomplete; indexing/search pool isolation; failed-checkpoint resume; missing reader entries despite existing evidence; empty/short/binary-only inputs; recovery at each file-move boundary; malformed/ambiguous journals; failed-commit rollback; low-space/probe failures; mapped-file cleanup retry; and real CLI writer commands refusing linked staging without touching external sentinel files.

Failed-rollback regressions exercise move, reader-validation, and commit failures through both publication paths, then reject all subsequent publishers, preserve the old reader/journal, and recover through restart. Successful rollback still permits reload. These regressions reproduced unsafe later publication before the fix. The owner-claim fixture also rejects nonretryable, committed, unknown-commit, unrelated-lock, and expired retry cases.

Storage-error regressions cover real spill-directory/segment creation and spill-read failures; every core output filename with both sort strategies; native write failures and JSON-wrapped I/O; unchanged managed error envelopes and non-I/O failures; destination versus input-path provenance; and cold-server failure/recovery before its first checkpoint. Three core regressions and the cold-server regression failed before the fix, with the latter actually entering the heap fallback; all now pass on both platforms.

All 17 real-Git release-helper cases pass on both platforms. They cover raw annotated-tag object SHAs in shallow/no-tags checkouts for preparation and publication verification, exact snapshot matching, invalid object inputs, retries, conflicting/deleted tags, and read/push failures. Annotated-tag and linked-staging regressions also failed before their fixes. Deterministic teardown tests cover transient Darwin permission errors, confirmed disappearance, persistent denial, and unchanged non-Darwin error handling; the actual macOS teardown tests passed in the final exact-head CI. These are bounded regression fixtures, not large-repository benchmarks. The unchanged workflow previously passed actionlint 1.7.12; public tag creation and release publication are deliberately not exercised before merge.

Shengyu Fu (shengyfu) and others added 30 commits October 8, 2026 06:58
Add isolated managed storage, guarded reader and owner lifetimes, atomic explicit and adaptive advancement, reference-aware resumable collection, allocations, and versioned live/offline management. Preserve ordinary and retain-all v1 behavior, document the generic client contract, and add native lifecycle qualification.

Co-authored-by: Copilot App <[email protected]>
Restore authoritative full publications after committed failures, retain adaptive decisions across deferral, and checkpoint WAL before mutations. Correct idle-stop authorization and native ownership portability. Exercise live recovery and record checked measurement cleanup and UTC windows.

Co-authored-by: Copilot App <[email protected]>
Use a bounded metadata-root list and choose the shortest matching relative path. Exercise both root orders against a real linked-worktree view, including HEAD, index, configuration, lock and unrelated-event controls.

Co-authored-by: Copilot App <[email protected]>
Use the documented sys/proc_info.h ABI value because the pinned libc crate exposes proc_listpids without PROC_PGRP_ONLY. Keep the bounded, positively identified zombie-only inventory check unchanged.

Co-authored-by: Copilot App <[email protected]>
Serialize headroom admission with SQLite writer acquisition, account for FULL-sync padding and future sidecars, and bound spill-disabled pager payloads. Preserve durable usage and reject unsafe policy reductions before mutation. Cover actual held-reader CLI service and owner-reaper contention.

Co-authored-by: Copilot App <[email protected]>
Use the smallest immutable upstream SQLite correction for canonical Windows paths, cover native read-lock release and real PSOW padding, and serialize metadata execution before deciding whether a receipt is terminal.

Co-authored-by: Copilot App <[email protected]>
Record bounded rendezvous timeouts inside the callback and assert only after restoring the VFS hook. Exercise the sticky timeout path without native callbacks.

Co-authored-by: Copilot App <[email protected]>
Exercise the normally installed release binary through owner lifetime, generation reuse, private views, shared-v2 scan parity, exact migration replay and explicit release. Reuse version-aware backend labels for filename search stats.

Co-authored-by: Copilot App <[email protected]>
Require supported nonzero content evidence for an unmapped owned fixture, invalidate timestamp-restored writes, and reject reusable evidence while a writable mapping survives its creator descriptor. This native proof does not assert a deletion exclusion fence.

Co-authored-by: Copilot App <[email protected]>
Add authentication format discrimination, bounded immutable block proof batches, creation-handle ownership snapshots, exact post-commit proof replay, and conservative producer recovery. Charge authentication scratch memory and catalog storage; compact proof rows in bounded units. This is an intermediate producer slice; native authenticated collection remains separate unfinished work.

Co-authored-by: Copilot App <[email protected]>
Retain native continuity observations, authenticate surviving prefixes and deletion intents, preserve ownership changes, and account for volatile verifier resources.

Co-authored-by: Copilot App <[email protected]>
…rors

Use the Linux F_SETOWN_EX UAPI with its thread-owner struct, and retain cross-platform final-boundary ownership regressions without losing durable intent state.

Co-authored-by: Copilot App <[email protected]>
Record the descriptor-backed absent FILESEC_ACL state separately from bounded ACL encodings and add native absence, ACL-change, and restoration controls.

Co-authored-by: Copilot App <[email protected]>
Centralize bounded unreserved admission with memory-first locking and verify the lock order through a deterministic nonhanging fault boundary.

Co-authored-by: Copilot App <[email protected]>
Retain the cross-platform inventory regression and exercise policy/allocation restarts, expiration, cancellation, and active-versus-idle shutdown resources.

Co-authored-by: Copilot App <[email protected]>
…r guards

Invalidate all version-stale proof without conflicting with retained inventory descriptors. Observe cancellation before destructive I/O and atomically in the final saved result.

Co-authored-by: Copilot App <[email protected]>
Keep missing guards unknown without matching retirement evidence, avoid duplicate control credits, and place the control-removal barrier after confirmed Windows handle release.

Co-authored-by: Copilot App <[email protected]>
Fence matching control opens without blocking unrelated owner admission. Separate root withdrawal from physical cleanup, serialize protected-reader admission with retirement, and retain accepted idle tokens across admission contention. Preserve deterministic same-control, unrelated-owner and same-token regressions.

Co-authored-by: Copilot App <[email protected]>
Reread the authoritative receipt after maintenance admission and hold serialization through error publication. Add a deterministic accepted-receipt interleaving that previously replaced a non-stopping decision with a committed stop.

Co-authored-by: Copilot App <[email protected]>
Revalidate terminal recovery state under maintenance serialization before lifetime checks and execution. Retain the exact pending collection object when another bounded control verifier owns admission, exposing the Busy skip without losing continuation or recrediting removed members. Add deterministic completed/failed/cancelled replay and physical-cleanup continuation controls.

Co-authored-by: Copilot App <[email protected]>
…naries

Scope known-operation pause and error hooks before asynchronous admission becomes visible. Preserve causal reconciliation, crash, recovery, native and legacy controls, and capture the exact Cargo-selected measurement CLI and harness as qualification artifacts.

Co-authored-by: Copilot App <[email protected]>
Preserve the pinned SQLite graph and managed backend labels while merging the upstream pattern resolution, smart-case, boundary and multiline fixes. Exercise the actual managed-v2 backend against scanning for both engines, retaining the empty-pattern-set early exit.

Co-authored-by: Copilot App <[email protected]>
Preserve failed-token replay and exact recovered pins before fresh-token attempts. Exercise post-lease SQLite Busy injection, unchanged lease resumption, and bounded exhaustion without changing shipping retry or serialization policy.

Co-authored-by: Copilot App <[email protected]>
Preserve ready readers and exact checkpoints when queued background work has already been fulfilled. Keep forced repairs, cancellation and version checks, immutable replay, and the periodic verification clock intact.

Co-authored-by: Copilot App <[email protected]>
Keep new attempts limited to authoritative uncommitted catalog contention, preserve absent or pending initial intent and immutable receipts, and continue from the actual consumed sequence. Cover pre-lease transaction failure, persisted-lease resumption, bounded exhaustion, and actual dropped-response replay without altering shipping retry behavior.

Co-authored-by: Copilot App <[email protected]>
Read one byte past the claim limit before deserializing so a valid JSON prefix cannot hide oversized whitespace or trailing data. Cover the boundary and preserved owner lifecycle through real CLI clients.

Co-authored-by: Copilot App <[email protected]>

Copilot AI 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.

🟡 Changes recommended

Empty-index creation can prevent the server from starting under low disk space, and substantial runtime changes are absent from the PR description.

2 open findings

🧠 Review effort: Balanced

Comment thread tgrep-cli/src/serve.rs Resolved
Comment thread tgrep-core/src/builder.rs Resolved
Reuse bounded external sorting for partial checkpoints and recover interrupted publications before startup cleanup. Keep search parallelism independent, preserve low-space status and scan fallback, and cover restart recovery with owned subprocess tests.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 11, 2026 04:33
@shengyfu Shengyu Fu (shengyfu) changed the title Automate release tagging and safeguard index builds Automate release tagging and make index builds resilient Oct 11, 2026

Copilot AI 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.

🟡 Changes recommended

Annotated tag-push releases compare the tag-object SHA against its peeled commit and are incorrectly rejected.

1 open finding
2 resolved since last review

🧠 Review effort: Balanced

Comment thread scripts/prepare_release.py Resolved
Resolve full captured Git object IDs to commits without consulting mutable tag refs. Cover raw annotated-tag SHAs in shallow checkouts, both preparation and publish verification, mismatched snapshots, and invalid object inputs.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 11, 2026 04:56

Copilot AI 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.

🟡 Changes recommended

Failed cleanup can leave linked staging paths that subsequent writers follow outside the index directory.

1 open finding
1 resolved since last review

🧠 Review effort: Balanced

Comment thread tgrep-cli/src/serve/index_cleanup.rs Resolved
Shengyu Fu (shengyfu) and others added 2 commits October 10, 2026 22:28
Fail preparation on linked, unremovable, or invalid fixed staging entries and on incomplete scratch enumeration. Keep spill cleanup best-effort because spill names are freshly allocated, and cover both real CLI writer commands and mapped-file retry.

Co-authored-by: Copilot App <[email protected]>
Handle transient zombie-only group EPERM by reaping the owned child and polling with signal zero for ESRCH under a three-second deadline. Persistent permission errors remain fatal. Add deterministic error-path tests and native macOS descendant-state checks instead of relying on missing procfs.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 11, 2026 05:28

Copilot AI 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.

🟡 Changes recommended

Storage errors can still trigger heap fallback, and rollback-failed journals can corrupt or block later recovery.

1 open finding
1 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Treat destination I/O failures as non-fallback errors

tgrep-cli/​src/​serve.rs:7043

A destination write failure can occur in chunk.finish before the callback sets checkpoint_attempted. Since is_build_disk_error only recognizes preflight errors and StorageFull, errors such as PermissionDenied, ReadOnlyFilesystem, or WriteZero fall through here, reset the index, and enter the in-heap fallback—the storage-error behavior this change is intended to prevent. Treat returned I/O failures as non-fallback failures as well.

🧠 Review effort: Balanced

Comment thread tgrep-cli/src/serve.rs Resolved
Shengyu Fu (shengyfu) and others added 2 commits October 10, 2026 23:07
Latch recovery-required state under the publication lock, reject every later publisher and reload, and expose restart diagnostics. Exercise move, validation, and commit failures with preserved readers and journal recovery.

Co-authored-by: Copilot App <[email protected]>
Retry only bounded, explicitly uncommitted catalog-busy owner claims without replacing the claim. Cover a real SQLite writer lock and nonretryable, committed, unknown, and expired outcomes.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 11, 2026 06:08

Copilot AI 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.

🟡 Changes recommended

Destination write failures can still trigger the memory-intensive fallback despite publication being unable to succeed.

1 open finding
1 resolved since last review

🧠 Review effort: Balanced

Comment thread tgrep-core/src/builder.rs Resolved
Mark destination and spill I/O at ordinary builder boundaries, including JSON writes and delta builds, while preserving native causes and managed commitment/retry states. Keep storage failures out of the cold-start heap fallback and verify recovery after the obstruction is removed.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 11, 2026 06:55

Copilot AI 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.

🔵 Needs a closer look

It combines release publication with cross-platform crash recovery and index lifecycle changes requiring final human validation.

0 open findings

1 resolved since last review

🧠 Review effort: Balanced

Run the fixture without a nonexistent watcher so reload finishes its catch-up synchronously. Retain a duplicate lock handle to model a fork-inherited file description, assert active writer exclusion, and explicitly unlock before the simulated restart instead of assuming that dropping one descriptor releases it.

Co-authored-by: Copilot App <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 11, 2026 07:07

Copilot AI 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.

🔵 Needs a closer look

It combines release publication with cross-platform storage recovery and concurrency changes that warrant final human review.

0 open findings

🧠 Review effort: Balanced

@shengyfu
Shengyu Fu (shengyfu) merged commit 5555248 into main Oct 11, 2026
15 checks passed
@shengyfu
Shengyu Fu (shengyfu) deleted the shengyfu-managed-shared-index-lifecycle branch October 11, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants