gitlab-housekeeper 0.1.0.pre.code.pre.challenge.pre.f0dc6c.pre → 0.1.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: cd6805b38ad05a71627181fe194b47da9608acbbb7c8712a39dea2f37a59b17e
4
- data.tar.gz: 1186229f242b4d59a70732beaa9379c8c4462a776fcdc4bcf7a912fd4329dfe7
3
+ metadata.gz: 8b911737b1ef300020b8cd648c514329d2eee7dfd8f86610727d8f4c4c47bd20
4
+ data.tar.gz: 47ef5bec137ec296a9bc61032aaee4c3be6e26fd8d404a1b4483f1797a8ad2bf
5
5
  SHA512:
6
- metadata.gz: 8d15af919460aa575b5ca61d64c46a288bb5469ba65d569d6e0879d6e34eac38262c8341b3d9a92aee5d4ca706fb99073176e5d306f301dd9a9893187f39e187
7
- data.tar.gz: d6b484163ae9bc9571b813c2a3006951f5b2b0c22c3bc4e1c38b6ae4fa274a1bde91684d562cb6d22476e6610028cf4265de2e4e2bd7e9dd7badb81a362c2804
6
+ metadata.gz: 767b5444231e67c439b7bd659c2e974445041e3e8140ed2d7c3336aecf3f7a5628505122cf32a83be68f5277578afe04b0ea74cfa6402108f466850a9d827a74
7
+ data.tar.gz: 6f50658e7fc7d37694af6f504a046bd2e1510d85852a37c3e4a84ac54391b8cea985c729f34be24f49f2ec7e53202de7bcc9b8f309c6fa61de445394e3c55641
@@ -8,30 +8,19 @@ module Gitlab
8
8
  :description,
9
9
  :changed_files,
10
10
  :labels,
11
- :keep_class,
12
- :changelog_type,
13
- :mr_web_url
14
- attr_reader :reviewers
11
+ :reviewers
15
12
 
16
13
  def initialize
17
14
  @labels = []
18
15
  @reviewers = []
19
16
  end
20
17
 
21
- def reviewers=(reviewers)
22
- @reviewers = Array(reviewers)
23
- end
24
-
25
18
  def mr_description
26
19
  <<~MARKDOWN
27
20
  #{description}
28
21
 
29
22
  This change was generated by
