Skip to content

Improve swap-deps backup handling for multiple swaps - #48

Merged
justin808 merged 3 commits into
mainfrom
fix-backup-handling
Oct 9, 2025
Merged

Improve swap-deps backup handling for multiple swaps#48
justin808 merged 3 commits into
mainfrom
fix-backup-handling

Conversation

@justin808

@justin808 justin808 commented Oct 9, 2025

Copy link
Copy Markdown
Member

Summary

  • Improved backup file handling when swapping dependencies multiple times without restoring
  • Preserves original dependency versions through multiple swaps
  • Provides clearer messages about backup status

Problem

When users run swap-deps multiple times with different paths (e.g., swap to path A, then swap to path B without restoring), the tool was confusing about backup state.

Solution

  • Detect when a file is already swapped and preserve the original backup
  • Provide clear messages about backup status
  • Warn users about inconsistent states (backup exists but file not swapped)

Test plan

  • All existing tests pass
  • RuboCop passes
  • Manual testing shows improved messages when re-swapping

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Detects already-swapped dependency files and preserves existing backups.
    • Logs a clear confirmation when a backup is created (non-dry-run).
  • Bug Fixes

    • Prevents accidental backup overwrites by verifying current file state.
    • Stops and warns with restore instructions if a backup exists but the file looks inconsistent.
    • Improved logging to make swap/backup actions and states more visible.

When users swap dependencies multiple times without restoring (e.g.,
swapping from path A to path B), the tool now:

- Preserves the original backup (not the intermediate state)
- Provides clearer messages about backup status
- Detects and warns about inconsistent states

This prevents users from losing their original dependency versions
when performing multiple swaps in succession.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 9, 2025

Copy link
Copy Markdown

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds state-aware backup handling to lib/demo_scripts/gem_swapper.rb: backup_file now detects if Gemfile or package.json are already swapped, preserves existing backups when appropriate, warns and raises on inconsistent states, logs backup creation in non-dry runs, and wraps the expanded method with RuboCop complexity disables.

Changes

Cohort / File(s) Summary of Changes
Gem swapper backup logic
lib/demo_scripts/gem_swapper.rb
Enhanced backup_file: detect swapped state for Gemfile (shakakapacker, react_on_rails, cypress-on-rails using path: or github:) and package.json (dependencies/devDependencies/peerDependencies with file:); preserve existing backups when already swapped and log info; warn and raise on inconsistent backup/file states with restore instructions; log backup creation in non-dry-run mode; added RuboCop disables for MethodLength, AbcSize, CyclomaticComplexity, and PerceivedComplexity.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant GS as GemSwapper
  participant BF as backup_file
  participant FS as Filesystem

  Dev->>GS: Run swap operation
  GS->>BF: backup_file(target_path, dry_run)
  BF->>FS: Check for existing backup file
  alt Backup exists
    BF->>FS: Inspect current file for swapped markers
    alt Already swapped
      BF-->>GS: Keep existing backup, log info
    else Appears unswapped
      BF-->>GS: Log warning + print restore instructions
      BF-->>Dev: Raise Error and halt
    end
  else No backup
    BF->>FS: Create backup (unless dry-run)
    BF-->>GS: Log backup created
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

I nibble bytes by Gemfile light,
Backups kept snug through swap or fight.
If paths are swapped, I'll leave them be—
If not, I warn and pause with glee.
Logs like pawprints for you to see. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately describes the primary change of improving backup handling for multiple swap operations in the swap-deps script, directly aligning with the PR’s intent to preserve original backups and manage repeated swaps without confusion.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-backup-handling

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e01c060 and ff91bc2.

