pull_request_templates 0.1.0 โ†’ 0.3.0.pre.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db0cf51f3a6b4c2d45d07e740fb3e2bcac4f3b1f88fd4307adbb06ab0b53a941
4
- data.tar.gz: 2c67e9cce44dccdd94a59f8483fa87165a407bd9f6c378ca26866573c240657a
3
+ metadata.gz: 9038ada19f6b753fe0c7bdde625a38ddf76aa4b91a64dd0761b55223e0d04c6e
4
+ data.tar.gz: 7ed0febfb2172bb9b65f79a205f3d2685c3846e876a91cdb1f59233b7e00758c
5
5
  SHA512:
6
- metadata.gz: 1fa8d5796afaeb1a187cba4025f11edbaacdfdd685636717aa243acb86f7e5d9fc6b74eb810f91384c2e54ff4a9536eaa7ce0407ac9a26fe28f77609df024359
7
- data.tar.gz: 6ae32df0357873efb44def8080b7478bee857e6f24f7485a9e915260b401053c06cbf61a3f03cd33271ff4523d0066de7a7b29608bfeb69aabd98f912666840b
6
+ metadata.gz: 1a6526cd5bfb2dbb0d5f9f46c3d7baf9ac3f1b5b5d0448f2c757077caaa8d3ada57348d3249a288d0be088c77213a3d0532b30e947c5b33603ad1a44191e8bad
7
+ data.tar.gz: ed7973df8bc2125fd0b29600a102378c52b94d2f7bb66a6e9d321f64a4cb3b50db93603a36e950ba6cd853cd9d4a2f4627aa706462058e61fbcaab2131b3b34d
@@ -0,0 +1,59 @@
1
+ ---
2
+ description:
3
+ globs: *_spec.rb
4
+ alwaysApply: false
5
+ ---
6
+ # TDD Workflow Rule
7
+
8
+ ## Core Priorities
9
+ 1. Always write a failing test before implementing behavior
10
+ 2. Automatically implement changes when test failures match expectations
11
+
12
+ ## Workflow Steps
13
+
14
+ 1. **Write Test**
15
+ - Write a minimal test to demonstrate missing behavior
16
+ - Include specific error message expectations
17
+ - Follow RSpec best practices
18
+
19
+ 2. **Verify Test Failure**
20
+ - Run the specific failing test
21
+ - If the failure matches expectations, proceed to implementation
22
+ - If the failure is unexpected, revise the test
23
+
24
+ 3. **Commit the Failing Test**
25
+ - Commit the failing test separately from the implementation
26
+ - Use conventional commits with gitmoji
27
+ - Format: `๐Ÿงช test(scope): description` for tests
28
+ - Include a `Co-authored-by:` trailer if AI contributed
29
+
30
+ 4. **Implement Behavior**
31
+ - Write minimal code to pass the test
32
+ - Follow Ruby best practices
33
+ - Maintain existing code style
34
+
35
+ 5. **Commit the Implementation**
36
+ - Commit the implementation separately from the test
37
+ - Use conventional commits with gitmoji
38
+ - Format: `โœจ feat(scope): description` for implementation
39
+ - Include a `Co-authored-by:` trailer if AI contributed
40
+
41
+ 6. **Review Confidence**
42
+ - The goal is to build confidence in the process so that you can review the changes in a PR rather than accepting every change in the agent session
43
+ - If you get stuck, you are encouraged to ask for help, but strict adherence to the process is required
44
+
45
+ ## Gitmoji Reference
46
+ - ๐Ÿงช for failing test commits
47
+ - โœจ for feature implementations
48
+ - โ™ป๏ธ for refactoring
49
+ - ๐Ÿ› for bug fixes
50
+ - ๐Ÿ”ง for configuration changes
51
+ - ๐Ÿšš for renaming or moving
52
+ - ๐Ÿ—๏ธ for architectural changes
53
+
54
+ ## Notes
55
+ - Keep tests focused and atomic
56
+ - One behavior per test
57
+ - Maintain test isolation
58
+ - Follow red-green-refactor cycle strictly
59
+ - Always attribute AI contributions in commit messages
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.0] - 2024-06-11
4
+
5
+ - Added support for multiple templates via `.mapping.yml` configuration
6
+ - Implemented MECE template selection based on changed files
7
+ - Improved error handling for ambiguous template selection
8
+ - Clarified YAML parsing issues with examples in tests and README
9
+
3
10
  ## [0.1.0] - 2025-04-11
4
11
 
5
12
  - Initial release
data/README.md CHANGED
@@ -12,6 +12,80 @@ PullRequestTemplates helps teams by:
12
12
 
13
13
  Works seamlessly both in local development and GitHub Actions workflows.
14
14
 