30
23
  [gitlab-housekeeper](https://gitlab.com/gitlab-org/gitlab/-/tree/master/gems/gitlab-housekeeper)
31
- using the #{keep_class} keep.
32
-
33
- To provide feedback on your experience with `gitlab-housekeeper` please comment in
34
- <https://gitlab.com/gitlab-org/gitlab/-/issues/442003>.
35
24
  MARKDOWN
36
25
  end
37
26
 
@@ -41,7 +30,7 @@ module Gitlab
41
30
 
42
31
  #{mr_description}
43
32
 
44
- Changelog: #{changelog_type || 'other'}
33
+ Changelog: other
45
34
  MARKDOWN
46
35
  end
47
36
 
@@ -11,57 +11,49 @@ module Gitlab
11
11
  @branch_from = branch_from
12
12
  end
13
13
 
14
- def with_clean_state
15
- result = Shell.execute('git', 'stash')
16
- stashed = !result.include?('No local changes to save')
17
-
18
- with_return_to_current_branch(stashed: stashed) do
19
- checkout_branch(@branch_from)
20
-
21
- yield
22
- end
23
- end
24
-
25
- def create_branch(change)
14
+ def commit_in_branch(change)
26
15
  branch_name = branch_name(change.identifiers)
27
16
 
28
- Shell.execute("git", "branch", "-f", branch_name)
17
+ create_commit(branch_name, change)
29
18
 
30
19
  branch_name
31
20
  end
32
21
 
33
- def in_branch(branch_name)
34
- with_return_to_current_branch do
35
- checkout_branch(branch_name)
22
+ def with_branch_from_branch
23
+ stashed = false
24
+ current_branch = Shell.execute('git', 'branch', '--show-current').chomp
36
25
 
37
- yield
38
- end
39
- end
26
+ result = Shell.execute('git', 'stash')
27
+ stashed = !result.include?('No local changes to save')
40
28
 
41
- def create_commit(change)
42
- Shell.execute("git", "add", *change.changed_files)
43
- Shell.execute("git", "commit", "-m", change.commit_message)
29
+ Shell.execute("git", "checkout", @branch_from)
30
+
31
+ yield
32
+ ensure
33
+ # The `current_branch` won't be set in CI due to how the repo is cloned. Therefore we should only checkout
34
+ # `current_branch` if we actually have one.
35
+ Shell.execute("git", "checkout", current_branch) if current_branch.present?
36
+ Shell.execute('git', 'stash', 'pop') if stashed
44
37
  end
45
38
 
46
- private
39
+ def create_commit(branch_name, change)
40
+ current_branch = Shell.execute('git', 'branch', '--show-current').chomp
47
41
 
48
- def create_and_checkout_branch(branch_name)
49
42
  begin
50
43
  Shell.execute("git", "branch", '-D', branch_name)
51
44
  rescue Shell::Error # Might not exist yet
52
45
  end
53
46
 
54
47
  Shell.execute("git", "checkout", "-b", branch_name)
55
- end
56
-
57
- def checkout_branch(branch_name)
58
- Shell.execute("git", "checkout", branch_name)
48
+ Shell.execute("git", "add", *change.changed_files)
49
+ Shell.execute("git", "commit", "-m", change.commit_message)
50
+ ensure
51
+ Shell.execute("git", "checkout", current_branch)
59
52
  end
60
53
 
61
54
  def branch_name(identifiers)
62
55
  # Hyphen-case each identifier then join together with hyphens.
63
56
  branch_name = identifiers
64
- .map { |i| i.gsub(/[^\w]+/, '-') }
65
57
  .map { |i| i.gsub(/[[:upper:]]/) { |w| "-#{w.downcase}" } }
66
58
  .join('-')
67
59
  .delete_prefix("-")
@@ -73,17 +65,6 @@ module Gitlab
73
65
 
74
66
  branch_name
75
67
  end
76
-
77
- def with_return_to_current_branch(stashed: false)
78
- current_branch = Shell.execute('git', 'branch', '--show-current').chomp
79
-
80
- yield
81
- ensure
82
- # The `current_branch` won't be set in CI due to how the repo is cloned. Therefore we should only checkout
83
- # `current_branch` if we actually have one.
84
- checkout_branch(current_branch) if current_branch.present?
85
- Shell.execute('git', 'stash', 'pop') if stashed
86
- end
87
68
  end
88
69
  end
89
70
  end
@@ -23,19 +23,16 @@ module Gitlab
23
23
  target_project_id:
24
24
  )
25
25
 
26
- existing_merge_request = get_existing_merge_request(
26
+ iid = get_existing_merge_request(
27
27
  source_project_id: source_project_id,
28
28
  source_branch: source_branch,
29
29
  target_branch: target_branch,
30
30
  target_project_id: target_project_id
31
31
  )
32
32
 
33
- return [] if existing_merge_request.nil?
33
+ return [] if iid.nil?
34
34
 
35
- merge_request_notes = get_merge_request_notes(
36
- target_project_id: target_project_id,
37
- iid: existing_merge_request['iid']
38
- )
35
+ merge_request_notes = get_merge_request_notes(target_project_id: target_project_id, iid: iid)
39
36
 
40
37
  changes = Set.new
41
38
 
@@ -51,10 +48,7 @@ module Gitlab
51
48
  changes << :reviewers if note['body'].include?('removed review request for')
52
49
  end
53
50
 
54
- resource_label_events = get_merge_request_resource_label_events(
55
- target_project_id: target_project_id,
56
- iid: existing_merge_request['iid']
57
- )
51
+ resource_label_events = get_merge_request_resource_label_events(target_project_id: target_project_id, iid: iid)
58
52
 
59
53
  resource_label_events.each do |event|
60
54
  next if event["user"]["id"] == current_user_id
@@ -82,17 +76,17 @@ module Gitlab
82
76
  update_labels:,
83
77
  update_reviewers:
84
78
  )
