Skip to content

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Oct 8, 2025

Summary

  • Fixes the swap-deps tool to correctly use tag: parameter for Git tags instead of branch:
  • Adds test coverage for tag syntax

Changes

When using bin/swap-deps --github user/[email protected], the tool now correctly generates:

gem "foo", github: "user/repo", tag: "v1.0.0"

Instead of the incorrect:

gem "foo", github: "user/repo", branch: "v1.0.0"

Implementation Details

  • Modified swap_gem_to_github method in lib/demo_scripts/gem_swapper.rb to use info[:ref_type] to determine whether to use tag: or branch: parameter
  • Added test case in spec/demo_scripts/gem_swapper_spec.rb to verify tag syntax
  • All existing tests continue to pass

Test Plan

  • Run RSpec tests: bundle exec rspec spec/demo_scripts/gem_swapper_spec.rb - all passing
  • Run RuboCop: bundle exec rubocop on changed files - no offenses
  • Verified new test case for tag syntax
  • Verified existing branch tests still pass

Fixes #38

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Supports using Git tags when swapping a gem to a GitHub source.
    • Automatically chooses tag or branch based on the provided reference.
    • Omits the branch parameter when targeting the default branch for cleaner output.
  • Tests
    • Added test coverage for tag-based GitHub references to ensure correct gem line generation.

When using bin/swap-deps --github user/[email protected], the tool now
correctly generates:

  gem "foo", github: "user/repo", tag: "v1.0.0"

Instead of the incorrect:

  gem "foo", github: "user/repo", branch: "v1.0.0"

Changes:
- Update swap_gem_to_github to use :ref_type to determine parameter
- Use 'tag:' for tags and 'branch:' for branches
- Add test coverage for tag syntax

Fixes #38

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

Co-Authored-By: Claude <[email protected]>
@coderabbitai
Copy link

coderabbitai bot commented Oct 8, 2025

Warning

Rate limit exceeded

@justin808 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 27 minutes and 7 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 2486ff6 and 722579b.

📒 Files selected for processing (10)
  • .new-demo-versions (1 hunks)
  • .swap-deps.yml.example (1 hunks)
  • bin/new-demo (2 hunks)
  • docs/LOCAL_DEVELOPMENT.md (1 hunks)
  • lib/demo_scripts/demo_creator.rb (3 hunks)
  • lib/demo_scripts/gem_swapper.rb (4 hunks)
  • lib/demo_scripts/github_spec_parser.rb (2 hunks)
  • spec/demo_scripts/demo_creator_spec.rb (6 hunks)
  • spec/demo_scripts/gem_swapper_spec.rb (2 hunks)
  • spec/demo_scripts/github_spec_parser_spec.rb (1 hunks)

Walkthrough

Updated swap_gem_to_github to select the Bundler parameter based on ref_type: uses tag: for :tag and branch: otherwise, skipping the ref when branch is 'main'. Added a test case verifying tag-based GitHub references produce tag: 'vX.Y.Z' in the generated gem line.

Changes

Cohort / File(s) Summary
Core logic update
lib/demo_scripts/gem_swapper.rb
Adjusts swap_gem_to_github to choose tag: when ref_type is :tag, otherwise branch:. Omits ref when branch is 'main'.
Test coverage
spec/demo_scripts/gem_swapper_spec.rb
Adds tests ensuring tag-based refs generate tag: 'v1.0.0' instead of branch:.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant CLI as swap-deps CLI
  participant GS as GemSwapper.swap_gem_to_github
  participant Gemfile as Gemfile Line

  User->>CLI: run --github user/[email protected]
  CLI->>GS: swap_gem_to_github(line, gem_name, {repo, ref_type, branch/tag})
  alt ref_type == :tag
    GS->>GS: param_name = "tag"
  else ref_type != :tag
    GS->>GS: param_name = "branch"
  end
  alt branch == "main"
    GS->>Gemfile: replace with github: "user/repo"
  else
    GS->>Gemfile: replace with github: "user/repo", {param_name}: "<ref>"
  end
  GS-->>CLI: updated line
  CLI-->>User: writes updated Gemfile
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I hop through gems with whiskers bright,
Swapping branches, tags just right.
No more oops on v1.0.0,
Tag it proper—off we go!
Thump-thump tests that pass on cue,
Carrots up for clean ref glue. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly states the primary change—updating swap-deps to use correct Bundler syntax for Git tags—which accurately reflects the PR’s main objective. It is concise and specific enough for a teammate to understand the primary change at a glance.
Linked Issues Check ✅ Passed The changes correctly implement selection of the tag or branch parameter based on info[:ref_type], handle the special-case main branch, and include tests verifying tag syntax, fully addressing issue #38’s requirements. Existing behavior is preserved and tests cover both branch and tag scenarios, so the linked issue objectives are met.
Out of Scope Changes Check ✅ Passed All modifications are confined to the swap_gem_to_github method and its associated spec, directly addressing the bug and test requirements without introducing unrelated changes. No other files or features were altered.

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.