15
+ ## Installation
16
+
17
+ Install the gem and add to the application's Gemfile by executing:
18
+
19
+ ```bash
20
+ bundle add pull_request_templates
21
+ ```
22
+
23
+ If bundler is not being used to manage dependencies, install the gem by executing:
24
+
25
+ ```bash
26
+ gem install pull_request_templates
27
+ ```
28
+
29
+ ## Configuration
30
+
31
+ To support multiple templates and automatically select the right one based on changed files, add a `.mapping.yml` file to your template directory:
32
+
33
+ ```yaml
34
+ # .github/PULL_REQUEST_TEMPLATE/.mapping.yml
35
+ feature.md:
36
+ - "**/feature*.txt"
37
+ bug_fix.md:
38
+ - "**/fix*.txt"
39
+ ```
40
+
41
+ - Each key is a template filename.
42
+ - Each value is a list of glob patterns (quoted for YAML compatibility).
43
+ - The tool will select the template whose patterns match all changed files (MECE logic).
44
+ - If more than one template matches, you'll get an error listing the ambiguous templates and files.
45
+
46
+ ## Usage
47
+
48
+ > **Note:** This is pre-release software. Currently, it only works with a single template in the pull request template directory.
49
+
50
+ ### Setting Up Templates
51
+
52
+ Place your PR templates in the `.github/PULL_REQUEST_TEMPLATE/` directory. For example:
53
+
54
+ ```
55
+ .github/
56
+ โ””โ”€โ”€ PULL_REQUEST_TEMPLATE/
57
+ โ”œโ”€โ”€ feature.md
58
+ โ”œโ”€โ”€ bug_fix.md
59
+ โ””โ”€โ”€ .mapping.yml
60
+ ```
61
+
62
+ The `.mapping.yml` file should define which templates apply to which files:
63
+
64
+ ```yaml
65
+ # .github/PULL_REQUEST_TEMPLATE/.mapping.yml
66
+ feature.md:
67
+ - "**/feature*.txt"
68
+ bug_fix.md:
69
+ - "**/fix*.txt"
70
+ ```
71
+
72
+ This setup allows the tool to automatically select the appropriate template based on your changes.
73
+
74
+ ### Creating a Pull Request
75
+
76
+ When you're ready to create a pull request:
77
+
78
+ ```bash
79
+ pull_request_templates pr-url
80
+ ```
81
+
82
+ This command:
83
+ - Selects an appropriate template based on your changes
84
+ - Generates a GitHub PR URL with the template parameter
85
+ - Outputs the URL to your terminal
86
+
87
+ Open the URL in your browser to create a pull request with the template pre-applied.
88
+
15
89
  ## Development
16
90
 
17
91
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,3 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require "bundler/setup"
3
4
  require "pull_request_templates"
