pr-with-params 1.3.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e73e0d7cdcfe3e16d632105a2a54564b94e04b0fe523a7faa3449e11e6ad7edb
4
- data.tar.gz: 3260ff8eec71435baf10bbce8ba8633b37077e8d8e26dad28c6ee729a23e6783
3
+ metadata.gz: fb5d7b7436528a5a08568892974cc238bd5ffc1dd6fb40e2157be5600b72dd04
4
+ data.tar.gz: 8904c400e3fc49e1ac68f1434279af3d2b2a92f8c39fddc0b0b4b35c825d3b5f
5
5
  SHA512:
6
- metadata.gz: 4039bc9e0d935d8355899f6b71c34b958d7900c447e710c6fccfe12dea0e4172279207cd8bd559226da2e4e33c1cd90961f9d1221d21ddc2349a6748aae457e5
7
- data.tar.gz: 0ead5bf501b295bf8892600773872c9132a8857de609d78146636de50d4447cdf37e0ad746b0f81d765b4c2b5e859ece057d74d310defb3859decd6c85a2c3ed
6
+ metadata.gz: 00473d4b542df9d312c51f8e6801b2050109108780f914fe49cd5f5048493792d002ab3bfb5b992461644352612e9cfc2c70ff80d010fcfc32d71596d14f7379
7
+ data.tar.gz: 4b86fc3db6832b59830123dce6a2b1077b90fc312d28cd360bcc648a931692680c03059c218e7acd2d8da3ccdbc3886541dd98ee677ed699347d3a5d1d523fbe
data/.rubocop.yml CHANGED
@@ -1,3 +1,6 @@
1
+ # All Cops
2
+ AllCops:
3
+ TargetRubyVersion: 3.1.2
1
4
  # Style
2
5
  Style/StringLiterals:
3
6
  Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ ## [2.0.0] - 2023-06-05
2
+
3
+ To migrate to this version, simply run `gem update pr-with-params`
4
+
5
+ ### Added
6
+ - Ability to specify a list of validators to run as an option
7
+ - Ability to set `ignore_conventional_commits` in config file
8
+ - Default path for config file at `~/.pwp/config.yml`
9
+
10
+ ### Changed
11
+ - `--conf` is now `--config_path` or `-path` or `-p`
12
+ - Make specifying config path optional - was previously a required
13
+ - CLI name is now `pr-wip` - was previously `pr-with-params`
14
+ - `--validate-conventional-commits` is now `--ignore-conventional-commits` - optionally turn off versus optionally turn on
15
+
16
+ ### Fixed
17
+ - Occasional failures related to `launchy` not being loaded properly
data/Gemfile CHANGED
@@ -4,8 +4,3 @@ source "https://rubygems.org"
4
4
 
5
5
  # Specify your gem's dependencies in pr-with-params.gemspec
6
6
  gemspec
7
-
8
- gem "rake", "~> 13.0"
9
- gem "minitest", "~> 5.0"
10
- gem "rubocop", "~> 0.80"
11
- gem "launchy"
data/Gemfile.lock CHANGED
@@ -1,21 +1,33 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pr-with-params (1.3.0)
4
+ pr-with-params (2.0.0)
5
+ activesupport
6
+ launchy (~> 2.5)
7
+ rake (~> 13.0)
8
+ thor
5
9
 
6
10
  GEM
7
11
  remote: https://rubygems.org/
8
12
  specs:
9
- addressable (2.8.0)
10
- public_suffix (>= 2.0.2, < 5.0)
13
+ activesupport (7.0.5)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 1.6, < 2)
16
+ minitest (>= 5.1)
17
+ tzinfo (~> 2.0)
18
+ addressable (2.8.4)
19
+ public_suffix (>= 2.0.2, < 6.0)
11
20
  ast (2.4.2)
12
- launchy (2.5.0)
13
- addressable (~> 2.7)
14
- minitest (5.16.2)
21
+ concurrent-ruby (1.2.2)
22
+ i18n (1.14.1)
23
+ concurrent-ruby (~> 1.0)
24
+ launchy (2.5.2)
25
+ addressable (~> 2.8)
26
+ minitest (5.18.0)
15
27
  parallel (1.22.1)