@claude
Copy link

claude bot commented Oct 8, 2025

Code Review - PR #43: Fix swap-deps to use correct Bundler syntax for Git tags

Summary

This PR correctly fixes the swap-deps tool to use tag: parameter for Git tags instead of branch:. The implementation is clean, well-tested, and addresses issue #38 appropriately.

✅ Code Quality & Best Practices

Strengths:

  • Clean implementation: The fix is minimal and focused - only changes what's necessary (lib/demo_scripts/gem_swapper.rb:282-286)
  • Follows Ruby conventions: Proper use of ternary operator and string interpolation
  • Maintains consistency: The change aligns with how ref_type is already used elsewhere in the codebase
  • Good test coverage: New test case specifically validates the tag syntax (spec/demo_scripts/gem_swapper_spec.rb:169-177)
  • Preserves backward compatibility: Existing tests continue to pass, ensuring no regression

Code Quality:

  • The logic in swap_gem_to_github (line 282) correctly determines parameter name based on ref_type
  • The condition if info[:branch] != 'main' (line 286) appropriately handles the default branch case
  • Code is readable and self-documenting

✅ Potential Bugs & Issues

None identified. The implementation appears correct:

  • The ref_type field is already being set in validate_github_repos (lines 104, 107, 116) for all code paths
  • The ternary operator correctly maps :tag'tag' and anything else → 'branch'
  • The existing validation in validate_github_repos (lines 128-130) ensures branch/tag names are safe

Minor observation: The variable name info[:branch] is used for both branches and tags (line 286). While this works, it might be slightly clearer to use a more generic name like info[:ref]. However, this is very minor and changing it would require broader refactoring.

✅ Performance Considerations

No concerns. The changes:

  • Add a single conditional check (ternary operator) which is O(1)
  • No loops, additional I/O, or memory allocation
  • Negligible performance impact

✅ Security Concerns

Well-handled. Security is already properly addressed:

  • Input validation in validate_github_repos (lines 128-130) prevents injection attacks in branch/tag names
  • The regex \A[\w.\-/]+\z restricts characters to safe alphanumerics, dots, hyphens, and slashes
  • No new security vectors introduced by this change
  • The fix actually improves correctness, which indirectly improves security by ensuring predictable behavior

✅ Test Coverage

Excellent test coverage:

  • New test case added for tag syntax (spec/demo_scripts/gem_swapper_spec.rb:169-177)
  • Test validates that ref_type: :tag produces tag: 'v1.0.0' in output
  • Existing tests for branch syntax continue to pass
  • The test follows the same pattern as other tests in the suite

Suggestions for additional test coverage (optional):

  1. A test for ref_type: :branch explicitly (currently only implicit through existing tests)
  2. Edge case: tag with main name to ensure it's included (unlike default main branch)

However, the current test coverage is sufficient for this fix.

📝 Recommendations

Optional improvements (not blocking):

  1. Consider adding explicit test for branch ref_type:
context 'with explicit branch ref_type' do
  let(:gemfile_content) { "gem 'shakapacker', '~> 9.0.0'\n" }
  let(:github_info) { { repo: 'shakacode/shakapacker', branch: 'develop', ref_type: :branch } }

  it 'uses branch parameter' do
    result = swapper.send(:swap_gem_to_github, gemfile_content, 'shakapacker', github_info)
    expect(result).to eq("gem 'shakapacker', github: 'shakacode/shakapacker', branch: 'develop'\n")
  end
