Skip to content

feat(config): support remote preset resolution via git clone --depth 1#43

Merged
fohte merged 6 commits intomainfrom
fohte/impl-runok-init-remote-preset-v2
Feb 18, 2026
Merged

feat(config): support remote preset resolution via git clone --depth 1#43
fohte merged 6 commits intomainfrom
fohte/impl-runok-init-remote-preset-v2

Conversation

@fohte
Copy link
Owner

@fohte fohte commented Feb 17, 2026

Why

  • Allow sharing presets across repositories through the extends field

What

  • Support github:org/repo@version shorthand and generic HTTPS/SSH git URLs for remote preset resolution
  • Fetch presets via git clone --depth 1, delegating authentication to the machine's git configuration (lefthook approach)
  • Cache shallow clones at $XDG_CACHE_HOME/runok/presets/ with SHA256-keyed directories (24-hour TTL; commit SHA references are cached permanently)
  • Attempt git fetch to update stale caches, falling back to the old cache on failure
  • Warn on mutable references (branches, Latest) recommending commit SHA pinning for reproducibility
  • Sanitize GIT_DIR/GIT_INDEX_FILE environment variables for worktree compatibility
  • Abstract git operations behind a GitClient trait, enabling MockGitClient-based testing

Open with Devin

Local-only preset loading (extends field) could not resolve remote
references like `github:org/[email protected]` or generic git URLs. Teams
sharing presets across repositories had no way to reference them.

Add git clone --depth 1 based remote preset fetching with:
- `github:org/repo@version` shorthand parsing (SHA, tag, branch, latest)
- Generic git URL support (HTTPS and SSH, with optional @ref suffix)
- Cache at $XDG_CACHE_HOME/runok/presets/ with SHA256-keyed directories
- TTL-based cache (24h default, RUNOK_CACHE_TTL override, SHA permanent)
- Stale cache: git fetch update with fallback to old cache on error
- Mutable reference warnings recommending commit SHA pinning
- GIT_DIR/GIT_INDEX_FILE env sanitization for worktree compatibility
- GitClient trait abstraction with MockGitClient for testability
- Unified load_preset() dispatcher for local and remote references

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@gemini-code-assist
Copy link

Summary of Changes

Hello @fohte, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the configuration system by enabling the resolution of presets from remote Git repositories. It introduces a comprehensive caching layer to optimize performance and reliability for remote presets, supporting various reference types including GitHub shorthand and direct Git URLs. The underlying Git operations are carefully abstracted and environment variables are sanitized, ensuring both testability and broad compatibility.

Highlights

  • Remote Preset Resolution: Implemented support for loading configuration presets from remote Git repositories, allowing sharing across different projects.
  • Git Reference Parsing: Added parsing for GitHub shorthand (e.g., 'github:org/repo@version') and generic HTTPS/SSH Git URLs, including optional branch/tag/commit SHA references.
  • Caching Mechanism: Introduced a caching system for remote presets, storing shallow Git clones at '$XDG_CACHE_HOME/runok/presets/' with SHA256-keyed directories and a 24-hour TTL. Commit SHA references are cached permanently.
  • Git Operations Abstraction: Abstracted Git commands behind a GitClient trait, with ProcessGitClient for real execution and MockGitClient for robust testing.
  • Environment Sanitization: Sanitized GIT_DIR and GIT_INDEX_FILE environment variables during Git operations to ensure compatibility within Git worktree environments.
  • Mutable Reference Warnings: Added warnings for mutable references (branches, 'Latest') to encourage pinning to commit SHAs for improved reproducibility.