16
28
  parser (3.1.2.0)
17
29
  ast (~> 2.4.1)
18
- public_suffix (4.0.7)
30
+ public_suffix (5.0.1)
19
31
  rainbow (3.1.1)
20
32
  rake (13.0.6)
21
33
  regexp_parser (2.5.0)
@@ -32,16 +44,18 @@ GEM
32
44
  rubocop-ast (1.19.1)
33
45
  parser (>= 3.1.1.0)
34
46
  ruby-progressbar (1.11.0)
47
+ thor (1.2.2)
48
+ tzinfo (2.0.6)
49
+ concurrent-ruby (~> 1.0)
35
50
  unicode-display_width (1.8.0)
36
51
 
37
52
  PLATFORMS
38
53
  arm64-darwin-21
54
+ arm64-darwin-22
39
55
 
40
56
  DEPENDENCIES
41
- launchy
42
- minitest (~> 5.0)
57
+ minitest (~> 5.18.0)
43
58
  pr-with-params!
44
- rake (~> 13.0)
45
59
  rubocop (~> 0.80)
46
60
 
47
61
  BUNDLED WITH
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
- # PR::With::Params [![Gem Version](https://badge.fury.io/rb/pr-with-params.svg)](https://badge.fury.io/rb/pr-with-params)
2
- A lightweight gem that pushes current local branch to remote with upstream at origin/[local-branch-name]. It also opens a new pull request browser window at a URL with customized query params, based on specified options, which pre-populates certain fields in the pull request. This is especially useful when supporting multiple PR templates within a code base.
1
+ # PRWithParams [![Gem Version](https://badge.fury.io/rb/pr-with-params.svg)](https://badge.fury.io/rb/pr-with-params)
2
+ A lightweight ruby gem that pushes current local branch to remote with upstream at origin/[local-branch-name]. It also opens a new pull request browser window at a URL with customized query params, based on specified options, which pre-populates certain fields in the pull request. This is especially useful when supporting multiple PR templates within a code base.
3
3
 
4
4
  Inspired by GitHub's documentation on [using query params to create pull requets](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/using-query-parameters-to-create-a-pull-request)
5
5
 
@@ -21,13 +21,15 @@ Or install it yourself as:
21
21
 
22
22
  ## Usage
23
23
 
24
+ NOTE: CLI name has changed as of v2.0.0 from `pr-with-params` to `pr-wip` along with some other breaking changes. See changelog for more details
25
+
24
26
  Assuming you've committed your changes and your local branch is ready to be pushed, run:
25
27
 
26
28
  ```
27
- $ pr-with-params -t new_feature_template.md -l 'work in progress'
29
+ $ pr-wip -t new_feature_template.md -l 'work in progress'
28
30
  ```
29
31
 
30
- For a full list of options, run `$ pr-with-params -h`
32
+ For a full list of options, run `$ pr-wip -h`
31
33
 
32
34
  #### Using Config File
33
35
 
@@ -46,8 +48,8 @@ bug_fix:
46
48
  labels: bug,urgent