end
  1. Test edge case where tag is named "main":
    This would verify that tags aren't skipped just because they match the default branch name.

✅ Overall Assessment

Strong approval. This PR:

  • ✅ Solves the stated problem correctly
  • ✅ Includes appropriate test coverage
  • ✅ Follows project conventions
  • ✅ Maintains backward compatibility
  • ✅ Has no security concerns
  • ✅ Passes all tests
  • ✅ Well-documented with clear commit message and PR description

The implementation is production-ready. The optional suggestions above are minor enhancements that could be addressed in a future PR if desired.

Recommendation: Approve and merge


🤖 Review generated with Claude Code

Copy link

@coderabbitai coderabbitai bot left a comment

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)
spec/demo_scripts/gem_swapper_spec.rb (1)

169-177: LGTM! Test correctly validates tag syntax.

The test appropriately verifies that when ref_type: :tag is provided, the generated gem line uses tag: 'v1.0.0' instead of branch:. This aligns with the PR objectives and follows the existing test patterns.

Consider adding a test case for the edge scenario where a tag is named 'main':

context 'with tag named main' do
  let(:gemfile_content) { "gem 'shakapacker', '~> 9.0.0'\n" }
  let(:github_info) { { repo: 'shakacode/shakapacker', branch: 'main', ref_type: :tag } }

  it 'includes tag parameter even for main' do
    result = swapper.send(:swap_gem_to_github, gemfile_content, 'shakapacker', github_info)
    expect(result).to eq("gem 'shakapacker', github: 'shakacode/shakapacker', tag: 'main'\n")
  end
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 bef529d and 2486ff6.

📒 Files selected for processing (2)
  • lib/demo_scripts/gem_swapper.rb (1 hunks)
  • spec/demo_scripts/gem_swapper_spec.rb (1 hunks)
🔇 Additional comments (1)
lib/demo_scripts/gem_swapper.rb (1)

281-282: LGTM! Correctly selects parameter based on ref type.

The logic properly uses ref_type to determine whether to generate tag: or branch: parameter, which directly addresses the PR objectives.

Improved the swap_gem_to_github logic to correctly handle:

1. Tags named 'main' or 'master' - these must include the tag parameter
   Example: gem "foo", github: "user/repo", tag: "main"

2. Master branch as default - like 'main', omit the branch parameter
   Example: gem "foo", github: "user/repo"

3. Default ref_type to :branch when not specified for backward compatibility

Added comprehensive test coverage for:
- Tag named 'main' (ensures tag is not omitted)
- Master branch (ensures branch is omitted like main)
- Explicit branch ref_type

This ensures tags are always explicit while branches 'main' and 'master'
can be omitted as they are Bundler defaults.

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

Co-Authored-By: Claude <[email protected]>
@claude
Copy link

claude bot commented Oct 8, 2025

Code Review - PR #43

Summary

This PR fixes a bug in the swap-deps tool to correctly use the tag: parameter for Git tags instead of incorrectly using branch:. The implementation is solid with excellent test coverage.

✅ Strengths

Code Quality

  • Clean implementation: The logic in lib/demo_scripts/gem_swapper.rb:281-291 is clear and well-commented
  • Proper separation of concerns: Uses ref_type to distinguish between tags and branches
  • Backward compatibility: Defaults to :branch when ref_type is not specified (line 282)
  • Edge case handling: Correctly handles the "master" branch case in addition to "main"

Test Coverage

  • Comprehensive test cases: Added 4 new test cases covering tag usage, explicit branch ref_type, tag named "main", and master branch omission
  • Good test structure: Clear context blocks and descriptive test names
  • Maintains existing tests: All previous test cases remain intact

Documentation

  • Excellent PR description: Clear summary, implementation details, and test plan
  • Inline comments: Code comments explain the logic (lines 281-287)

🔍 Observations

Naming Consideration

The variable name info[:branch] is used even when it contains a tag (line 291). While functional, this could be slightly confusing. However, this is a minor point and not worth changing given it is consistent with the existing codebase.

Edge Case Coverage

The implementation correctly handles an important edge case: a tag named "main" or "master" will still include the explicit tag: parameter (lines 285-287, tested in spec lines 189-196). This is correct Bundler behavior.

🎯 Best Practices Followed

