Skip to content

GitHub Action to cache a directory via rsync#7

Open
pjones wants to merge 2 commits into
mainfrom
pjones/cache-action
Open

GitHub Action to cache a directory via rsync#7
pjones wants to merge 2 commits into
mainfrom
pjones/cache-action

Conversation

@pjones

@pjones pjones commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Simple directory sync via rsync.

Summary by CodeRabbit

  • New Features
    • Added a new rsync-based GitHub Action for caching build artifacts over SSH.
    • Added support for restoring cached files before a job and syncing updates after success.
  • Documentation
    • Expanded the README with build instructions and an example workflow for using the new cache action.
  • Chores
    • Updated example environment and ignore settings for a cleaner local setup.
    • Added project tooling for building the action bundles and working with Nix flakes.

@pjones pjones requested review from a team and timosachsenberg June 26, 2026 13:42
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@pjones, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 57 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

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 credits.

🚦 How do rate 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 see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b4ff757a-80c6-4ac0-a15f-4dba3f40dd69

📥 Commits

Reviewing files that changed from the base of the PR and between c94f115 and 9e99f4b.

📒 Files selected for processing (6)
  • README.md
  • actions/rsync-cache/action.yml
  • actions/rsync-cache/src/commit.js
  • actions/rsync-cache/src/restore.js
  • actions/rsync-cache/src/rsync.js
  • rollup.config.js
📝 Walkthrough

Walkthrough

Adds a new Cache via rsync GitHub Action, its rsync-based restore and commit entrypoints, bundle build configuration, and README usage instructions.

Changes

Cache via rsync action

Layer / File(s) Summary
Build and dev environment
package.json, rollup.config.js, flake.nix, .envrc.example, .gitignore
Adds the ES module package metadata, Rollup bundle config, Nix dev shell, and local ignore/envrc files used to build the action bundles.
Rsync transport implementation
actions/rsync-cache/src/rsync.js
Introduces the Rsync class with input validation, SSH and rsync command construction, key-file handling, and pull()/push() sync methods.
Action entrypoints and metadata
actions/rsync-cache/action.yml, actions/rsync-cache/src/restore.js, actions/rsync-cache/src/commit.js
Adds the action metadata and the restore.js and commit.js entrypoints that call Rsync.pull() or Rsync.push() with failure handling.
Usage documentation
README.md
Adds README build instructions and a workflow example for configuring Cache via rsync.

Sequence Diagram(s)

sequenceDiagram
  participant restore.js
  participant commit.js
  participant Rsync
  participant exec.exec
  participant core
  restore.js->>Rsync: pull()
  Rsync->>exec.exec: rsync remote cache -> local path
  exec.exec-->>Rsync: exit code
  Rsync-->>restore.js: exit code
  restore.js->>core: setFailed(error.message) on error
  commit.js->>Rsync: push()
  Rsync->>exec.exec: rsync local path -> remote cache
  exec.exec-->>Rsync: exit code
  Rsync-->>commit.js: exit code
  commit.js->>core: setFailed(error.message) on error
Loading

Poem

A bunny built a cache with care,
Through rsync hops it crossed the air.
Rollup spun and keys tucked tight,
Restore and commit worked day and night.
🐇✨

🚥 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 summarizes the main change: a GitHub Action for caching a directory with rsync.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pjones/cache-action

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
actions/rsync-cache/src/rsync.js (1)

71-79: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Private key file is not cleaned up if rsync invocation throws.

exec.exec runs with ignoreReturnCode: true, so a non-zero exit won't throw, but any thrown error (e.g., exec itself failing) leaves the private key at this.ssh_key_file on disk. Wrap the run/unlink in try/finally to guarantee removal.

🛡️ Proposed fix
-    // Run rsync.
-    const options = {ignoreReturnCode: true};
-    const exit_code = await exec.exec(this.command, [...this.args, ...additional_arguments], options);
-
-    // Remove the key file.
-    await fs.unlink(this.ssh_key_file);
-
-    // Let callers decide what to do with the exit code.
-    return exit_code;
+    // Run rsync.
+    const options = {ignoreReturnCode: true};
+    try {
+      return await exec.exec(this.command, [...this.args, ...additional_arguments], options);
+    } finally {
+      // Always remove the key file.
+      await fs.unlink(this.ssh_key_file);
+    }
🤖 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 `@actions/rsync-cache/src/rsync.js` around lines 71 - 79, The rsync command
path in rsync.js does not guarantee cleanup of the temporary SSH key when
exec.exec throws. Update the run/unlink flow in the rsync method to use a
try/finally around the exec.exec call so that fs.unlink(this.ssh_key_file)
always runs, even if this.command or the exec invocation fails; keep the
existing ignoreReturnCode behavior and preserve the current key file
creation/chmod logic.
flake.nix (1)