5
+
6
+ PullRequestTemplates::Cli.start(ARGV)
data/lefthook.yml ADDED
@@ -0,0 +1,7 @@
1
+ pre-commit:
2
+ parallel: true
3
+ commands:
4
+ standardrb:
5
+ glob: "*.{rb,rake,gemspec}"
6
+ run: bundle exec standardrb --fix {staged_files}
7
+ stage_fixed: true
@@ -0,0 +1,125 @@
1
+ require "thor"
2
+ require "yaml"
3
+ require "pathname"
4
+
5
+ module PullRequestTemplates
6
+ class Cli < Thor
7
+ # Set exit_on_failure to ensure Thor exits with non-zero status on errors
8
+ def self.exit_on_failure? = true
9
+
10
+ desc "pr-url", "Generate a pull request URL based on changes"
11
+ def pr_url
12
+ # Find all available templates
13
+ templates = get_available_templates
14
+
15
+ if templates.empty?
16
+ raise Thor::Error, "No templates found"
17
+ end
18
+
19
+ # Check if we're on the default branch
20
+ current_branch = `git rev-parse --abbrev-ref HEAD`.strip
21
+
22
+ if current_branch == "main"
23
+ raise Thor::Error, "Cannot generate PR URL while on default branch"
24
+ end
25
+
26
+ # Check if there are any changes to detect
27
+ changes = get_changes
28
+
29
+ if changes.empty?
30
+ raise Thor::Error, "No changes detected"
31
+ end
32
+
33
+ # Select appropriate template
34
+ template = select_template(templates, changes)
35
+
36
+ # Generate the pull request URL
37
+ url = generate_pr_url(current_branch, template)
38
+ say url
39
+ end
40
+
41
+ private
42
+
43
+ def get_available_templates
44
+ template_dir = ".github/PULL_REQUEST_TEMPLATE"
45
+ Dir.glob("#{template_dir}/*.md").map { |path| File.basename(path) }
46
+ end
47
+
48
+ def get_changes
49
+ # Get changes between current branch and main branch
50
+ # Returns an array of changed file paths or an empty array if no changes
51
+ changes = `git diff --name-only main...HEAD`.strip
52
+ changes.split("\n").reject(&:empty?)
53
+ end
54
+
55
+ def select_template(template_files, changes)
56
+ mapping_file = ".github/PULL_REQUEST_TEMPLATE/config.yml"
57
+ candidates = []
58
+ if File.exist?(mapping_file)
59
+ templates = YAML.load_file(mapping_file).fetch("templates")
60
+ matches = Hash.new { |h, k| h[k] = [] }
61
+ changes.each do |file|
62
+ templates.each do |template|
63
+ patterns = template.fetch("pattern")
64
+ Array(patterns).each do |pattern|
65
+ matches[template] << file if File.fnmatch(pattern, file, File::FNM_PATHNAME | File::FNM_EXTGLOB)
66
+ end
67
+ end
68
+ end
69
+ selected = matches.select { |_, files| files.sort == changes.sort }
70
+ candidates = selected.keys if selected.any?
71
+ end
72
+ candidates = template_files.map { {"file" => _1} } if candidates.empty?
73
+
74
+ # If we have a default template with catch-all pattern, use it when multiple templates match
75
+ if candidates.length > 1
76
+ fallback = candidates.find { _1.fetch("fallback", false) }
77
+ return fallback.fetch("file") if fallback
78
+ end
79
+
80
+ if candidates.length == 1
81
+ return candidates.first.fetch("file")
82
+ end
83
+
84
+ if File.exist?(mapping_file)
85
+ raise AmbiguousTemplateSelection, <<~MESSAGE
86
+ Unable to pick one template from #{candidates.map { _1.fetch("file") }} for the changes to #{changes.count} files:
87
+ * #{changes.join("\n* ")}
88
+
89
+ To resolve this, add a fallback template to your config.yml:
90
+ - file: default.md
91
+ pattern: "**"
92
+ fallback: true
93
+ MESSAGE
94
+ else
95
+ raise AmbiguousTemplateSelection, <<~MESSAGE
96
+ Unable to pick one template from #{candidates.map { _1.fetch("file") }} for the changes to #{changes.count} files:
97
+ * #{changes.join("\n* ")}
98
+
99
+ To resolve this, add a fallback template to your config.yml:
100
+ - file: default.md
101
+ pattern: "**"
102
+ fallback: true
103
+
104
+ Run this command to create the fallback template:
105
+ echo 'templates:
106
+ - file: default.md
107
+ pattern: "**"
108
+ fallback: true
109
+ ' >> .github/PULL_REQUEST_TEMPLATE/config.yml
110
+ MESSAGE
111
+ end
112
+ end
113
+
114
+ def generate_pr_url(branch, template)
115
+ # Get the repository URL from git config
116
+ remote_url = `git config --get remote.origin.url`.strip
117
+
118
+ # Extract repository path from SSH URL format (git@github.com:user/repo.git)
119
+ repo_path = remote_url.sub(/^git@github\.com:/, "").sub(/\.git$/, "")
120
+
121
+ # Generate GitHub pull request URL with template parameter
122
+ "https://github.com/#{repo_path}/compare/#{branch}?expand=1&quick_pull=1&template=#{template}"
123
+ end
124
+ end
125
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PullRequestTemplates
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0.pre.2"
5
5
  end
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "pull_request_templates/version"
4
+ require_relative "pull_request_templates/cli"
5
+
6
+ require "thor/error"
4
7
 
5
8
  module PullRequestTemplates
6
- class Error < StandardError; end
7
- # Your code goes here...
9
+ Error = Class.new(StandardError)
10
+ CliError = Class.new(Thor::Error)
11
+ AmbiguousTemplateSelection = Class.new(CliError)
8
12
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pull_request_templates
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0.pre.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Caleb Buxton
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-04-11 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2025-06-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
13
27
  description: A tool that reduces pull request description toil and provides the right
14
28
  context for changes.
15
29
  email:
@@ -19,6 +33,7 @@ executables:
19
33
  extensions: []
20
34
  extra_rdoc_files: []
21
35
  files:
36
+ - ".cursor/rules/test-driven-developer.mdc"
22
37
  - ".rspec"
23
38
  - ".standard.yml"
24
39
  - CHANGELOG.md
@@ -27,9 +42,10 @@ files:
27
42
  - README.md
28
43
  - Rakefile
29
44
  - exe/pull_request_templates
45
+ - lefthook.yml
30
46
  - lib/pull_request_templates.rb
47
+ - lib/pull_request_templates/cli.rb
31
48
  - lib/pull_request_templates/version.rb
32
- - sig/pull_request_templates.rbs
33
49
  homepage: https://github.com/cpb/pull_request_templates
34
50
  licenses:
35
51
  - MIT
@@ -52,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
68
  - !ruby/object:Gem::Version
53
69
  version: '0'
54
70
  requirements: []
55
- rubygems_version: 3.4.19
71
+ rubygems_version: 3.5.22
56
72
  signing_key:
57
73
  specification_version: 4
58
74
  summary: Match pull request templates to your changes.
@@ -1,4 +0,0 @@
1
- module PullRequestTemplates
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end