47
49
  ```
48
50
 
49
- * To run with config file, use `$ pr-with-params --conf='path/to/file.yml' --scope=bug_fix`. If `--scope` option is not specified, only `:default` scope will apply.
50
- * If you specify a config file (`--conf`) and also pass options by flag (e.g `--base-branch=develop`), the flag value will override the config value.
51
+ * To run with config file, use `$ pr-wip --config_path='path/to/file.yml' --scope=bug_fix`. If `--scope` option is not specified, only `:default` scope will apply.
52
+ * If you specify a config file (`--config_path`) and also pass options by flag (e.g `--base-branch=develop`), the flag value will override the config value.
51
53
  * All your defaults go in the `:default` scope.
52
54
  * Only fields defined in another scope will override the defaults. In the example above, the final list of configs will be:
53
55
 
@@ -59,6 +61,7 @@ bug_fix:
59
61
  | Config | Type | Example |
60
62
  | :--- | :---: | :--- |
61
63
  | validators | `Array` | \`[conventional_commits]\` |
64
+ | ignore_conventional_commits | `Boolean` | true |
62
65
  | base_branch | `String` | develop |
63
66
  | template | `String` | new_feature_template.md |
64
67
  | title | `String` | 'Update login screen' |
@@ -66,7 +69,7 @@ bug_fix:
66
69
  | assignees | `String` | 2k-joker |
67
70
 
68
71
  #### Validators
69
- * **Conventional Commits**: Gem supports validation of conventional commits for PR `:title`. If you want to follow [conventional commit specs](https://www.conventionalcommits.org/en/v1.0.0/#specification) in your codebase, you may want to use this validation. To turn it on, set the `--validate-conventional-commits` flag or add `conventional_commits` to the list of validators in your config file.
72
+ * **Conventional Commits**: Gem supports validation of conventional commits for PR `:title` by default. This is to encourage users to follow [conventional commit specs](https://www.conventionalcommits.org/en/v1.0.0/#specification). To turn it off, pass the `--ignore-conventional-commits` flag or add `conventional_commits` to the list of validators in your config file or set `ignore_conventional_commits: true` in your config file.
70
73
 
71
74
  ## Development
72
75
 
data/bin/console CHANGED
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "bundler/setup"
5
- require "pr/with/params"
5
+ require "pr_with_params"
6
6
 
7
7
  # You can add fixtures and/or initialization code here to make experimenting
8
8
  # with your gem easier. You can also use a different console, if you like.
data/bin/setup CHANGED
@@ -4,5 +4,5 @@ IFS=$'\n\t'
4
4
  set -vx
5
5
 
6
6
  bundle install
7
-
7
+ Bundler.require(:default, :development)
8
8
  # Do any other automated setup that you need to do here
data/exe/pr-wip ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup' # support local testing/development
4
+ require_relative '../lib/pr_with_params'
5
+
6
+ PRWithParams::CLI.start
@@ -0,0 +1,77 @@
1
+ require 'active_support/core_ext/hash'
2
+ require 'thor'
3
+ require 'launchy'
4
+ require 'uri'
5
+
6
+ module PRWithParams
7
+ class CLI < Thor
8
+ desc "open", "Open a new pull request for local branch"
9
+ long_desc <<-LONGDESC
10
+ `pr-wip open [options]` will open a new browser window with a pull request at a URL with customized query params from <options>.
11
+
12
+ The pull request will be pre-populated with certain fields based on custom query params
13
+ LONGDESC
14
+ option :template, type: :string, aliases: ['-t'], desc: 'Specify the filename of the target custom PR template (e.g: bug_squash_template.md). Will use default template otherwise.'
15
+ option :config_path, type: :string, aliases: ['-path', '-p'], default: '/.pwp/config.yml', desc: 'Path to yaml file where configs are defined. Defaults to: ~/.pwp/config.yml'
16
+ option :scope, type: :string, aliases: ['-s'], default: 'default', desc: 'Specify the scope name under which options are defined.'
17
+ option :base_branch, type: :string, aliases: ['-b'], desc: 'Specify the base branch for your PR (e.g: develop). Will use default branch otherwise.'
18
+ option :title, type: :string, aliases: ['-d', '-desc', '--description'], desc: 'Specify a custom PR title. Will use the first branch commit message otherwise.'
19
+ option :labels, type: :string, aliases: ['-l'], desc: "Specify a list of labels (e.g: 'help+wanted,bug,urgent,work+in+progress')."
20
+ option :assignees, type: :string, aliases: ['-a'], desc: "Specify a list of assignees (e.g: 'octocat,codedog')."
21
+ option :validators, type: :array, default: [:conventional_commits], desc: 'Specify a list of validations to run against local branch before opening pull request'
22
+ option :ignore_conventional_commits, type: :boolean, desc: 'Allow PR titles that do not conform to conventional commits spec.'
23
+ def open
24
+ home_dir_path = `echo $HOME`.chomp
25
+ config_file_path = "#{home_dir_path}/#{options[:config_path].delete_prefix('/')}"
26
+ config_options = (options[:config_path].empty? ? {} : PRWithParams::ConfigParser.new(config_file_path: config_file_path, scope: options[:scope]).parse!).with_indifferent_access
27
+ options[:validators].delete(:conventional_commits) if options[:ignore_conventional_commits]
28
+ all_options = config_options.merge(options)
29
+
30
+ branch_name = `git rev-parse --abbrev-ref HEAD`.chomp
31
+ base_branch = all_options.delete(:base_branch) || `git remote show origin | grep "HEAD branch" | sed 's/.*: //'`.chomp
32
+
33
+ default_title = `git show-branch --no-name $(git log #{base_branch}..#{branch_name} --pretty=format:"%h" | tail -1)`.chomp
34
+ all_options[:title] ||= default_title
35
+
36
+ puts all_options
37
+ puts options
38
+ PRWithParams::OptionsValidator.validate!(all_options.except(:validators), validators: all_options[:validators])
39
+
40
+ remote_git_uri = `git config --get remote.origin.url`.sub('git@github.com:', '').sub('.git', '').chomp
41
+ uri_path = "/#{remote_git_uri}/compare/#{base_branch}...#{branch_name}"
42
+
43
+ push_local_to_remote(branch_name, base_branch, remote_git_uri)
44
+ open_pr_in_browser(uri_path, all_options)
45
+ rescue StandardError => e
46
+ message = "\e[31mERROR\e[0m: An error occurred while building or opening your custom pull request URL"
47
+ reason = "reason: #{e.message}"
48
+ backtrace = "backtrace: #{e.backtrace&.last(10)&.join("\n")}"
49
+ error_message = [message, reason, backtrace, "\n\n"].join("\n")
50
+
51
+ warn error_message
52
+ exit 1
53
+ end
54
+
55
+ private
56
+
57
+ def push_local_to_remote(branch_name, base_branch, remote_git_uri)
58
+ puts "current branch: \e[36m#{branch_name}\e[0m"
59
+ puts "base branch: \e[36m#{base_branch}\e[0m"
60
+ puts "repo path: \e[36m#{remote_git_uri}\e[0m"
61
+
62
+ push_message = "\nPushing your local branch to origin/#{branch_name}..."
63
+ puts "\e[32m#{push_message}\e[0m"
64
+ `sleep 1`
65
+
66
+ system("git push -u origin #{branch_name}", exception: true)
67
+ end
68
+
69
+ def open_pr_in_browser(uri_path, options)
70
+ uri_host = 'www.github.com'
71
+ uri_query = URI.encode_www_form(options)
72
+ url_string = URI::HTTPS.build(host: uri_host, path: uri_path, query: uri_query).to_s
73
+
74
+ Launchy.open(url_string)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,51 @@
1
+ require 'yaml'
2
+
3
+ module PRWithParams
4
+ class ConfigParser
5
+ class ParserError < StandardError; end
6
+
7
+ # Attributes
8
+ attr_reader :config_file_path, :scope, :parsed_config, :filtered_config
9
+
10
+ # Constants
11
+ VALID_CONFIG_KEYS = %i[validators base_branch template title labels assignees].freeze
12
+
13
+ def initialize(config_file_path:, scope: nil)
14
+ @config_file_path = config_file_path
15
+ @scope = scope&.to_sym || :default
16
+ end
17
+
18
+ def parse!
19
+ validate_file_type!
20
+ parse_yaml_config
21
+ end
22
+
23
+ private
24
+
25
+ def parse_yaml_config
26
+ @parsed_config = YAML.safe_load(IO.read(config_file_path)).to_h.transform_keys(&:to_sym)
27
+ @filtered_config = scoped_config.transform_keys(&:to_sym).slice(*VALID_CONFIG_KEYS)
28
+ end
29
+
30
+ def scoped_config
31
+ if scope == :default || parsed_config.fetch(scope, {}).empty?
32
+ parsed_config.fetch(:default, {})
33
+ else
34
+ parsed_config.fetch(:default, {}).merge(parsed_config[scope])
35
+ end
36
+ end
37
+
38
+ def validate_file_type!
39
+ raise ParserError, 'Config file type must be YAML (.yaml or .yml)' unless yaml_file?
40
+ raise ParserError, "Config file path is invalid or file does not exist: #{config_file_path}" unless file_exists?
41
+ end
42
+
43
+ def yaml_file?
44
+ config_file_path.end_with?('.yaml') || config_file_path.end_with?('yml')
45
+ end
46
+
47
+ def file_exists?
48
+ File.file?(config_file_path)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,44 @@
1
+ module PRWithParams
2
+ class OptionsValidator
3
+ class ValidatorError < StandardError; end
4
+
5
+ VALIDATOR_CLASS_MAP = {
6
+ conventional_commits: 'PRWithParams::ConventionalCommitValidator'
7
+ }.freeze
8
+
9
+ class << self
10
+ def validate!(options, validators: [])
11
+ validators.each do |validator|
12
+ validate_options(validator, options)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def validate_options(validator, options)
19
+ class_name = VALIDATOR_CLASS_MAP[validator.to_sym]
20
+ raise(ValidatorError, "Invalid or undefined validator: #{validator}") if class_name.nil?
21
+
22
+ Object.const_get(class_name).new(options).validate!
23
+ end
24
+ end
25
+ end
26
+
27
+ class ConventionalCommitValidator
28
+ CONVENTIONAL_COMMIT_REGEX = /^((build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\(.*\))?(!)?(: (.*\s*)*))|(^Merge (.*\s*)*)|(^Initial commit$)/.freeze
29
+
30
+ def initialize(options)
31
+ @commit_message = options[:title]
32
+ end
33
+
34
+ def validate!
35
+ raise OptionsValidator::ValidatorError, "Conventional commit specifications not met for commit message: '#{@commit_message}'" unless valid_commit?
36
+ end
37
+
38
+ private
39
+
40
+ def valid_commit?
41
+ CONVENTIONAL_COMMIT_REGEX.match?(@commit_message)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PRWithParams
4
+ VERSION = "2.0.0"
5
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'pr_with_params/config_parser'
2
+ require_relative 'pr_with_params/options_validator'
3
+ require_relative 'pr_with_params/version'
4
+ require_relative 'pr_with_params/cli'
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "lib/pr/with/params/version"
3
+ require_relative "lib/pr_with_params/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "pr-with-params"
7
- spec.version = PR::With::Params::VERSION
7
+ spec.version = PRWithParams::VERSION
8
8
  spec.authors = ["2k-joker"]
9
9
  spec.email = ["kum.vanjunior@gmail.com"]
10
10
 
11
11
  spec.summary = "Pushes current local branch to remote with upstream at origin/[local-branch-name]. It also opens a new pull request browser window at a URL with customized query params, based on specified options, which pre-populates certain fields in the pull request. This is especially useful when supporting multiple PR templates within a code base."
12
12
  spec.homepage = "https://github.com/2k-joker/pr-with-params"
13
13
  spec.licenses = ["MIT"]
14
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+ spec.required_ruby_version = Gem::Requirement.new("~> 3.1.0")
15
15
 
16
16
  spec.metadata["homepage_uri"] = spec.homepage
17
17
 
@@ -24,9 +24,11 @@ Gem::Specification.new do |spec|
24
24
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ["lib"]
26
26
 
27
- # Uncomment to register a new dependency of your gem
28
- # spec.add_dependency "example-gem", "~> 1.0"
27
+ spec.add_dependency "launchy", "~> 2.5"
28
+ spec.add_dependency "rake", "~> 13.0"
29
+ spec.add_dependency "thor"
30
+ spec.add_dependency "activesupport"
29
31
 
30
- # For more information and examples about making a new gem, checkout our
31
- # guide at: https://bundler.io/guides/creating_gem.html
32
+ spec.add_development_dependency "minitest", "~> 5.18.0"
33
+ spec.add_development_dependency "rubocop", "~> 0.80"
32
34
  end
metadata CHANGED
@@ -1,20 +1,104 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pr-with-params
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - 2k-joker
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-10 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-06-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: launchy
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 5.18.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 5.18.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.80'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.80'
13
97
  description:
14
98
  email:
15
99
  - kum.vanjunior@gmail.com
16
100
  executables:
17
- - pr-with-params
101
+ - pr-wip
18
102
  extensions: []
19
103
  extra_rdoc_files: []
20
104
  files:
@@ -22,6 +106,7 @@ files:
22
106
  - ".github/PULL_REQUEST_TEMPLATE/new_feature_template.md"
23
107
  - ".gitignore"
24
108
  - ".rubocop.yml"
109
+ - CHANGELOG.md
25
110
  - Gemfile
26
111
  - Gemfile.lock
27
112
  - LICENSE
@@ -29,11 +114,12 @@ files:
29
114
  - Rakefile
30
115
  - bin/console
31
116
  - bin/setup
32
- - exe/pr-with-params
33
- - lib/pr/with/params.rb
34
- - lib/pr/with/params/config_parser.rb
35
- - lib/pr/with/params/options_validator.rb
36
- - lib/pr/with/params/version.rb
117
+ - exe/pr-wip
118
+ - lib/pr_with_params.rb
119
+ - lib/pr_with_params/cli.rb
120
+ - lib/pr_with_params/config_parser.rb
121
+ - lib/pr_with_params/options_validator.rb
122
+ - lib/pr_with_params/version.rb
37
123
  - pr-with-params.gemspec
38
124
  homepage: https://github.com/2k-joker/pr-with-params
39
125
  licenses:
@@ -46,16 +132,16 @@ require_paths:
46
132
  - lib
47
133
  required_ruby_version: !ruby/object:Gem::Requirement
48
134
  requirements:
49
- - - ">="
135
+ - - "~>"
50
136
  - !ruby/object:Gem::Version
51
- version: 2.3.0
137
+ version: 3.1.0
52
138
  required_rubygems_version: !ruby/object:Gem::Requirement
53
139
  requirements:
54
140
  - - ">="
55
141
  - !ruby/object:Gem::Version
56
142
  version: '0'
57
143
  requirements: []
58
- rubygems_version: 3.2.3
144
+ rubygems_version: 3.3.26
59
145
  signing_key:
60
146
  specification_version: 4
61
147
  summary: Pushes current local branch to remote with upstream at origin/[local-branch-name].
data/exe/pr-with-params DELETED
@@ -1,100 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'bundler/setup' # support local testing/development
4
- require_relative '../lib/pr/with/params'
5
- require 'json'
6
- require 'optparse'
7
- require 'open3'
8
-
9
- options = { expand: 1, validators: [] }
10
- config_file_path = ''
11
- config_scope = nil
12
-
13
- # rubocop:disable Metrics/BlockLength
14
- parser = OptionParser.new do |opt|
15
- opt.banner = "Usage pr-with-params [options]"
16
-
17
- opt.separator ''
18
-
19
- opt.on('-h', '--help', 'Show this usage help menu') do |_h|
20
- puts opt
21
- exit
22
- end
23
-
24
- opt.separator ''
25
-
26
- opt.on('--conf FILE_PATH', 'Path to yaml file where options are defined. NOTE that relative paths are not supported.') do |conf_file|
27
- stdout, _stderr, _status = Open3.capture3("echo #{conf_file}")
28
- config_file_path = stdout.chomp
29
- end
30
-
31
- opt.on('--scope CONFIG_SCOPE', 'Specify the scope name under which options are defined.') do |scope|
32
- config_scope = scope
33
- end
34
-
35
- opt.on('--base-branch BRANCH', "Specify the base branch for your PR (e.g: 'develop'). Will use default branch otherwise.") do |pr_base_branch|
36
- options[:base_branch] = pr_base_branch
37
- end
38
-
39
- opt.on('-t', '--template TEMPLATE', "Specify the filename of the target custom PR template (e.g: 'bug_squash_template.md'). Will use default template otherwise.") do |pr_template|
40
- options[:template] = pr_template
41
- end
42
-
43
- opt.on('-d', '--description DESC', 'Specify a custom PR title. Will use the first branch commit message otherwise.') do |pr_description|
44
- options[:title] = pr_description
45
- end
46
-
47
- opt.on('-l', '--labels LABELS', "Specify a list of labels (e.g: 'help+wanted,bug,urgent,work+in+progress').") do |pr_labels|
48
- options[:labels] = pr_labels
49
- end
50
-
51
- opt.on('-a', '--assignees ASSIGNEES', "Specify a list of assignees (e.g: 'octocat,codedog').") do |pr_assignees|
52
- options[:assignees] = pr_assignees
53
- end
54
-
55
- opt.on('--validate-conventional-commits', 'Validates that your PR title conforms to conventional commits specs.') do |_|
56
- options[:validators] = options[:validators].to_a << :conventional_commits
57
- end
58
- end
59
- # rubocop:enable Metrics/BlockLength
60
-
61
- begin
62
- parser.parse!
63
-
64
- config_options = PR::With::Params.parse_config(config_file_path, config_scope)
65
- options = config_options.merge(options)
66
-
67
- branch_name = `git rev-parse --abbrev-ref HEAD`.chomp
68
- base_branch = options.delete(:base_branch) || `git remote show origin | grep "HEAD branch" | sed 's/.*: //'`.chomp
69
-
70
- default_title = `git show-branch --no-name $(git log #{base_branch}..#{branch_name} --pretty=format:"%h" | tail -1)`.chomp
71
- options[:title] ||= default_title
72
-
73
- PR::With::Params.validate_options(options)
74
-
75
- remote_git_uri = `git config --get remote.origin.url`.sub('git@github.com:', '').sub('.git', '').chomp
76
- uri_host = 'www.github.com'
77
- uri_path = "/#{remote_git_uri}/compare/#{base_branch}...#{branch_name}"
78
-
79
- puts "current branch: \e[36m#{branch_name}\e[0m"
80
- puts "base branch: \e[36m#{base_branch}\e[0m"
81
- puts "repo path: \e[36m#{remote_git_uri}\e[0m"
82
-
83
- push_message = "\nPushing your local branch to origin/#{branch_name}..."
84
- puts "\e[32m#{push_message}\e[0m"
85
- `sleep 1`
86
- system("git push -u origin #{branch_name}", exception: true)
87
-
88
- open_url_message = "\nOpening pull request browser window..."
89
- puts "\e[32m#{open_url_message}\e[0m"
90
- `sleep 1`
91
- PR::With::Params.open(host: uri_host, path: uri_path, query: options)
92
- rescue StandardError => e
93
- message = "\e[31mERROR\e[0m: An error occurred while building or opening your custom pull request URL"
94
- reason = "reason: #{e.message}"
95
- backtrace = "backtrace: #{e.backtrace&.last(10)&.join("\n")}"
96
- error_message = [message, reason, backtrace, "\n\n"].join("\n")
97
-
98
- warn error_message
99
- exit 1
100
- end
@@ -1,53 +0,0 @@
1
- require 'yaml'
2
-
3
- module PR
4
- module With
5
- module Params
6
- class ConfigParser
7
- # Attributes
8
- attr_reader :config_file_path, :scope, :parsed_config, :filtered_config
9
-
10
- # Constants
11
- VALID_CONFIG_KEYS = %i[validators base_branch template title labels assignees].freeze
12
-
13
- def initialize(config_file_path:, scope: nil)
14
- @config_file_path = config_file_path
15
- @scope = scope&.to_sym || :default
16
- end
17
-
18
- def parse!
19
- validate_file_type!
20
- parse_yaml_config
21
- end
22
-
23
- private
24
-
25
- def parse_yaml_config
26
- @parsed_config = YAML.safe_load(IO.read(config_file_path)).transform_keys(&:to_sym)
27
- @filtered_config = scoped_config.transform_keys(&:to_sym).slice(*VALID_CONFIG_KEYS)
28
- end
29
-
30
- def scoped_config
31
- if scope == :default || parsed_config.fetch(scope, {}).empty?
32
- parsed_config.fetch(:default, {})
33
- else
34
- parsed_config.fetch(:default, {}).merge(parsed_config[scope])
35
- end
36
- end
37
-
38
- def validate_file_type!
39
- raise(TypeError, 'Config file type must be YAML (.yaml or .yml)') unless yaml_file?
40
- raise(ArgumentError, "Config file path is invalid or file does not exist: #{config_file_path}") unless file_exists?
41
- end
42
-
43
- def yaml_file?
44
- config_file_path.end_with?('.yaml') || config_file_path.end_with?('yml')
45
- end
46
-
47
- def file_exists?
48
- File.file?(config_file_path)
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,46 +0,0 @@
1
- module PR
2
- module With
3
- module Params
4
- class OptionsValidator
5
- VALIDATOR_CLASS_MAP = {
6
- conventional_commits: 'PR::With::Params::ConventionalCommitValidator'
7
- }.freeze
8
-
9
- class << self
10
- def validate!(options, validators: [])
11
- validators.each do |validator|
12
- validate_options(validator, options)
13
- end
14
- end
15
-
16
- private
17
-
18
- def validate_options(validator, options)
19
- class_name = VALIDATOR_CLASS_MAP[validator.to_sym]
20
- raise(ArgumentError, "Invalid or undefined validator: #{validator}") if class_name.nil?
21
-
22
- Object.const_get(class_name).new(options).validate!
23
- end
24
- end
25
- end
26
-
27
- class ConventionalCommitValidator
28
- CONVENTIONAL_COMMIT_REGEX = /^((build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\(.*\))?(!)?(: (.*\s*)*))|(^Merge (.*\s*)*)|(^Initial commit$)/.freeze
29
-
30
- def initialize(options)
31
- @commit_message = options[:title]
32
- end
33
-
34
- def validate!
35
- raise("Conventional commit specifications not met for commit message: '#{@commit_message}'") unless valid_commit?
36
- end
37
-
38
- private
39
-
40
- def valid_commit?
41
- CONVENTIONAL_COMMIT_REGEX.match?(@commit_message)
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PR
4
- module With
5
- module Params
6
- VERSION = "1.3.0"
7
- end
8
- end
9
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'params/version'
4
- require_relative 'params/config_parser'
5
- require_relative 'params/options_validator'
6
- require 'uri'
7
- require 'json'
8
- require 'launchy'
9
-
10
- module PR
11
- module With
12
- module Params
13
- class Error < StandardError; end
14
-
15
- extend self
16
-
17
- def open(host:, path:, query:)
18
- uri_query = URI.encode_www_form(query)
19
- url_string = URI::HTTPS.build(host: host, path: path, query: uri_query).to_s
20
- Launchy.open(url_string)
21
- end
22
-
23
- def parse_config(file_path, scope)
24
- ConfigParser.new(config_file_path: file_path, scope: scope).parse!
25
-
26
- file_path.empty? ? {} : ConfigParser.new(config_file_path: file_path, scope: scope).parse!
27
- rescue StandardError => e
28
- message = "\e[35mWARNING\e[0m: Error parsing config file. Using defaults"
29
- reason = "reason: #{e.message}"
30
- backtrace = "backtrace: #{e.backtrace&.last(10)&.join("\n")}"
31
- error_message = [message, reason, backtrace, "\n\n"].join("\n")
32
-
33
- warn error_message
34
-
35
- {}
36
- end
37
-
38
- def validate_options(options)
39
- validators = options.delete(:validators)
40
- OptionsValidator.validate!(options, validators: validators)
41
- end
42
- end
43
- end
44
- end