85
- existing_merge_request = get_existing_merge_request(
79
+ existing_iid = get_existing_merge_request(
86
80
  source_project_id: source_project_id,
87
81
  source_branch: source_branch,
88
82
  target_branch: target_branch,
89
83
  target_project_id: target_project_id
90
84
  )
91
85
 
92
- if existing_merge_request
86
+ if existing_iid
93
87
  update_existing_merge_request(
94
88
  change: change,
95
- existing_iid: existing_merge_request['iid'],
89
+ existing_iid: existing_iid,
96
90
  target_project_id: target_project_id,
97
91
  update_title: update_title,
98
92
  update_description: update_description,
@@ -111,21 +105,6 @@ module Gitlab
111
105
  end
112
106
  # rubocop:enable Metrics/ParameterLists
113
107
 
114
- def get_existing_merge_request(source_project_id:, source_branch:, target_branch:, target_project_id:)
115
- data = request(:get, "/projects/#{target_project_id}/merge_requests", query: {
116
- state: :opened,
117
- source_branch: source_branch,
118
- target_branch: target_branch,
119
- source_project_id: source_project_id
120
- })
121
-
122
- return nil if data.empty?
123
-
124
- raise Error, "More than one matching MR exists: iids: #{data.pluck('iid').join(',')}" unless data.size == 1
125
-
126
- data.first
127
- end
128
-
129
108
  private
130
109
 
131
110
  def get_merge_request_notes(target_project_id:, iid:)
@@ -141,6 +120,23 @@ module Gitlab
141
120
  @current_user_id ||= request(:get, "/user")['id']
142
121
  end
143
122
 
123
+ def get_existing_merge_request(source_project_id:, source_branch:, target_branch:, target_project_id:)
124
+ data = request(:get, "/projects/#{target_project_id}/merge_requests", query: {
125
+ state: :opened,
126
+ source_branch: source_branch,
127
+ target_branch: target_branch,
128
+ source_project_id: source_project_id
129
+ })
130
+
131
+ return nil if data.empty?
132
+
133
+ iids = data.pluck('iid')
134
+
135
+ raise Error, "More than one matching MR exists: iids: #{iids.join(',')}" unless data.size == 1
136
+
137
+ iids.first
138
+ end
139
+
144
140
  def create_merge_request(
145
141
  change:,
146
142
  source_project_id:,
@@ -182,7 +178,7 @@ module Gitlab
182
178
  end
183
179
 
184
180
  def usernames_to_ids(usernames)
185
- Array(usernames).map do |username|
181
+ usernames.map do |username|
186
182
  data = request(:get, "/users", query: { username: username })
187
183
  data[0]['id']
188
184
  end
@@ -2,12 +2,9 @@
2
2
 
3
3
  require 'active_support/core_ext/string'
4
4
  require 'gitlab/housekeeper/keep'
5
- require 'gitlab/housekeeper/keeps/rubocop_fixer'
6
- require 'gitlab/housekeeper/keeps/upgrade_dependency'
7
5
  require 'gitlab/housekeeper/gitlab_client'
8
6
  require 'gitlab/housekeeper/git'
9
7
  require 'gitlab/housekeeper/change'
10
- require 'gitlab/housekeeper/substitutor'
11
8
  require 'awesome_print'
12
9
  require 'digest'
13
10
 
@@ -32,7 +29,7 @@ module Gitlab
32
29
  def run
33
30
  created = 0
34
31
 
35
- git.with_clean_state do
32
+ git.with_branch_from_branch do
36
33
  @keeps.each do |keep_class|
37
34
  keep = keep_class.new
38
35
  keep.each_change do |change|
@@ -41,45 +38,22 @@ module Gitlab
41
38
  next
42
39
  end
43
40
 
44
- change.keep_class ||= keep_class
45
-
46
- branch_name = git.create_branch(change)
41
+ branch_name = git.commit_in_branch(change)
47
42
  add_standard_change_data(change)
48
43
 
44
+ # Must be done after we commit so that we don't keep around changed files. We could checkout those files
45
+ # but then it might be riskier in local development in case we lose unrelated changes.
49
46
  unless change.matches_filters?(@filter_identifiers)
50
- # At this point the keep has already run and edited files so we need to
51
- # restore the local working copy. We could simply checkout all
52
- # changed_files but this is very risky as it could mean losing work that
53
- # cannot be recovered. Instead we commit all the work to the branch and
54
- # move on without pushing the branch.
55
- git.in_branch(branch_name) do
56
- git.create_commit(change)
57
- end
58
-
59
- puts "Skipping change: #{change.identifiers} due to not matching filter."
60
- puts "Modified files have been committed to branch #{branch_name.yellowish}, but will not be pushed."
61
- puts
62
-
47
+ puts "Skipping change: #{change.identifiers} due to not matching filter"
63
48
  next
64
49
  end
65
50
 
66
- # If no merge request exists yet, create an empty one to allow keeps to use the web URL.
67
- unless @dry_run
68
- merge_reqeust = get_existing_merge_request(branch_name) || create(change, branch_name)
69
-
70
- change.mr_web_url = merge_reqeust['web_url']
71
- end
72
-
73
- git.in_branch(branch_name) do
74
- Gitlab::Housekeeper::Substitutor.perform(change)
75
-
76
- git.create_commit(change)
51
+ if @dry_run
52
+ dry_run(change, branch_name)
53
+ else
54
+ create(change, branch_name)
77
55
  end
78
56
 
79
- print_change_details(change, branch_name)
80
-
81
- create(change, branch_name) unless @dry_run
82
-
83
57
  created += 1
84
58
  break if created >= @max_mrs
85
59
  end
@@ -105,8 +79,7 @@ module Gitlab
105
79
  end
106
80
  end
107
81
 
108
- def print_change_details(change, branch_name)
109
- puts "Merge request URL: #{change.mr_web_url || '(known after create)'}, on branch #{branch_name}".yellowish
82
+ def dry_run(change, branch_name)
110
83
  puts "=> #{change.identifiers.join(': ')}".purple
111
84
 
112
85
  puts '=> Title:'.purple
@@ -117,10 +90,9 @@ module Gitlab
117
90
  puts change.description
118
91
  puts
119
92
 
120
- if change.labels.present? || change.reviewers.present?
93
+ if change.labels.present?
121
94
  puts '=> Attributes:'
122
95
  puts "Labels: #{change.labels.join(', ')}"
123
- puts "Reviewers: #{change.reviewers.join(', ')}"
124
96
  puts
125
97
  end
126
98
 
@@ -131,6 +103,8 @@ module Gitlab
131
103
  end
132
104
 
133
105
  def create(change, branch_name)
106
+ dry_run(change, branch_name)
107
+
134
108
  non_housekeeper_changes = gitlab_client.non_housekeeper_changes(
135
109
  source_project_id: housekeeper_fork_project_id,
136
110
  source_branch: branch_name,
@@ -142,7 +116,7 @@ module Gitlab
142
116
  Shell.execute('git', 'push', '-f', 'housekeeper', "#{branch_name}:#{branch_name}")
143
117
  end
144
118
 
145
- gitlab_client.create_or_update_merge_request(
119
+ mr = gitlab_client.create_or_update_merge_request(
146
120
  change: change,
147
121
  source_project_id: housekeeper_fork_project_id,
148
122
  source_branch: branch_name,
@@ -153,15 +127,8 @@ module Gitlab
153
127
  update_labels: !non_housekeeper_changes.include?(:labels),
154
128
  update_reviewers: !non_housekeeper_changes.include?(:reviewers)
155
129
  )
156
- end
157
130
 
158
- def get_existing_merge_request(branch_name)
159
- gitlab_client.get_existing_merge_request(
160
- source_project_id: housekeeper_fork_project_id,
161
- source_branch: branch_name,
162
- target_branch: 'master',
163
- target_project_id: housekeeper_target_project_id
164
- )
131
+ puts "Merge request URL: #{mr['web_url'].yellowish}"
165
132
  end
166
133
 
167
134
  def housekeeper_fork_project_id
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-housekeeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.code.pre.challenge.pre.f0dc6c.pre
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - group::tenant-scale
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-13 00:00:00.000000000 Z
11
+ date: 2024-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: awesome_print
28
+ name: httparty
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: httparty
42
+ name: rubocop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rubocop
56
+ name: awesome_print
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -136,11 +136,8 @@ files:
136
136
  - lib/gitlab/housekeeper/git.rb
137
137
  - lib/gitlab/housekeeper/gitlab_client.rb
138
138
  - lib/gitlab/housekeeper/keep.rb
139
- - lib/gitlab/housekeeper/keeps/rubocop_fixer.rb
140
- - lib/gitlab/housekeeper/keeps/upgrade_dependency.rb
141
139
  - lib/gitlab/housekeeper/runner.rb
142
140
  - lib/gitlab/housekeeper/shell.rb
143
- - lib/gitlab/housekeeper/substitutor.rb
144
141
  - lib/gitlab/housekeeper/version.rb
145
142
  homepage: https://gitlab.com/gitlab-org/gitlab/-/tree/master/gems/gitlab-housekeeper
146
143
  licenses:
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yaml'
4
-
5
- module Gitlab
6
- module Housekeeper
7
- module Keeps
8
- class RubocopFixer < Keep
9
- LIMIT_FIXES = 20
10
- RUBOCOP_TODO_DIR_PATTERN = ".rubocop_todo/**/*.yml"
11
-
12
- def initialize(todo_dir_pattern: RUBOCOP_TODO_DIR_PATTERN, limit_fixes: LIMIT_FIXES)
13
- @todo_dir_pattern = todo_dir_pattern
14
- @limit_fixes = limit_fixes
15
- end
16
-
17
- def each_change
18
- each_allowed_rubocop_rule do |rule, rule_file_path, violating_files|
19
- remove_allow_rule = true
20
-
21
- if violating_files.count > @limit_fixes
22
- violating_files = violating_files.first(@limit_fixes)
23
- remove_allow_rule = false
24
- end
25
-
26
- change = Change.new
27
- change.title = "Fix #{violating_files.count} rubocop violations for #{rule}"
28
- change.identifiers = [self.class.name, rule, violating_files.last]
29
- change.description = <<~MARKDOWN
30
- Fixes the #{violating_files.count} violations for the rubocop rule `#{rule}`
31
- that were previously excluded in `#{rule_file_path}`.
32
- The exclusions have now been removed.
33
- MARKDOWN
34
-
35
- if remove_allow_rule
36
- FileUtils.rm(rule_file_path)
37
- else
38
- remove_first_exclusions(rule, rule_file_path, violating_files.count)
39
- end
40
-
41
- begin
42
- ::Gitlab::Housekeeper::Shell.execute('rubocop', '--autocorrect', *violating_files)
43
- rescue ::Gitlab::Housekeeper::Shell::Error
44
- # Ignore when it cannot be automatically fixed. But we need to checkout any files we might have updated.
45
- ::Gitlab::Housekeeper::Shell.execute('git', 'checkout', rule_file_path, *violating_files)
46
- next
47
- end
48
-
49
- change.changed_files = [rule_file_path, *violating_files]
50
-
51
- yield(change)
52
- end
53
- end
54
-
55
- def each_allowed_rubocop_rule
56
- Dir.glob(@todo_dir_pattern).each do |file|
57
- content = File.read(file)
58
- next unless content.include?('Cop supports --autocorrect')
59
-
60
- data = YAML.safe_load(content)
61
-
62
- # Assume one per file since that's how it is in gitlab-org/gitlab
63
- next unless data.keys.count == 1
64
-
65
- rule = data.keys[0]
66
- violating_files = data[rule]['Exclude']
67
- next unless violating_files&.count&.positive?
68
-
69
- yield rule, file, violating_files
70
- end
71
- end
72
-
73
- def remove_first_exclusions(_rule, file, remove_count)
74
- content = File.read(file)
75
- skipped = 0
76
-
77
- output = content.each_line.filter do |line|
78
- if skipped < remove_count && line.match?(/\s+-\s+/)
79
- skipped += 1
80
- false
81
- else
82
- true
83
- end
84
- end
85
-
86
- File.write(file, output.join)
87
- end
88
- end
89
- end
90
- end
91
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module Housekeeper
5
- module Keeps
6
- class UpgradeDependency < Keep
7
- def initialize(
8
- upgrade_command: ENV.fetch('HOUSEKEEPER_DEPENDENCY_UPGRADE_COMMAND'), # bundle update haml
9
- changed_files: ENV.fetch('HOUSEKEEPER_DEPENDENCY_UPGRADE_CHANGED_FILES').split(',') # Gemfile.lock
10
- )
11
- @upgrade_command = upgrade_command
12
- @changed_files = changed_files
13
- end
14
-
15
- def each_change
16
- ::Gitlab::Housekeeper::Shell.execute(@upgrade_command)
17
-
18
- change = Change.new
19
- change.title = "Run #{@upgrade_command}"
20
- change.identifiers = [self.class.name, @upgrade_command]
21
- change.description = <<~MARKDOWN
22
- Automatically upgrade a dependency using:
23
-
24
- ```
25
- #{@upgrade_command}
26
- ```
27
- MARKDOWN
28
-
29
-
30
- change.changed_files = @changed_files
31
-
32
- yield(change)
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module Housekeeper
5
- class Substitutor
6
- MR_WEB_URL_PLACEHOLDER = '<HOUSEKEEPER_MR_WEB_URL>'
7
-
8
- def self.perform(change)
9
- return unless change.mr_web_url.present?
10
-
11
- change.changed_files.each do |file|
12
- next unless File.file?(file)
13
-
14
- content = File.read(file)
15
- content.gsub!(MR_WEB_URL_PLACEHOLDER, change.mr_web_url)
16
-
17
- File.write(file, content)
18
- end
19
- end
20
- end
21
- end
22
- end