19-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the action's runtime tools to the dev shell.

nix develop currently gives you Node and shell linters, but this action's core path shells out through rsync and SSH. Including those binaries here would make local smoke-testing much closer to the real runtime.

Suggested diff
           devShells.default = pkgs.mkShell {
             nativeBuildInputs = with pkgs; [
               nodejs_24
+              rsync
+              openssh
               shellcheck
               shfmt
             ];
           };
🤖 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 `@flake.nix` around lines 19 - 24, The dev shell in the mkShell setup is
missing the runtime binaries used by the action’s main path, so local testing
does not match production behavior. Update the nativeBuildInputs for
devShells.default to include the tools used by the action’s rsync and SSH
execution path, alongside nodejs_24, shellcheck, and shfmt, so nix develop
provides everything needed for realistic smoke tests.
🤖 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 `@actions/rsync-cache/src/rsync.js`:
- Around line 20-24: The rsync target is missing the configured SSH username, so
`ssh_user` is read in the `RsyncCache` constructor but never applied. Update the
SSH/rsync command assembly in `RsyncCache` (including the `ssh_dir` target and
the command built later in the class) to prefix the remote host with
`this.ssh_user` so connections authenticate against the intended account instead
of the local runner user.
- Around line 76-82: `run()` in `RsyncCache` has two breakages: it is passing
merged arguments incorrectly and returning an undefined exit code. Update the
`exec.exec` call to combine `this.args` with `additional_arguments` as an array
so `this.command` receives valid args, and fix the exit-code variable naming so
the value assigned from `exec.exec` is the same symbol returned later
(`exit_code` instead of the misspelled temporary). Ensure the method still
removes `this.ssh_key_file` before returning.

In `@README.md`:
- Line 28: The ssh_port example has invalid YAML because it includes an extra
PORT: prefix in the value assignment. Update the README example so ssh_port is
defined as a normal key-value pair using the ARCHIVE_RRSYNC_PORT secret, and
remove the extraneous prefix to keep the YAML well-formed.

---

Nitpick comments:
In `@actions/rsync-cache/src/rsync.js`:
- Around line 71-79: The rsync command path in rsync.js does not guarantee
cleanup of the temporary SSH key when exec.exec throws. Update the run/unlink
flow in the rsync method to use a try/finally around the exec.exec call so that
fs.unlink(this.ssh_key_file) always runs, even if this.command or the exec
invocation fails; keep the existing ignoreReturnCode behavior and preserve the
current key file creation/chmod logic.

In `@flake.nix`:
- Around line 19-24: The dev shell in the mkShell setup is missing the runtime
binaries used by the action’s main path, so local testing does not match
production behavior. Update the nativeBuildInputs for devShells.default to
include the tools used by the action’s rsync and SSH execution path, alongside
nodejs_24, shellcheck, and shfmt, so nix develop provides everything needed for
realistic smoke tests.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 50cc7193-63a9-4551-9afb-7949237892fe

📥 Commits

Reviewing files that changed from the base of the PR and between 42eac09 and c94f115.

⛔ Files ignored due to path filters (2)
  • flake.lock is excluded by !**/*.lock
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • .envrc.example
  • .gitignore
  • README.md
  • actions/rsync-cache/action.yml
  • actions/rsync-cache/src/commit.js
  • actions/rsync-cache/src/restore.js
  • actions/rsync-cache/src/rsync.js
  • flake.nix
  • package.json
  • rollup.config.js

Comment thread actions/rsync-cache/src/rsync.js Outdated
Comment thread actions/rsync-cache/src/rsync.js Outdated
Comment thread README.md Outdated
Comment thread actions/rsync-cache/src/rsync.js Outdated
@pjones pjones force-pushed the pjones/cache-action branch 2 times, most recently from 6cb0531 to dd072f3 Compare June 26, 2026 14:24
@pjones

pjones commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@castorNova2

This is the caching action I wrote for vcpkg.

@pjones pjones force-pushed the pjones/cache-action branch 2 times, most recently from ca62d9b to 66d0d97 Compare June 26, 2026 14:34
Probably needs more error handling.
@pjones pjones force-pushed the pjones/cache-action branch from 66d0d97 to 9e99f4b Compare June 26, 2026 14:35
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