diff --git a/.gitignore b/.gitignore index 41f3c4a7..db8cab95 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ Gemfile.lock bin/bundle bin/rspec +coverage/ modules/ tmp/ vendor/ diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f6080fbb..11011ddb 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,12 +1,12 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2021-10-08 19:19:01 UTC using RuboCop version 1.22.1. +# on 2021-10-18 14:18:47 UTC using RuboCop version 1.22.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 9 +# Offense count: 8 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: Max: 60 @@ -14,14 +14,14 @@ Metrics/AbcSize: # Offense count: 2 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 131 + Max: 134 # Offense count: 4 # Configuration parameters: IgnoredMethods. Metrics/CyclomaticComplexity: Max: 15 -# Offense count: 16 +# Offense count: 14 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: Max: 34 diff --git a/features/cli.feature b/features/cli.feature index ce3d6e61..79a2de7e 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -17,9 +17,8 @@ Feature: CLI Then the exit status should be 1 Scenario: When running the help command - When I run `msync help` - And the output should match /Commands:/ - Then the exit status should be 0 + When I successfully run `msync help` + Then the output should match /Commands:/ Scenario: When overriding a setting from the config file on the command line Given a puppet module "puppet-test" from "fakenamespace" @@ -35,9 +34,8 @@ Feature: CLI """ And a git_base option appended to "modulesync.yml" for local tests And a directory named "moduleroot" - When I run `msync update --noop --namespace fakenamespace --branch command-line-branch` - Then the exit status should be 0 - And the output should contain: + When I successfully run `msync update --verbose --noop --namespace fakenamespace --branch command-line-branch` + Then the output should contain: """ Creating new branch command-line-branch """ diff --git a/features/hook.feature b/features/hook.feature index cae008e9..9326d213 100644 --- a/features/hook.feature +++ b/features/hook.feature @@ -3,24 +3,21 @@ Feature: hook Scenario: Activating a hook Given a directory named ".git/hooks" - When I run `msync hook activate` - Then the exit status should be 0 - And the file named ".git/hooks/pre-push" should contain "bash" + When I successfully run `msync hook activate` + Then the file named ".git/hooks/pre-push" should contain "bash" Scenario: Deactivating a hook Given a file named ".git/hooks/pre-push" with: """ git hook """ - When I run `msync hook deactivate` - Then the exit status should be 0 + When I successfully run `msync hook deactivate` Then the file ".git/hooks/pre-push" should not exist Scenario: Activating a hook with arguments Given a directory named ".git/hooks" - When I run `msync hook activate -a '--foo bar --baz quux' -b master` - Then the exit status should be 0 - And the file named ".git/hooks/pre-push" should contain: + When I successfully run `msync hook activate -a '--foo bar --baz quux' -b master` + Then the file named ".git/hooks/pre-push" should contain: """ "$message" -n puppetlabs -b master --foo bar --baz quux """ diff --git a/features/support/env.rb b/features/support/env.rb index 730de3d6..fb5a264e 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -13,4 +13,6 @@ # This enables coverage when aruba runs `msync` executable (cf. `bin/msync`) set_environment_variable('COVERAGE', '1') + + aruba.config.activate_announcer_on_command_failure = %i[stdout stderr] end diff --git a/features/update.feature b/features/update.feature index c04f1dfe..702b4032 100644 --- a/features/update.feature +++ b/features/update.feature @@ -14,9 +14,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files added: test @@ -37,9 +36,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update -s -m "Add test"` - Then the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" + When I successfully run `msync update -s -m "Add test"` + Then the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: Adding a new file to repo without write access Given a basic setup with a puppet module "puppet-test" from "fakenamespace" @@ -72,9 +70,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Warning: using './moduleroot/test' as template without '.erb' suffix """ @@ -99,9 +96,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files added: test @@ -125,9 +121,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files added: test @@ -151,9 +146,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files added: test @@ -195,9 +189,8 @@ Feature: update <%= c['name'] %> <% end %> """ - When I run `msync update --noop -s` - Then the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" + When I successfully run `msync update --noop -s` + Then the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: Using skip_broken and fail_on_warnings options with invalid files Given a basic setup with a puppet module "puppet-test" from "fakenamespace" @@ -235,9 +228,8 @@ Feature: update """ source '<%= @configs['gem_source'] %>' """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files changed: +diff --git a/Gemfile b/Gemfile @@ -265,9 +257,8 @@ Feature: update """ source '<%= @configs['gem_source'] %>' """ - When I run `msync update -m "Update Gemfile" -r test` - Then the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have only 1 commit made by "Aruba" + When I successfully run `msync update -m "Update Gemfile" -r test` + Then the puppet module "puppet-test" from "fakenamespace" should have only 1 commit made by "Aruba" And the puppet module "puppet-test" from "fakenamespace" should have 1 commit made by "Aruba" in branch "test" And the puppet module "puppet-test" from "fakenamespace" should have a branch "test" with a file named "Gemfile" which contains: """ @@ -292,7 +283,7 @@ Feature: update """ source '<%= @configs['gem_source'] %>' """ - When I run `msync update --noop` + When I successfully run `msync update --noop` Then the output should not match: """ Files changed: @@ -302,7 +293,6 @@ Feature: update """ Not managing 'Gemfile' in 'puppet-test' """ - And the exit status should be 0 And the file named "modules/fakenamespace/puppet-test/Gemfile" should contain: """ source 'https://rubygems.org' @@ -326,14 +316,13 @@ Feature: update """ source 'https://rubygems.org' """ - When I run `msync update --noop` + When I successfully run `msync update --noop` Then the output should match: """ Files changed: diff --git a/Gemfile b/Gemfile deleted file mode 100644 """ - And the exit status should be 0 And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: Setting a non-existent file to deleted @@ -345,9 +334,8 @@ Feature: update delete: true """ And a directory named "moduleroot" - When I run `msync update -m 'deletes a file that doesnt exist!' -f puppet-test` - And the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" + When I successfully run `msync update -m 'deletes a file that doesnt exist!' -f puppet-test` + Then the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: Setting a directory to unmanaged Given a basic setup with a puppet module "puppet-apache" from "puppetlabs" @@ -367,17 +355,15 @@ Feature: update """ This is a fake spec_helper! """ - When I run `msync update --offline` + When I successfully run `msync update --offline` Then the output should contain: """ Not managing 'spec/spec_helper.rb' in 'puppet-apache' """ - And the exit status should be 0 And the file named "modules/puppetlabs/puppet-apache/spec/spec_helper.rb" should contain: """ This is a fake spec_helper! """ - And the exit status should be 0 And the puppet module "puppet-apache" from "puppetlabs" should have no commits made by "Aruba" Scenario: Adding a new file in a new subdirectory @@ -395,9 +381,8 @@ Feature: update require '<%= required %>' <% end %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files added: spec/spec_helper.rb @@ -423,17 +408,15 @@ Feature: update require '<%= required %>' <% end %> """ - When I run `msync update --offline` - Then the exit status should be 0 - And the output should not match /Files (changed|added|deleted):/ + When I successfully run `msync update --offline` + Then the output should not match /Files (changed|added|deleted):/ And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: Pulling a module that already exists in the modules directory Given a basic setup with a puppet module "puppet-test" from "fakenamespace" And a directory named "moduleroot" - When I run `msync update --message "First update run"` - Then the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" + When I successfully run `msync update --message "First update run"` + Then the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Given a file named "config_defaults.yml" with: """ --- @@ -447,9 +430,8 @@ Feature: update require '<%= required %>' <% end %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files added: spec/spec_helper.rb @@ -459,9 +441,8 @@ Feature: update Scenario: When running update without changes Given a basic setup with a puppet module "puppet-test" from "fakenamespace" And a directory named "moduleroot" - When I run `msync update --message "Running without changes"` - Then the exit status should be 0 - And the stdout should contain "There were no changes in 'modules/fakenamespace/puppet-test'. Not committing." + When I successfully run `msync update --verbose --message "Running without changes"` + Then the stdout should contain "There were no changes in 'modules/fakenamespace/puppet-test'. Not committing." And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: When specifying configurations in managed_modules.yml @@ -483,9 +464,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files added: test @@ -521,9 +501,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop -f puppet-test` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop -f puppet-test` + Then the output should match: """ Files added: test @@ -560,9 +539,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop -x puppet-blacksmith` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop -x puppet-blacksmith` + Then the output should match: """ Files added: test @@ -604,9 +582,8 @@ Feature: update spec/spec_helper.rb: unmanaged: true """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Not managing 'spec/spec_helper.rb' in 'puppet-test' """ @@ -645,9 +622,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files added: test @@ -674,9 +650,8 @@ Feature: update """ Hello world! """ - When I run `msync update --noop` - Then the exit status should be 0 - And the output should match: + When I successfully run `msync update --noop` + Then the output should match: """ Files changed: +diff --git a/README.md b/README.md @@ -701,13 +676,11 @@ Feature: update """ source '<%= @configs['gem_source'] %>' """ - When I run `msync update -m "Update Gemfile" -r test` - Then the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have only 1 commit made by "Aruba" + When I successfully run `msync update -m "Update Gemfile" -r test` + Then the puppet module "puppet-test" from "fakenamespace" should have only 1 commit made by "Aruba" And the puppet module "puppet-test" from "fakenamespace" should have 1 commit made by "Aruba" in branch "test" Given I remove the directory "modules" - When I run `msync update -m "Update Gemfile" -r test` - Then the exit status should be 0 + When I successfully run `msync update -m "Update Gemfile" -r test` Then the output should not contain "error" Then the output should not contain "rejected" And the puppet module "puppet-test" from "fakenamespace" should have only 1 commit made by "Aruba" @@ -727,9 +700,8 @@ Feature: update """ source '<%= @configs['gem_source'] %>' """ - When I run `msync update -m "Update Gemfile"` - Then the exit status should be 0 - And the output should contain "Using repository's default branch: develop" + When I successfully run `msync update --verbose -m "Update Gemfile"` + Then the output should contain "Using repository's default branch: develop" And the puppet module "puppet-test" from "fakenamespace" should have only 1 commit made by "Aruba" And the puppet module "puppet-test" from "fakenamespace" should have 1 commit made by "Aruba" in branch "develop" @@ -746,9 +718,8 @@ Feature: update target: <%= @metadata[:target_file] %> workdir: <%= @metadata[:workdir] %> """ - When I run `msync update --noop` - Then the exit status should be 0 - And the file named "modules/fakenamespace/puppet-test/test" should contain: + When I successfully run `msync update --noop` + Then the file named "modules/fakenamespace/puppet-test/test" should contain: """ module: puppet-test target: modules/fakenamespace/puppet-test/test @@ -770,10 +741,8 @@ Feature: update """ <%= @configs['name'] %> """ - When I run `msync update -m "No changes!" --branch delete-me` - Then the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have 1 commit made by "Aruba" in branch "delete-me" + When I successfully run `msync update -m "No changes!" --branch delete-me` + Then the puppet module "puppet-test" from "fakenamespace" should have 1 commit made by "Aruba" in branch "delete-me" When the branch "delete-me" of the puppet module "puppet-test" from "fakenamespace" is deleted - And I run `msync update -m "No changes!" --branch delete-me` - Then the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" + And I successfully run `msync update -m "No changes!" --branch delete-me` + Then the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" diff --git a/features/update/bump_version.feature b/features/update/bump_version.feature index a1f18772..f5a5bea4 100644 --- a/features/update/bump_version.feature +++ b/features/update/bump_version.feature @@ -16,9 +16,8 @@ Feature: Bump a new version after an update """ <%= @configs['content'] %> """ - When I run `msync update --message "Add new-file" --bump --changelog --tag` - Then the exit status should be 0 - And the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba" + When I successfully run `msync update --verbose --message "Add new-file" --bump --changelog --tag` + Then the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba" And the stdout should contain: """ Bumped to version 0.4.3 @@ -44,9 +43,8 @@ Feature: Bump a new version after an update """ <%= @configs['content'] %> """ - When I run `msync update --message "Add new-file" --bump` - Then the exit status should be 0 - And the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba" + When I successfully run `msync update --message "Add new-file" --bump` + Then the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba" And the stdout should contain: """ Bumped to version 0.4.3 @@ -67,9 +65,8 @@ Feature: Bump a new version after an update """ <%= @configs['content'] %> """ - When I run `msync update --message "Add new-file" --bump --changelog` - Then the exit status should be 0 - And the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba" + When I successfully run `msync update --message "Add new-file" --bump --changelog` + Then the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba" And the stdout should contain: """ Bumped to version 0.4.3 @@ -81,7 +78,6 @@ Feature: Bump a new version after an update Scenario: Dont bump the module version after an update that produces no changes Given a basic setup with a puppet module "puppet-test" from "fakenamespace" And a directory named "moduleroot" - When I run `msync update --message "Add new-file" --bump --tag` - Then the exit status should be 0 - And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" + When I successfully run `msync update --message "Add new-file" --bump --tag` + Then the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" And the puppet module "puppet-test" from "fakenamespace" should not have a tag named "0.4.3" diff --git a/features/update/pull_request.feature b/features/update/pull_request.feature index c4762a5d..e5b0c78e 100644 --- a/features/update/pull_request.feature +++ b/features/update/pull_request.feature @@ -22,9 +22,8 @@ Feature: Create a pull-request/merge-request after update """ <%= @configs['name'] %> """ - When I run `msync update --noop --branch managed_update --pr` + When I successfully run `msync update --noop --branch managed_update --pr` Then the output should contain "Would submit PR " - And the exit status should be 0 And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: Run update in no-op mode and ask for GitLab MR @@ -50,9 +49,8 @@ Feature: Create a pull-request/merge-request after update """ <%= @configs['name'] %> """ - When I run `msync update --noop --branch managed_update --pr` + When I successfully run `msync update --noop --branch managed_update --pr` Then the output should contain "Would submit MR " - And the exit status should be 0 And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: Run update without changes in no-op mode and ask for GitLab MR @@ -69,9 +67,8 @@ Feature: Create a pull-request/merge-request after update And I set the environment variables to: | variable | value | | GITLAB_TOKEN | foobar | - When I run `msync update --noop --branch managed_update --pr` + When I successfully run `msync update --noop --branch managed_update --pr` Then the output should not contain "Would submit MR " - And the exit status should be 0 And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba" Scenario: Ask for PR without credentials @@ -124,9 +121,8 @@ Feature: Create a pull-request/merge-request after update """ <%= @configs['name'] %> """ - When I run `msync update --noop --branch managed_update --pr` - Then the exit status should be 0 - And the output should contain "Would submit PR " + When I successfully run `msync update --noop --branch managed_update --pr` + Then the output should contain "Would submit PR " And the output should contain "Would submit MR " And the puppet module "puppet-github" from "fakenamespace" should have no commits made by "Aruba" And the puppet module "puppet-gitlab" from "fakenamespace" should have no commits made by "Aruba" diff --git a/lib/modulesync/cli.rb b/lib/modulesync/cli.rb index 0fa157a5..0567303a 100644 --- a/lib/modulesync/cli.rb +++ b/lib/modulesync/cli.rb @@ -12,14 +12,13 @@ def self.defaults end class Hook < Thor - class_option :project_root, - :aliases => '-c', - :desc => 'Path used by git to clone modules into. Defaults to "modules"', - :default => CLI.defaults[:project_root] || 'modules' - class_option :hook_args, - :aliases => '-a', - :desc => 'Arguments to pass to msync in the git hook' - + option :hook_args, + :aliases => '-a', + :desc => 'Arguments to pass to msync in the git hook' + option :branch, + :aliases => '-b', + :desc => 'Branch name to pass to msync in the git hook', + :default => CLI.defaults[:branch] desc 'activate', 'Activate the git hook.' def activate config = { :command => 'hook' }.merge(options) @@ -53,11 +52,11 @@ class Base < Thor class_option :negative_filter, :aliases => '-x', :desc => 'A regular expression to skip repositories.' - class_option :branch, - :aliases => '-b', - :desc => 'Branch name to make the changes in.' \ - ' Defaults to the default branch of the upstream repository, but falls back to "master".', - :default => CLI.defaults[:branch] + class_option :verbose, + :aliases => '-v', + :desc => 'Verbose mode', + :type => :boolean, + :default => false desc 'update', 'Update the modules in managed_modules.yml' option :message, @@ -132,6 +131,11 @@ class Base < Thor :desc => 'Produce a failure exit code when there are warnings' \ ' (only has effect when --skip_broken is enabled)', :default => false + option :branch, + :aliases => '-b', + :desc => 'Branch name to make the changes in.' \ + ' Defaults to the default branch of the upstream repository, but falls back to "master".', + :default => CLI.defaults[:branch] def update config = { :command => 'update' }.merge(options) diff --git a/lib/modulesync/git_service.rb b/lib/modulesync/git_service.rb index a1d55f30..9c5a5538 100644 --- a/lib/modulesync/git_service.rb +++ b/lib/modulesync/git_service.rb @@ -5,6 +5,8 @@ class Error < StandardError; end module GitService class MissingCredentialsError < Error; end + class UnguessableTypeError < Error; end + def self.configuration_for(sourcecode:) type = type_for(sourcecode: sourcecode) @@ -28,13 +30,13 @@ def self.type_for(sourcecode:) return :gitlab if sourcecode.repository_remote.include? 'gitlab' if ENV['GITLAB_TOKEN'].nil? && ENV['GITHUB_TOKEN'].nil? - raise ModuleSync::Error, <<~MESSAGE + raise UnguessableTypeError, <<~MESSAGE Unable to guess Git service type without GITLAB_TOKEN or GITHUB_TOKEN sets. MESSAGE end unless ENV['GITLAB_TOKEN'].nil? || ENV['GITHUB_TOKEN'].nil? - raise ModuleSync::Error, <<~MESSAGE + raise UnguessableTypeError, <<~MESSAGE Unable to guess Git service type with both GITLAB_TOKEN and GITHUB_TOKEN sets. Please set the wanted one in configuration (ie. add `gitlab:` or `github:` key) @@ -63,7 +65,7 @@ def self.endpoint_for(sourcecode:, type:) ENV['GITLAB_BASE_URL'] end - endpoint ||= guess_endpoint_from(remote: sourcecode.repository_remote, type: type) + endpoint ||= GitService::Factory.klass(type: type).guess_endpoint_from(remote: sourcecode.repository_remote) raise NotImplementedError, <<~MESSAGE if endpoint.nil? Unable to guess endpoint for remote: '#{sourcecode.repository_remote}' @@ -73,16 +75,6 @@ def self.endpoint_for(sourcecode:, type:) endpoint end - # This method attempts to guess the git service endpoint based on remote and type - def self.guess_endpoint_from(remote:, type:) - hostname = extract_hostname(remote) - return nil if hostname.nil? - - endpoint = "https://#{hostname}" - endpoint += '/api/v4' if type == :gitlab - endpoint - end - # This method attempts to find the token associated to provided sourcecode and type # It process in this order: # 1. use module specific configuration (ie. `token`) @@ -100,30 +92,5 @@ def self.token_for(sourcecode:, type:) token end - - # This method extracts hostname from URL like: - # - # - ssh://[user@]host.xz[:port]/path/to/repo.git/ - # - git://host.xz[:port]/path/to/repo.git/ - # - [user@]host.xz:path/to/repo.git/ - # - http[s]://host.xz[:port]/path/to/repo.git/ - # - ftp[s]://host.xz[:port]/path/to/repo.git/ - # - # Returns nil if - # - /path/to/repo.git/ - # - file:///path/to/repo.git/ - # - any invalid URL - def self.extract_hostname(url) - return nil if url.start_with?('/') || url.start_with?('file://') # local path (e.g. file:///path/to/repo) - - unless url.start_with?(%r{[a-z]+://}) # SSH notation does not contain protocol (e.g. user@server:path/to/repo/) - pattern = /^(?.*@)?(?[\w|.]*):(?.*)$/ # SSH path (e.g. user@server:repo) - return url.match(pattern)[:hostname] if url.match?(pattern) - end - - URI.parse(url).host - rescue URI::InvalidURIError - nil - end end end diff --git a/lib/modulesync/git_service/base.rb b/lib/modulesync/git_service/base.rb index da4476a7..9d584691 100644 --- a/lib/modulesync/git_service/base.rb +++ b/lib/modulesync/git_service/base.rb @@ -20,6 +20,39 @@ def open_pull_request(repo_path:, namespace:, title:, message:, source_branch:, ) end + # This method attempts to guess the git service endpoint based on remote + def self.guess_endpoint_from(remote:) + hostname = extract_hostname(remote) + return nil if hostname.nil? + + "https://#{hostname}" + end + + # This method extracts hostname from URL like: + # + # - ssh://[user@]host.xz[:port]/path/to/repo.git/ + # - git://host.xz[:port]/path/to/repo.git/ + # - [user@]host.xz:path/to/repo.git/ + # - http[s]://host.xz[:port]/path/to/repo.git/ + # - ftp[s]://host.xz[:port]/path/to/repo.git/ + # + # Returns nil if + # - /path/to/repo.git/ + # - file:///path/to/repo.git/ + # - any invalid URL + def self.extract_hostname(url) + return nil if url.start_with?('/') || url.start_with?('file://') # local path (e.g. file:///path/to/repo) + + unless url.start_with?(%r{[a-z]+://}) # SSH notation does not contain protocol (e.g. user@server:path/to/repo/) + pattern = /^(?.*@)?(?[\w|.]*):(?.*)$/ # SSH path (e.g. user@server:repo) + return url.match(pattern)[:hostname] if url.match?(pattern) + end + + URI.parse(url).host + rescue URI::InvalidURIError + nil + end + protected def _open_pull_request(repo_path:, namespace:, title:, message:, source_branch:, target_branch:, labels:, noop:) # rubocop:disable Metrics/ParameterLists diff --git a/lib/modulesync/git_service/factory.rb b/lib/modulesync/git_service/factory.rb index eb7bc5e9..52adafe8 100644 --- a/lib/modulesync/git_service/factory.rb +++ b/lib/modulesync/git_service/factory.rb @@ -8,15 +8,19 @@ def self.instantiate(type:, endpoint:, token:) Please set environment variable: "#{type.upcase}_TOKEN" or set the token entry in module options. MESSAGE + klass(type: type).new token, endpoint + end + + def self.klass(type:) case type when :github require 'modulesync/git_service/github' - ModuleSync::GitService::GitHub.new(token, endpoint) + ModuleSync::GitService::GitHub when :gitlab require 'modulesync/git_service/gitlab' - ModuleSync::GitService::GitLab.new(token, endpoint) + ModuleSync::GitService::GitLab else - raise NotImplementedError, "Unable to manage a PR/MR for Git service: '#{type}'" + raise NotImplementedError, "Unknown git service: '#{type}'" end end end diff --git a/lib/modulesync/git_service/gitlab.rb b/lib/modulesync/git_service/gitlab.rb index 7fcfd306..bd634882 100644 --- a/lib/modulesync/git_service/gitlab.rb +++ b/lib/modulesync/git_service/gitlab.rb @@ -16,6 +16,14 @@ def initialize(token, endpoint) ) end + def self.guess_endpoint_from(remote:) + endpoint = super + return nil if endpoint.nil? + + endpoint += '/api/v4' + endpoint + end + private def _open_pull_request(repo_path:, namespace:, title:, message:, source_branch:, target_branch:, labels:, noop:) # rubocop:disable Metrics/ParameterLists, Lint/UnusedMethodArgument diff --git a/lib/modulesync/repository.rb b/lib/modulesync/repository.rb index 836bdf02..58582b29 100644 --- a/lib/modulesync/repository.rb +++ b/lib/modulesync/repository.rb @@ -148,20 +148,24 @@ def untracked_unignored_files def show_changes(options) checkout_branch(options[:branch]) - puts 'Files changed:' + $stdout.puts 'Files changed:' repo.diff('HEAD', '--').each do |diff| - puts diff.patch + $stdout.puts diff.patch end - puts 'Files added:' + $stdout.puts 'Files added:' untracked_unignored_files.each_key do |file| - puts file + $stdout.puts file end - puts "\n\n" - puts '--------------------------------' + $stdout.puts "\n\n" + $stdout.puts '--------------------------------' git.diff('HEAD', '--').any? || untracked_unignored_files.any? end + + def puts(*args) + $stdout.puts(*args) if ModuleSync.options[:verbose] + end end end diff --git a/lib/modulesync/source_code.rb b/lib/modulesync/source_code.rb index 89b75b52..44235ae8 100644 --- a/lib/modulesync/source_code.rb +++ b/lib/modulesync/source_code.rb @@ -49,11 +49,15 @@ def path(*parts) end def git_service + return nil if git_service_configuration.nil? + @git_service ||= GitService::Factory.instantiate(**git_service_configuration) end def git_service_configuration @git_service_configuration ||= GitService.configuration_for(sourcecode: self) + rescue GitService::UnguessableTypeError + nil end def open_pull_request diff --git a/spec/helpers/faker/puppet_module_remote_repo.rb b/spec/helpers/faker/puppet_module_remote_repo.rb index 10de2f70..137048f4 100644 --- a/spec/helpers/faker/puppet_module_remote_repo.rb +++ b/spec/helpers/faker/puppet_module_remote_repo.rb @@ -95,7 +95,7 @@ def commit_count_between(commit1, commit2) def commit_count_by(author, commit = nil) FileUtils.chdir(bare_repo_dir) do commit ||= '--all' - stdout = run %W[git rev-list #{commit} --author #{author} --count] + stdout = run %W[git rev-list --author #{author} --count #{commit} --] return Integer(stdout) end end diff --git a/spec/unit/modulesync/git_service_spec.rb b/spec/unit/modulesync/git_service_spec.rb index d20f0767..5723f32c 100644 --- a/spec/unit/modulesync/git_service_spec.rb +++ b/spec/unit/modulesync/git_service_spec.rb @@ -162,7 +162,7 @@ RSpec.shared_examples 'hostname_extractor' do |url, hostname| context "with '#{url}' URL" do - subject { ModuleSync::GitService.extract_hostname(url) } + subject { ModuleSync::GitService::Base.extract_hostname(url) } it "should extract #{hostname.nil? ? 'nil' : "'#{hostname}'"} as hostname" do expect(subject).to eq(hostname) end