Changelog
  • Cargo.lock
    • Added new dependencies: block-buffer, cpufeatures, crypto-common, digest, generic-array, sha2, and typenum.
  • Cargo.toml
    • Added the 'sha2' crate as a new dependency.
  • src/config/cache.rs
    • Added a new module for managing the preset cache, including CacheMetadata structure, CacheStatus enum, and PresetCache logic for directory resolution, TTL, and metadata handling.
  • src/config/error.rs
    • Extended PresetError enum with GitClone and GitCloneWithCache variants to provide more specific error reporting for Git-related failures.
  • src/config/git_client.rs
    • Added a new module defining the GitClient trait for abstracting Git commands, along with ProcessGitClient for executing real Git commands and MockGitClient for testing purposes.
  • src/config/mod.rs
    • Exposed new modules cache, git_client, and preset_remote within the config module.
  • src/config/preset.rs
    • Updated load_local_preset to be part of the new preset loading flow. Introduced load_preset and load_preset_with functions to dispatch preset loading based on whether the reference is local or remote, integrating the new Git client and caching logic.
  • src/config/preset_remote.rs
    • Added a new module responsible for parsing remote preset references (PresetReference enum), resolving Git parameters, handling the caching logic (hit, stale, miss), and orchestrating Git clone, fetch, and checkout operations for remote presets.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

devin-ai-integration[bot]

This comment was marked as resolved.

gemini-code-assist[bot]

This comment was marked as resolved.

Devin review identified three issues:

1. `GitUrl` with commit SHA passed SHA as `--branch` to `git clone`,
   which fails because `--branch` only accepts branch/tag names.
   Now SHA detection is based on `params.git_ref` instead of only
   checking the `GitHub` variant, so both `github:` and git URL
   references handle SHA correctly.

2. Stale cache for `Latest` references ran `git fetch` but skipped
   `git checkout`, leaving the working tree at the old commit while
   updating metadata. Now always checks out `FETCH_HEAD` when no
   explicit git_ref is specified.

3. HTTPS URLs with userinfo `@` (e.g., `https://user@host/...`) were
   misparsed because `rfind('@')` matched the userinfo `@` instead of
   the ref separator. Now only searches for `@` in the URL path portion
   after the host.
devin-ai-integration[bot]

This comment was marked as resolved.

1. Add `--` separator to `git clone`, `git fetch`, and `git checkout`
   commands to prevent argument injection via crafted ref strings
   (e.g., `--upload-pack=...`).

2. Sanitize URLs in error messages to strip credentials from the
   authority component (`user:pass@host` → `***@host`).

3. Use `Self::git_command()` helper in `clone_shallow` to avoid
   duplicating env sanitization logic.

4. Remove unused fields from `GitCall` enum and the `#[expect(dead_code)]`
   annotation. Only `branch` and `git_ref` are used in test assertions.

5. Remove unused `_reference` and `_cache` parameters from
   `handle_cache_miss` and `handle_stale_cache`.

6. Replace `Vec::remove(0)` with `VecDeque::pop_front()` in
   `MockGitClient` for O(1) queue operations.
devin-ai-integration[bot]

This comment was marked as resolved.

1. Move git_ref before `--` in `git checkout` so it is interpreted as
   a tree-ish (branch/tag/commit), not a pathspec. `git checkout -- ref`
   tries to restore a file named "ref" from the index, which is wrong.

2. Extract inner message from PresetError::GitClone when re-wrapping
   clone/checkout errors in handle_cache_miss. Previously `e.to_string()`
   produced "git clone failed for '...': <msg>" which was nested inside
   another "git clone failed for '...': ..." making the output redundant.
devin-ai-integration[bot]

This comment was marked as resolved.

`git fetch --depth 1 origin main` updates FETCH_HEAD and origin/main
but not the local main branch. If the working tree is already on main,
`git checkout main` is a no-op and the files stay at the old commit.
Always checking out FETCH_HEAD ensures the working tree reflects the
just-fetched content regardless of the current branch state.
devin-ai-integration[bot]

This comment was marked as resolved.

A shallow clone without --branch only has the default branch tip.
The requested commit SHA is not available, so `git checkout <sha>`
fails. Instead, explicitly `git fetch origin <sha>` to retrieve the
commit object, then `git checkout FETCH_HEAD` to update the working
tree.
@fohte fohte merged commit 5368ddb into main Feb 18, 2026
3 checks passed
@fohte fohte deleted the fohte/impl-runok-init-remote-preset-v2 branch February 18, 2026 01:55
@fohte-bot fohte-bot bot mentioned this pull request Feb 17, 2026
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.

1 participant