✅ Single Responsibility: Each change serves the specific purpose of fixing the tag syntax
✅ Test-Driven: Tests cover the bug and edge cases
✅ Code Style: Follows RuboCop conventions
✅ Git Hygiene: References issue #38 in the PR description
✅ Semantic Logic: The should_omit_ref variable makes the intent clear

🔒 Security & Performance

  • No security concerns: The change is purely syntactic
  • No performance impact: Same computational complexity
  • Input validation: Already handled by validate_github_repos method

✅ Approval Recommendation

This PR is ready to merge. It:

Great work on the implementation and thorough testing! 🎉


Review generated by Claude Code

@justin808 justin808 requested a review from Copilot October 9, 2025 02:30
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Fixes the swap-deps tool to correctly use tag: parameter for Git tags instead of incorrectly using branch: for all Git references in Bundler gem declarations.

  • Uses ref_type to distinguish between tags and branches when generating Bundler syntax
  • Adds comprehensive test coverage for tag vs branch scenarios
  • Maintains existing behavior of omitting branch parameter for default branches (main/master) while always including tag parameter

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
lib/demo_scripts/gem_swapper.rb Updated gem swapping logic to use correct Bundler syntax based on reference type
spec/demo_scripts/gem_swapper_spec.rb Added test cases covering tag syntax, explicit branch types, and edge cases

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

Improved documentation to make tag vs branch syntax clearer:

.swap-deps.yml.example:
- Added explicit branch example with # syntax
- Added explicit tag example with @ syntax showing Bundler output
- Added real-world tag examples showing exact Bundler syntax generated
- Added pre-release tag example
- Clarified ref_type option in hash format

docs/LOCAL_DEVELOPMENT.md:
- Clarified Gemfile syntax differences between branches and tags
- Noted that branches omit 'branch:' for main/master
- Noted that tags are always explicit

These examples make it crystal clear what Bundler syntax will be
generated for each input format, helping users understand the fix
for issue #38.

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

Co-Authored-By: Claude <[email protected]>
@claude
Copy link

claude bot commented Oct 9, 2025

Code Review - PR #43: Fix swap-deps to use correct Bundler syntax for Git tags

Summary

This PR successfully addresses issue #38 by fixing the swap-deps tool to correctly use tag: parameter for Git tags instead of branch:. The implementation is well-thought-out with comprehensive test coverage and excellent documentation updates.


✅ Strengths

1. Correct Implementation

  • Properly distinguishes between tags and branches using ref_type parameter (lib/demo_scripts/gem_swapper.rb:282-283)
  • Handles edge cases correctly: tags named 'main'/'master' are kept explicit while branches 'main'/'master' are omitted (lib/demo_scripts/gem_swapper.rb:287)
  • Maintains backward compatibility by defaulting to :branch when ref_type is not specified

2. Excellent Test Coverage
The test suite comprehensively covers:

  • Basic tag syntax (spec/demo_scripts/gem_swapper_spec.rb:169-177)
  • Explicit branch ref_type (spec/demo_scripts/gem_swapper_spec.rb:179-187)
  • Edge case: tag named 'main' (spec/demo_scripts/gem_swapper_spec.rb:189-197)
  • Edge case: master branch default (spec/demo_scripts/gem_swapper_spec.rb:199-207)

3. Clear Documentation

  • Updated .swap-deps.yml.example with concrete examples showing exact Bundler syntax generated
  • Added explanatory comments distinguishing # for branches vs @ for tags
  • Updated docs/LOCAL_DEVELOPMENT.md to clarify the syntax differences

4. Code Quality

  • Clean, readable code with helpful comments
  • Follows Ruby conventions
  • No security concerns identified

💡 Suggestions for Improvement

1. Potential Git Clone Issue with Tags

In lib/demo_scripts/gem_swapper.rb:178, the code uses --branch flag for both branches and tags:

success = system('git', 'clone', '--depth', '1', '--branch', info[:branch], repo_url, cache_path,
                 out: '/dev/null', err: '/dev/null')

Issue: While Git's --branch flag can technically accept tags, the variable name info[:branch] is misleading when it contains a tag. More importantly, the update logic in update_github_repo (line 186) uses git fetch origin info[:branch], which may not work correctly for tags.