📒 Files selected for processing (1)
  • lib/demo_scripts/gem_swapper.rb (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: claude-review
🔇 Additional comments (2)
lib/demo_scripts/gem_swapper.rb (2)

739-784: Well-designed state-aware backup handling.

The logic correctly handles multiple swap scenarios:

  • Preserves original backups when re-swapping to different paths (lines 771-774)
  • Detects and warns about inconsistent states with clear remediation steps (lines 775-783)
  • Checks only managed packages to avoid false positives from unrelated file: dependencies

The approach addresses the PR objectives effectively.


790-790: Good UX improvement.

Adding explicit feedback when creating backups improves visibility into what the tool is doing.


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 and usage tips.

@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: 0

🧹 Nitpick comments (1)
lib/demo_scripts/gem_swapper.rb (1)

739-767: LGTM! Well-designed backup preservation logic with excellent error handling.

The implementation correctly addresses the PR objectives:

  • Preserves original backup when re-swapping to different paths ✓
  • Detects inconsistent state and provides clear remediation steps ✓
  • User messaging is helpful and actionable ✓

Minor enhancement: Consider anchoring the regex pattern to avoid matching commented lines.

The gem detection pattern on line 745 could potentially match commented gem lines (e.g., # gem 'shakapacker', path: '...'), leading to false positives. For consistency with swap_gem_in_gemfile (line 626) which anchors patterns with ^, consider:

-        gem_pattern = /gem\s+["'](?:shakapacker|react_on_rails|cypress-on-rails)["'],.*(?:path:|github:)/
+        gem_pattern = /^\s*gem\s+["'](?:shakapacker|react_on_rails|cypress-on-rails)["'],.*(?:path:|github:)/

This anchors to the start of line and matches leading whitespace, preventing false matches in comments. However, this is a low-risk issue since:

  1. The specific pattern is unlikely to appear in comments
  2. The worst-case impact is unnecessarily preserving a backup (safe failure mode)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ee628c and 766c6d3.

📒 Files selected for processing (1)
  • lib/demo_scripts/gem_swapper.rb (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: claude-review
🔇 Additional comments (2)
lib/demo_scripts/gem_swapper.rb (2)

735-736: MethodLength disable is appropriate.

The method complexity increased to handle the new backup preservation logic, which is necessary for the feature. The rubocop disable is justified.


769-774: Good addition of user feedback logging.

The log message on line 773 provides clear feedback when a backup is created, improving transparency about what the tool is doing.

@justin808
justin808 requested a review from Copilot October 9, 2025 22:27
@justin808

Copy link
Copy Markdown
Member Author

@claude review this pr

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

Pull Request Overview

Improves dependency swap backup handling to properly manage multiple swaps without restoration, preserving original dependency versions and providing clearer status messages.

  • Detects when files are already swapped to prevent redundant backups
  • Preserves existing backups and warns about inconsistent states
  • Adds confirmation messages for backup creation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread lib/demo_scripts/gem_swapper.rb Outdated
is_gemfile = file_path.end_with?('Gemfile')

# Check if file has already been swapped
gem_pattern = /gem\s+["'](?:shakapacker|react_on_rails|cypress-on-rails)["'],.*(?:path:|github:)/

Copilot AI Oct 9, 2025

Copy link

Choose a reason for hiding this comment

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

The hardcoded gem names in the regex make this method tightly coupled to specific gems. Consider extracting these gem names to a constant or configuration to improve maintainability.

Suggested change
gem_pattern = /gem\s+["'](?:shakapacker|react_on_rails|cypress-on-rails)["'],.*(?:path:|github:)/
gem_names = NPM_PACKAGE_PATHS.keys.map { |name| Regexp.escape(name) }.join('|')
gem_pattern = Regexp.new("gem\\s+[\"'](?:#{gem_names})[\"'],.*(?:path:|github:)")

Copilot uses AI. Check for mistakes.
Comment on lines +746 to +752
already_swapped = if is_gemfile
# Check for path: or github: in Gemfile
content.match?(gem_pattern)
else
# Check for file: in package.json
content.include?('"file:')
end

Copilot AI Oct 9, 2025

Copy link

Choose a reason for hiding this comment

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

The swap detection logic uses different patterns for different file types. Consider extracting this into separate methods (e.g., gemfile_swapped? and package_json_swapped?) to improve readability and testability.

Copilot uses AI. Check for mistakes.
Comment thread lib/demo_scripts/gem_swapper.rb Outdated
Comment on lines +750 to +751
# Check for file: in package.json
content.include?('"file:')

Copilot AI Oct 9, 2025

Copy link

Choose a reason for hiding this comment

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

The package.json swap detection is too broad - it will match any occurrence of '"file:' in the content, potentially including comments or unrelated JSON fields. Consider using a more specific pattern that matches dependency declarations.

Suggested change
# Check for file: in package.json
content.include?('"file:')
# Check for file: in package.json dependency fields
begin
package = JSON.parse(content)
dep_fields = %w[dependencies devDependencies peerDependencies optionalDependencies bundledDependencies]
already_swapped = dep_fields.any? do |field|
deps = package[field]
next false unless deps.is_a?(Hash)
deps.values.any? { |v| v.is_a?(String) && v.start_with?('file:') }
end
rescue JSON::ParserError
already_swapped = false
end

Copilot uses AI. Check for mistakes.
@claude

claude Bot commented Oct 9, 2025

Copy link
Copy Markdown

Claude finished @justin808's task —— View job


Code Review: Improve swap-deps backup handling for multiple swaps

Tasks

  • Read the changed file
  • Analyze the diff
  • Review the implementation
  • Provide feedback

Summary

This PR successfully addresses the problem of confusing backup state when swapping dependencies multiple times. The implementation is well-thought-out with good error handling and user messaging. I found a few issues to address:

Issues Found

1. Critical: Regex pattern doesn't anchor to line start (lib/demo_scripts/gem_swapper.rb:745)

The gem detection pattern can match commented-out gem lines, leading to false positives:

gem_pattern = /gem\s+["'](?:shakapacker|react_on_rails|cypress-on-rails)["'],.*(?:path:|github:)/

This will match:

# gem 'shakapacker', path: '/tmp/test'  # ← Commented out but still matches

Recommendation: Anchor to line start and allow for leading whitespace:

gem_pattern = /^\s*gem\s+["'](?:shakapacker|react_on_rails|cypress-on-rails)["'],.*(?:path:|github:)/

This matches the pattern used in swap_gem_in_gemfile (line 626) which already uses ^ anchoring.

2. Bug: package.json detection is too broad (lib/demo_scripts/gem_swapper.rb:751)

The package.json swap detection will match "file: anywhere in the JSON content:

content.include?('"file:')

This could match:

  • JSON strings that happen to contain "file:
  • Comments (if any)
  • Unrelated fields

Recommendation: Parse the JSON and check dependency fields specifically:

already_swapped = if is_gemfile
                    content.match?(gem_pattern)
                  else
                    # Parse JSON and check dependency fields
                    begin
                      data = JSON.parse(content)
                      dep_types = %w[dependencies devDependencies peerDependencies]
                      dep_types.any? do |type|
                        deps = data[type]
                        deps.is_a?(Hash) && deps.values.any? { |v| v.is_a?(String) && v.start_with?('file:') }
                      end
                    rescue JSON::ParserError
                      false
                    end
                  end

This is more robust and matches the approach used in swap_package_json (lines 686-702).

3. Minor: Hardcoded gem names reduce maintainability (lib/demo_scripts/gem_swapper.rb:745)

The regex hardcodes gem names instead of using the SUPPORTED_GEMS constant:

gem_pattern = /gem\s+["'](?:shakapacker|react_on_rails|cypress-on-rails)["'],.*(?:path:|github:)/

Recommendation: Generate from NPM_PACKAGE_PATHS.keys for consistency:

gem_names = NPM_PACKAGE_PATHS.keys.map { |name| Regexp.escape(name) }.join('|')
gem_pattern = /^\s*gem\s+["'](?:#{gem_names})["'],.*(?:path:|github:)/

Positive Aspects

Excellent error handling: The inconsistent state detection (lines 759-766) is well-implemented with clear guidance for users

Good user messaging: Clear distinction between "using existing backup" (line 756) vs. warning about inconsistent state

Preserves original backups: Correctly solves the core problem of preserving original dependencies through multiple swaps

Added confirmation logging: The new message on line 773 improves transparency

Test Coverage Note

The PR description mentions manual testing, but consider adding automated tests for:

  • Re-swapping to different paths (preserves backup)
  • Detecting inconsistent state (backup exists, file not swapped)
  • Edge cases with commented gem lines

Recommendation

Fix issues #1 and #2 (the regex patterns) before merging. Issue #3 is a nice-to-have for maintainability.


Job Run | Branch: fix-backup-handling

Address three issues identified in code review:

1. Fix regex pattern to anchor to line start (^\s*) to avoid matching
   commented-out gem lines
2. Fix package.json detection to properly parse JSON and check dependency
   fields instead of simple string search
3. Use NPM_PACKAGE_PATHS.keys to generate gem names dynamically instead
   of hardcoding them

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude

claude Bot commented Oct 9, 2025

Copy link
Copy Markdown

Code Review - PR #48: Improve swap-deps backup handling for multiple swaps

Summary

This PR improves the backup file handling logic to better support multiple sequential swaps without restoring. Overall, the implementation is solid and addresses a real usability issue.


Strengths

  1. Well-defined problem and solution - Clearly addresses confusing backup states when swapping multiple times
  2. Good test coverage - Comprehensive test suite exists (though this specific feature needs tests)
  3. Clear user messaging - Good use of informative messages
  4. Proper error handling - Raises appropriate errors with actionable guidance

Code Quality and Best Practices

Good Practices:

  • Proper RuboCop directives for complexity metrics
  • Follows existing code style
  • Good separation of concerns (Gemfile vs package.json)
  • Helpful inline comments

Areas for Improvement:

Method Complexity (lib/demo_scripts/gem_swapper.rb:743-794)
The method has grown significantly. Consider extracting helper methods for better readability and testability.


Potential Issues

  1. Regex Performance (line 753)
    Pattern is constructed dynamically on every call. Low impact, but could be optimized with a constant.

  2. JSON Parsing (lines 760-769)
    Silent failure could hide corrupt package.json. Consider adding warning in verbose mode.

  3. False Positive Detection Risk

The check for file: in package.json is too broad - it matches ANY file: dependency, not just managed ones. If projects have other file: deps, it incorrectly detects as swapped.

Fix: Check specific package names (shakapacker, react-on-rails, cypress-on-rails).


Security

No new concerns - Safe file operations, no user input in commands, proper use of File.basename


Performance

Minimal impact - File read only when backup exists


Test Coverage MISSING

The new logic (lines 747-784) lacks unit tests. The comment saying backup_file is simple is now outdated.

Recommended tests:

  1. Backup exists + file swapped - Uses existing backup
  2. Backup exists + file NOT swapped - Raises error
  3. Backup exists + Gemfile has path: - Detected correctly
  4. Backup exists + package.json has file: - Detected correctly
  5. Backup exists + corrupt JSON - Handles gracefully

Recommendations

Priority: High

  1. Add unit tests for new backup detection
  2. Fix false positive risk in package.json check

Priority: Medium
3. Extract helper methods
4. Add JSON parse error context

Priority: Low
5. Memoize regex pattern


Conclusion

Solid improvement addressing a real issue. Request changes for:

  1. Unit tests
  2. Package.json false positive fix

Once addressed, ready to merge!

Review by Claude Code

@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: 1

🧹 Nitpick comments (1)
lib/demo_scripts/gem_swapper.rb (1)

745-762: Consider extracting swap detection into separate methods.

The swap detection logic for Gemfile and package.json could be extracted into dedicated methods (gemfile_swapped? and package_json_swapped?) to improve readability and testability. This would also make it easier to add more sophisticated detection logic in the future.

Based on learnings.

Example refactoring:

def gemfile_swapped?(content)
  gem_names = NPM_PACKAGE_PATHS.keys.map { |name| Regexp.escape(name) }.join('|')
  gem_pattern = /^\s*gem\s+["'](?:#{gem_names})["'],.*(?:path:|github:)/
  content.match?(gem_pattern)
end

def package_json_swapped?(content)
  data = JSON.parse(content)
  dep_types = %w[dependencies devDependencies peerDependencies]
  managed_npm_names = NPM_PACKAGE_PATHS.select { |_, path| !path.nil? }
                                       .keys
                                       .map { |name| name.tr('_', '-') }
  dep_types.any? do |type|
    deps = data[type]
    next false unless deps.is_a?(Hash)
    deps.any? { |pkg, ver| managed_npm_names.include?(pkg) && ver.is_a?(String) && ver.start_with?('file:') }
  end
rescue JSON::ParserError
  false
end

Then in backup_file:

already_swapped = if is_gemfile
                    gemfile_swapped?(content)
                  else
                    package_json_swapped?(content)
                  end
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 766c6d3 and e01c060.

📒 Files selected for processing (1)
  • lib/demo_scripts/gem_swapper.rb (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: claude-review
🔇 Additional comments (4)
lib/demo_scripts/gem_swapper.rb (4)

735-736: LGTM: Complexity metrics disabled appropriately.

The RuboCop disables are justified given the added state-detection logic. The method handles multiple scenarios (backup exists + swapped vs unswapped) which increases complexity necessarily.

Also applies to: 786-786


745-749: LGTM: Gemfile swap detection logic is correct.

The pattern correctly detects if the file has been modified by checking whether ANY supported gem uses path: or github:. This approach is appropriate because:

  • If any supported gem is swapped, the file has been modified from its original state
  • The backup should preserve the true original (before any swaps)
  • This enables re-swapping to different paths without losing the original

764-776: LGTM: Error handling for inconsistent state is appropriate.

The approach of raising an error when a backup exists but the file appears unswapped is a reasonable safety check. The error message provides clear guidance to the user on how to resolve the inconsistency.


783-783: LGTM: Improved user feedback.

Adding a log message when creating the backup improves transparency and helps users understand what's happening during the swap operation.

Comment thread lib/demo_scripts/gem_swapper.rb Outdated
The previous implementation checked for ANY file: dependency in package.json,
which incorrectly detected the file as swapped when unrelated file:
dependencies existed.

Now checks only managed packages (shakapacker, react-on-rails,
cypress-on-rails) by converting gem names to npm package names and checking
if those specific packages use file: protocol.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude

claude Bot commented Oct 9, 2025

Copy link
Copy Markdown

Code Review - PR #48: Improve swap-deps backup handling for multiple swaps

Summary

This PR improves the backup file handling logic in the gem_swapper.rb to better handle scenarios where users run swap-deps multiple times with different paths without restoring. The implementation is solid overall with good error handling and clear user messaging.


✅ Code Quality & Best Practices

Strengths:

  • Clear intent: The logic properly distinguishes between already swapped and inconsistent state scenarios
  • Good separation of concerns: Gemfile and package.json detection logic is cleanly separated
  • Informative messaging: User-facing messages are clear and actionable with helpful emoji indicators
  • Appropriate error handling: Raises an error with clear instructions when encountering inconsistent state

Minor Suggestions:

  1. Consider extracting detection logic (lib/demo_scripts/gem_swapper.rb:753-777):
    The swap detection logic is complex and could benefit from extraction into separate methods for better readability and testability.

  2. RuboCop disables (lib/demo_scripts/gem_swapper.rb:743):
    While the RuboCop disables are justified given the complexity, consider if extracted methods might reduce some metrics naturally.


🐛 Potential Bugs & Issues

1. Regex escaping performance (lib/demo_scripts/gem_swapper.rb:753):
The regex is reconstructed on every call. Consider memoizing this pattern as a constant since NPM_PACKAGE_PATHS is frozen.

2. JSON parsing edge case (lib/demo_scripts/gem_swapper.rb:774-776):
The JSON::ParserError rescue is good. The current logic handles nil dependency sections correctly with next false unless deps.is_a?(Hash).

3. Race condition possibility:
Between checking File.exist?(backup_path) and reading File.read(file_path), the file could theoretically be modified. This is unlikely in typical usage but worth noting.


⚡ Performance Considerations

  1. File I/O: The method reads the entire file content. For config files (typically small), this is acceptable.
  2. Regex compilation: The regex pattern is recreated on each invocation. Memoization would provide a small performance boost.

🔒 Security Concerns

No security issues identified. The code properly:

  • Uses safe file operations (FileUtils.cp)
  • Validates input through existing methods
  • Does not execute user-provided code
  • Properly escapes regex patterns

🧪 Test Coverage

Status: ⚠️ Tests needed

The PR description mentions All existing tests pass and RuboCop passes, but I notice:

  1. Missing test coverage for the new logic:

    • No tests verify the already swapped with existing backup scenario (line 779-782)
    • No tests verify the backup exists but file not swapped error case (line 784-790)
    • The spec file at spec/demo_scripts/gem_swapper_spec.rb:386-394 has a comment noting backup tests are limited
  2. Recommended test additions: Add tests for both the preserve existing backup and inconsistent state error scenarios, plus swap detection logic for Gemfile and package.json files.


📋 Recommendations Summary

High Priority:

  1. ✅ Add test coverage for the new backup handling logic
  2. 🔄 Consider extracting swap detection into separate methods for better testability

Medium Priority:
3. ⚡ Optimize regex pattern compilation (memoize as constant)
4. 📝 Add inline comments explaining edge cases (e.g., nil dependency sections)

Low Priority:
5. 📚 Update method documentation if needed


Conclusion

This is a well-implemented improvement that addresses a real user pain point. The logic is sound, error handling is appropriate, and user messaging is excellent. With the addition of comprehensive tests for the new scenarios, this will be ready to merge.

The main gap is test coverage for the new conditional logic paths. Once tests are added to verify both the preserve existing backup and inconsistent state error scenarios, this PR will be solid.

Great work on improving the developer experience! 🎉


Review generated with 🤖 Claude Code

@justin808
justin808 merged commit 8deb1a2 into main Oct 9, 2025
3 checks passed
@justin808
justin808 deleted the fix-backup-handling branch October 9, 2025 23:14
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