Recommendation:

  • Consider renaming the hash key from :branch to :ref since it can hold both branches and tags
  • Or handle tag cloning/updating differently, as tags don't update like branches do
  • Add a test that actually clones a GitHub repo with a tag to ensure this works end-to-end

2. Test Coverage Gap

The current tests only verify string generation but don't test the actual GitHub cloning with tags. Consider adding integration tests that:

  • Clone a real/test repo using a tag
  • Verify the cached repo is at the correct tag
  • Test the update behavior for tags (tags shouldn't update, unlike branches)

3. Minor: Variable Naming Clarity

The variable info[:branch] holds both branches and tags throughout the codebase. While this works, it could be clearer:

# Current
{ repo: repo, branch: ref, ref_type: :tag }

# Suggestion
{ repo: repo, ref: ref, ref_type: :tag }

This would make the code more self-documenting and reduce confusion.


🔒 Security

✅ No security concerns identified. The code:

  • Uses array form for git commands to avoid shell injection (already present)
  • Validates repo format with regex
  • Handles user input safely

🎯 Performance

✅ No performance concerns. The changes are minimal and don't introduce any performance overhead.


📋 Final Verdict

Recommendation: APPROVE with minor suggestions

This is a solid PR that correctly fixes the reported issue. The implementation is clean, well-tested, and well-documented. The suggestions above are minor improvements for robustness, particularly around ensuring tag cloning/fetching works correctly in practice.

The main concern is ensuring that git clone --branch <tag> and git fetch origin <tag> work correctly for tags in the wild. If these operations have been manually tested and work, this PR is ready to merge.

Great work on the comprehensive edge case handling and documentation! 🎉


Files Reviewed:

  • ✅ lib/demo_scripts/gem_swapper.rb
  • ✅ spec/demo_scripts/gem_swapper_spec.rb
  • ✅ .swap-deps.yml.example
  • ✅ docs/LOCAL_DEVELOPMENT.md

Added concrete examples showing the difference between:
- Published gem versions
- GitHub main branch (default)
- GitHub custom branches (# syntax)
- GitHub tags (@ syntax)

These examples help developers understand how to use the GitHub
syntax when creating new demos with unreleased versions.

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

Co-Authored-By: Claude <[email protected]>
@claude
Copy link

claude bot commented Oct 9, 2025

Code Review - PR #43: Fix swap-deps to use correct Bundler syntax for Git tags

Summary

This PR correctly fixes the swap-deps tool to generate proper Bundler syntax for Git tags using tag: instead of branch:. The implementation is well-structured with comprehensive test coverage.


✅ Code Quality & Best Practices

Strengths:

  • Clean separation of concerns between ref_type logic
  • Comprehensive test coverage with 5 new test cases covering edge cases
  • Clear, self-documenting code with helpful comments
  • Follows existing RuboCop conventions
  • Good variable naming (ref_type, param_name, should_omit_ref)

Minor Suggestions:

  1. Naming inconsistency (lib/demo_scripts/gem_swapper.rb:171): The hash key :branch is used to store both branches AND tags. Consider renaming to :ref for clarity to make the intent clearer throughout the codebase.

  2. Display message clarity (lib/demo_scripts/gem_swapper.rb:79, 155, 158): The output messages still say "branch:" even when displaying a tag. Consider using dynamic labels based on ref_type.


🐛 Potential Issues

Critical: None identified. The core logic is sound.

Minor: Git command compatibility (lib/demo_scripts/gem_swapper.rb:178): When cloning with --branch, Git also accepts tags, so this works for both. However, the parameter name might be misleading when used with tags.


⚡ Performance Considerations

No performance concerns. The changes are logical operations with no additional I/O or computational overhead.


🔒 Security Considerations

Excellent work on input validation:

  • Line 128-129: Proper regex validation of branch/tag names prevents command injection
  • Line 123-125: Repo format validation prevents path traversal
  • Use of system() with array arguments prevents injection

All security measures from the original code are maintained. ✅


🧪 Test Coverage

Excellent test coverage:

  • ✅ Tag with ref_type: :tag → generates tag: parameter
  • ✅ Explicit ref_type: :branch → generates branch: parameter
  • ✅ Tag named "main" → still includes tag: (correct behavior)
  • ✅ Branch named "master" → omits branch: like "main"
  • ✅ All edge cases covered

Suggested additions:

  1. Test for pre-release tags (e.g., v16.1.0-rc.1)
  2. Integration test showing the full flow from CLI to Gemfile output

📝 Documentation

Strengths:

  • Excellent documentation updates in .new-demo-versions with clear examples
  • .swap-deps.yml.example provides comprehensive usage examples
  • docs/LOCAL_DEVELOPMENT.md correctly updated

Summary

This is a well-executed fix with:

  • ✅ Correct implementation of the core feature
  • ✅ Comprehensive test coverage
  • ✅ Proper security considerations
  • ✅ Good documentation
  • ⚠️ Minor naming/display improvements suggested but not blocking

Recommendation: Approve with minor suggestions for improved clarity. The code is production-ready as-is, but the naming suggestions would improve long-term maintainability.

Great work on this fix! 🎉

Updated the new-demo command to use the same GitHub reference syntax
as swap-deps for consistency:
- Use # for branches (e.g., github:org/repo#branch-name)
- Use @ for tags (e.g., github:org/[email protected])

Changes:
- Updated parse_github_spec to return [repo, ref, ref_type]
- Modified build_github_bundle_command to use --tag or --branch based on ref_type
- Updated bin/new-demo help text to show correct syntax
- Added comprehensive tests for both # (branch) and @ (tag) syntax
- Updated all existing tests to use new 3-element return value
- Updated demo creator to use correct Bundler parameters

This ensures consistent behavior between swap-deps and new-demo tools,
and generates correct Bundler syntax for both branches and tags.

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

Co-Authored-By: Claude <[email protected]>
@claude
Copy link

claude bot commented Oct 9, 2025

Pull Request Review

This PR fixes an important bug in the swap-deps tool to correctly use Bundler's tag: parameter for Git tags instead of incorrectly using branch:. The implementation is well-designed with comprehensive test coverage.

Strengths

Code Quality

  • Clear separation of concerns: The ref_type symbol provides excellent type safety
  • Comprehensive documentation with updated examples
  • Backward compatibility handled thoughtfully
  • Clean three-tuple return value [repo, ref, ref_type]

Test Coverage

  • Excellent coverage of all edge cases (tag syntax, branch syntax, special cases)
  • Well-structured RSpec tests following best practices

Best Practices

  • Clear error messages
  • Security: Good validation prevents path traversal and injection attacks
  • Consistent documentation updates

Minor Suggestions

  1. Variable Naming (lib/demo_scripts/gem_swapper.rb:291): The info[:branch] key is used for both branches and tags. Consider renaming to info[:ref] in future refactor for clarity.

  2. Comment Discrepancy (lib/demo_scripts/github_spec_parser.rb:15): Comment says @ returns :branch for backward compatibility, but line 23 returns :tag. Clarify the comment.

  3. Method Naming: validate_github_branch validates both branches AND tags. Consider renaming to validate_github_ref.

Assessment

Performance: No concerns - purely string parsing
Security: ✅ Excellent validation, no injection risks
Test Coverage: ✅ Comprehensive with all edge cases covered

Conclusion

High-quality PR with excellent test coverage. Minor suggestions above are for clarity and don't block merging.

Recommendation: ✅ Approve with minor suggestions

Great work fixing this Bundler syntax issue!


🤖 Review generated with Claude Code

Refactored DependencySwapper to use the shared GitHubSpecParser module
instead of duplicating GitHub spec parsing logic.

Benefits:
- Eliminates ~40 lines of duplicated parsing logic
- Ensures consistent behavior between swap-deps and new-demo
- Centralizes validation rules in one place
- Adds shell injection protection (validates against $, (), etc.)

Changes:
- Added `include GitHubSpecParser` to DependencySwapper
- Replaced inline parsing logic with parse_github_spec()
- Replaced regex validation with validate_github_repo() and validate_github_branch()
- Enhanced validate_github_branch() with final safety check for shell injection
- Updated test expectations to match new error messages

All 77 tests passing, including security validation for $(malicious) input.

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

Co-Authored-By: Claude <[email protected]>
@justin808
Copy link
Member Author

@claude review this pr

@claude
Copy link

claude bot commented Oct 9, 2025

Claude finished @justin808's task —— View job


Code Review for PR #43

I've completed a thorough review of the fix for swap-deps to use correct Bundler syntax for Git tags.

Todo List

  • Read core implementation files (gem_swapper.rb, github_spec_parser.rb)
  • Read test files to verify coverage
  • Review documentation changes
  • Analyze for bugs, security issues, and edge cases
  • Check previous review comments
  • Provide comprehensive review feedback

Summary

This PR successfully fixes issue #38 by correctly using tag: parameter for Git tags instead of branch: in Bundler gem declarations. The implementation is well-designed, thoroughly tested, and production-ready.

✅ Strengths

1. Excellent Implementation Quality

  • Clean separation of concerns: The ref_type symbol (:tag vs :branch) provides clear type safety throughout the codebase
  • Shared parsing logic: Uses GitHubSpecParser module for consistent parsing across both swap-deps and new-demo tools
  • Proper edge case handling: Correctly handles the important distinction that tags named "main"/"master" must be explicit, while branches "main"/"master" can be omitted (lib/demo_scripts/gem_swapper.rb:278-280)

2. Comprehensive Test Coverage

The test suite is exemplary with 8 new test cases covering all scenarios:

  • Basic tag syntax (spec/demo_scripts/gem_swapper_spec.rb:169-177)
  • Explicit branch ref_type (spec/demo_scripts/gem_swapper_spec.rb:179-187)
  • Edge case: tag named "main" (spec/demo_scripts/gem_swapper_spec.rb:189-197)
  • Edge case: master branch default (spec/demo_scripts/gem_swapper_spec.rb:199-207)
  • Plus comprehensive tests in github_spec_parser_spec.rb

3. Clear Documentation

  • Updated .swap-deps.yml.example with concrete examples showing exact Bundler syntax generated (lines 35-56)
  • Clear comments distinguishing # for branches vs @ for tags
  • Updated docs/LOCAL_DEVELOPMENT.md to clarify the syntax differences (lines 143-145)

4. Security & Validation

  • Proper input validation in validate_github_branch prevents command injection (lib/demo_scripts/github_spec_parser.rb:52-73)
  • Regex validation ensures only safe characters: \A[\w.\-/]+\z
  • Uses array form for git commands to avoid shell injection (lib/demo_scripts/gem_swapper.rb:171)

📋 Code Quality Observations

Positive

  1. Type safety: The ref_type field provides excellent clarity about whether a ref is a tag or branch
  2. DRY principle: Eliminates code duplication by using shared GitHubSpecParser (commit 722579b)
  3. Backward compatibility: Defaults to :branch when ref_type is not specified (lib/demo_scripts/gem_swapper.rb:275)
  4. Consistent behavior: Both swap-deps and new-demo now use the same GitHub spec syntax

Minor Naming Consideration

The hash key info[:branch] is used to store both branches AND tags throughout the codebase (e.g., lib/demo_scripts/gem_swapper.rb:107, 114, 280, 284). While this works correctly, the name could be slightly misleading. Consider renaming to info[:ref] in a future refactor for improved clarity. Not blocking - this is purely a documentation/clarity improvement.

🔍 Edge Cases & Correctness

✅ Properly Handled

  1. Tag named "main": Correctly includes tag: 'main' (test at line 189-197)
  2. Master branch: Correctly omits branch: parameter for master branch (test at line 199-207)
  3. Pre-release tags: Documentation includes example like v16.1.0-rc.1
  4. Branch with slashes: Validated in tests (spec/demo_scripts/gem_swapper_spec.rb:317-324)

Implementation Correctness

The logic at lib/demo_scripts/gem_swapper.rb:274-284 is correct:

ref_type = info[:ref_type] || :branch
param_name = ref_type == :tag ? 'tag' : 'branch'
should_omit_ref = ref_type == :branch && %w[main master].include?(info[:branch])

This ensures:

  • Tags always use tag: parameter
  • Branches use branch: parameter
  • Only branches named 'main'/'master' are omitted (tags with these names are kept explicit)

🔒 Security Assessment

No security concerns. The implementation maintains all existing security measures:

  • Input validation with safe regex patterns
  • Array form for system commands (prevents shell injection)
  • Path traversal prevention in repo validation

⚡ Performance

No performance impact. The changes add minimal conditional logic (one ternary operator) with negligible overhead.

📝 Documentation Quality

Excellent. The documentation changes are clear and include:

  • Concrete examples in .swap-deps.yml.example
  • Explanation of syntax differences in LOCAL_DEVELOPMENT.md
  • Code comments explaining the logic

🎯 Previous Review Comments

I reviewed the previous comments from CodeRabbit and Copilot. All significant issues have been addressed:

  • ✅ CodeRabbit's edge case concern about tags named 'main' - Fixed in commit 5a2a88f
  • ✅ Test coverage suggestions - Addressed with comprehensive tests
  • ✅ Documentation requests - Well-documented

Final Verdict

✅ APPROVED - Ready to Merge

This is a high-quality PR that:

  • ✅ Correctly fixes the stated problem
  • ✅ Has comprehensive test coverage with all edge cases
  • ✅ Follows Ruby and project conventions
  • ✅ Maintains backward compatibility
  • ✅ Has no security or performance concerns
  • ✅ Includes excellent documentation
  • ✅ Addresses all previous review feedback

The code is production-ready and can be merged with confidence. Great work! 🎉


Job Run | Branch: justin808/fix-git-tag-syntax

@claude
Copy link

claude bot commented Oct 9, 2025

PR Review: Fix swap-deps to use correct Bundler syntax for Git tags

Summary

This PR fixes an important bug in the swap-deps tool where Git tags were incorrectly using the branch: parameter instead of tag: in Bundler syntax. The implementation is well-tested and follows good practices.

Code Quality and Best Practices

Strengths:

  • Clear separation of concerns: The GitHubSpecParser module is properly shared between DemoCreator and DependencySwapper
  • Comprehensive documentation: Excellent inline comments and examples in .swap-deps.yml.example
  • Consistent API: The three-tuple return value [repo, ref, ref_type] is used consistently
  • Backward compatibility maintained with @ syntax now meaning tags

Recommendations:

  1. Method complexity at lib/demo_scripts/gem_swapper.rb:96-127 could be reduced by extracting string-to-hash conversion
  2. The hash key :branch is used for both branches and tags, consider renaming to :ref for clarity

Potential Issues

Minor issues identified:

  1. Backward compatibility: The @ syntax now means tags, which could break configs using @ for branches. Consider deprecation warning.
  2. Validation at lib/demo_scripts/github_spec_parser.rb:68-71 has redundant safety check

Performance

No performance concerns. Changes are logic improvements with no performance impact.

Security

Excellent security practices:

  • Comprehensive input validation for repo names and refs
  • Git ref naming rules properly enforced
  • Shellwords.join used for command construction prevents injection
  • Final safety regex check for unsafe characters

Test Coverage

Excellent test coverage with 53 new test lines:

  • New test for tag syntax at spec/demo_scripts/gem_swapper_spec.rb:169-176
  • Tests for both # and @ syntax parsing
  • Tests for edge cases and master branch omission
  • Tests for tag named main

Suggestions: Add integration test for full workflow and actual bundle add command generation.

Overall Assessment

Rating: Excellent

This well-crafted PR fixes a real bug, adds comprehensive test coverage, improves code reusability, and includes excellent documentation. The code quality is high, security practices are solid, and test coverage is thorough.

Recommendation: Approve and merge


Review by Claude Code

@justin808 justin808 requested a review from Copilot October 9, 2025 04:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.


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

# org/repo -> [org/repo, nil, nil]
# org/repo#branch -> [org/repo, branch, :branch]
# org/repo@tag -> [org/repo, tag, :tag]
# org/repo@branch -> [org/repo, branch, :branch] (backward compatibility)
Copy link

Copilot AI Oct 9, 2025

Choose a reason for hiding this comment

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

The documentation comment indicates org/repo@branch returns :branch for backward compatibility, but the actual implementation on line 23 returns :tag. This inconsistency between documentation and implementation could confuse users.

Copilot uses AI. Check for mistakes.
@justin808 justin808 merged commit 4486036 into main Oct 9, 2025
2 checks passed
@justin808 justin808 deleted the justin808/fix-git-tag-syntax branch October 9, 2025 04: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.

Bug: swap-deps generates incorrect Bundler syntax for Git tags

2 participants