git-maintain 0.7.0 → 0.9.0rc1

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.
data/README.md CHANGED
@@ -16,9 +16,9 @@ The idea is to script most of the maintenance tasks so the maintainer can focus
16
16
  - **list_stable**: List commit present in the stable branch but not in the latest associated relase
17
17
  - **merge**: Merge branch with suffix specified in -m <suff> into the main branch
18
18
  - **push**: Push branches to github for validation
19
- - **monitor**: Check the travis state of all branches
19
+ - **monitor**: Check the CI state of all branches
20
20
  - **push_stable**: Push to stable repo
21
- - **monitor_stable**: Check the travis state of all stable branches
21
+ - **monitor_stable**: Check the CI state of all stable branches
22
22
  - **release**: Create new release on all concerned branches
23
23
  - **reset**: Reset branch against upstream
24
24
  - **submit_release**: Push the to stable and create the release packages
@@ -157,7 +157,7 @@ Apply them to the appropriate branches
157
157
 
158
158
  ```git maintain cp -s deadbeef --version '1[789]'```
159
159
 
160
- And push them to my own github repo so that Travis will check everything out
160
+ And push them to my own github repo so that CI will check everything out
161
161
 
162
162
  ```git maintain push --version '1[789]'```
163
163
 
@@ -179,7 +179,7 @@ Push it to my own github too.
179
179
 
180
180
  ```git maintain push --version '1[789]' -b pending```
181
181
 
182
- Once this gets accepted (and Travis is OK too), I merge this branch back to my 'master'
182
+ Once this gets accepted (and CI is OK too), I merge this branch back to my 'master'
183
183
 
184
184
  ```git maintain merge --version '1[789]' -m pending```
185
185
 
@@ -239,7 +239,7 @@ The tag will not have been propagated anywhere else and can be deleted manually.
239
239
 
240
240
  ```git maintain push_stable --version '1[789]'```
241
241
 
242
- You can then monitor the status on Travis
242
+ You can then monitor the status on CI
243
243
 
244
244
  ```git maintain monitor_stable --version '1[789]'```
245
245
 
@@ -258,6 +258,8 @@ Enjoy, and feel free to report bugs, missing features and/or send patches
258
258
 
259
259
  This is a summary of all the settings that can be set in the git config:
260
260
 
261
+ - `maintain.valid-repo`: Remote github repo to test out branches before submitting. Default = `github`
262
+ - `maintain.stable-repo`: Remote stable github repository t submit validated branches and new releases. Default = `stable`
261
263
  - `maintain.autofetch`: Enable/Disable auto fetching.
262
264
  Can be overriden by the --[no-]fetch option on the CLI.
263
265
  If unset, autofetch is enabled
@@ -274,3 +276,22 @@ This is a summary of all the settings that can be set in the git config:
274
276
  - `maintain.mail-format`: Specify how release annoucement emails are sent. Can be:
275
277
  - `imap_send`: Store prepared email in an IMAP folder. See `main git-imap-send` for more infos. This is the default value.
276
278
  - `send_email`: Generates a file which is compatible with git send-email
279
+
280
+ # License
281
+
282
+ Unless otherwise stated, everything in this repo is covered by the following
283
+ copyright notice:
284
+
285
+ Copyright (c) 2022 SUSE
286
+
287
+ This program is free software: you can redistribute it and/or modify it
288
+ under the terms of the GNU General Public License version 3, as
289
+ published by the Free Software Foundation.
290
+
291
+ This program is distributed in the hope that it will be useful,
292
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
293
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
294
+ GNU General Public License for more details.
295
+
296
+ You should have received a copy of the GNU General Public License
297
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
data/bin/git-maintain CHANGED
@@ -11,17 +11,17 @@ $LOAD_PATH.pop()
11
11
 
12
12
  opts = {
13
13
  :br_suff => "master",
14
- :no => false,
14
+ :yn_default => nil,
15
15
  }
16
-
16
+ ACTION_HELPS = GitMaintain::getActionAttr("ACTION_HELP")
17
17
  actionParser = OptionParser.new(nil, 60)
18
18
  actionParser.banner = "Usage: #{__FILE__} <action> [action options]"
19
19
  actionParser.separator ""
20
20
  actionParser.separator "Options:"
21
21
  actionParser.on("-h", "--help", "Display usage.") { |val| puts actionParser.to_s; exit 0 }
22
22
  actionParser.separator "Possible actions:"
23
- GitMaintain::getActionAttr("ACTION_HELP").sort.each(){|x|
24
- actionParser.separator "\t " + x
23
+ ACTION_HELPS.each(){|k, x|
24
+ actionParser.separator "\t * " + k.to_s() + ": " + x
25
25
  }
26
26
  rest = actionParser.order!(ARGV);
27
27
  if rest.length <= 0 then
@@ -38,13 +38,16 @@ ARGV.shift()
38
38
 
39
39
  optsParser = OptionParser.new(nil, 60)
40
40
  optsParser.banner = "Usage: #{__FILE__} #{action_s} "
41
+ optsParser.separator "# " + ACTION_HELPS[action].to_s()
41
42
  optsParser.separator ""
42
43
  optsParser.separator "Options:"
43
44
  optsParser.on("-h", "--help", "Display usage.") { |val| puts optsParser.to_s; exit 0 }
44
45
  optsParser.on("-b", "--branch-suffix [SUFFIX]", "Branch suffix. Default is 'master'.") {
45
46
  |val| opts[:br_suff] = val}
46
47
  optsParser.on("-n", "--no", "Assume no to all questions.") {
47
- |val| opts[:no] = true}
48
+ |val| opts[:yn_default] = :no}
49
+ optsParser.on("-y", "--yes", "Assume yes to all questions.") {
50
+ |val| opts[:yn_default] = :yes}
48
51
  optsParser.on("--verbose", "Displays more informations.") {
49
52
  |val| GitMaintain::setVerbose(true)}
50
53
  GitMaintain::setOpts(action, optsParser, opts)
@@ -1,6 +1,7 @@
1
1
  module GitMaintain
2
2
  class RDMACoreBranch < Branch
3
3
  REPO_NAME = "rdma-core"
4
+ AZURE_MIN_VERSION = 18
4
5
 
5
6
  def self.set_opts(action, optsParser, opts)
6
7
  opts[:rel_type] = nil
@@ -15,8 +16,14 @@ module GitMaintain
15
16
  end
16
17
  def self.check_opts(opts)
17
18
  if opts[:action] == :release then
18
- if opts[:rel_type] == nil then
19
+ case opts[:rel_type]
20
+ when nil
19
21
  raise "No release type specified use --stable or --major"
22
+ when :major
23
+ if opts[:manual_branch] == nil then
24
+ GitMaintain::log(:INFO, "Major release selected. Auto-forcing branch to master")
25
+ opts[:manual_branch] = "master"
26
+ end
20
27
  end
21
28
  end
22
29
  end
@@ -64,16 +71,19 @@ module GitMaintain
64
71
  tag_file.puts `git log HEAD ^#{git_prev_ver} --no-merges --format=' * %s'`
65
72
  tag_file.close()
66
73
 
74
+ edit_flag = ""
75
+ edit_flag = "--edit" if opts[:no_edit] == false
76
+
67
77
  if opts[:rel_type] == :major
68
78
  # For major, tag the current version first
69
- @repo.runGitInteractive("tag -a -s v#{rel_ver} --edit -F #{tag_path}")
79
+ @repo.runGitInteractive("tag -a -s v#{rel_ver} #{edit_flag} -F #{tag_path}")
70
80
  if $? != 0 then
71
81
  raise("Failed to tag branch #{local_branch}")
72
82
  end
73
83
  end
74
84
 
75
85
  # Update version number in relevant files
76
- @repo.run("sed -i -e 's/\\(Version:[[:space:]]*\\)[0-9.]\\+/\\1#{new_ver}/g' redhat/rdma-core.spec suse/rdma-core.spec")
86
+ @repo.run("sed -i -e 's/\\(Version:[[:space:]]*\\)[0-9.]\\+/\\1#{new_ver}/g' */*.spec")
77
87
  @repo.run("sed -i -e 's/\\([sS][eE][tT](PACKAGE_VERSION[[:space:]]*\"\\)[0-9.]*\"/\\1#{new_ver}\"/g' CMakeLists.txt")
78
88
 
79
89
  case opts[:rel_type]
@@ -93,14 +103,14 @@ mv debian/changelog.new debian/changelog")
93
103
  end
94
104
 
95
105
  # Add and commit
96
- @repo.runGit("add redhat/rdma-core.spec suse/rdma-core.spec CMakeLists.txt debian/changelog")
97
- @repo.runGitInteractive("commit -m '#{commit_msg} #{new_ver}' --verbose --edit --signoff")
106
+ @repo.runGit("add */*.spec CMakeLists.txt debian/changelog")
107
+ @repo.runGitInteractive("commit -m '#{commit_msg} #{new_ver}' --verbose #{edit_flag} --signoff")
98
108
  if $? != 0 then
99
109
  raise("Failed to commit on branch #{local_branch}")
100
110
  end
101
111
 
102
112
  if opts[:rel_type] == :stable
103
- @repo.runGitInteractive("tag -a -s v#{rel_ver} --edit -F #{tag_path}")
113
+ @repo.runGitInteractive("tag -a -s v#{rel_ver} #{edit_flag} -F #{tag_path}")
104
114
  if $? != 0 then
105
115
  raise("Failed to tag branch #{local_branch}")
106
116
  end
@@ -108,7 +118,57 @@ mv debian/changelog.new debian/changelog")
108
118
  `rm -f #{tag_path}`
109
119
  end
110
120
  end
121
+ class RDMACoreRepo < Repo
122
+ AZURE_MIN_VERSION = 18
123
+ def submitReleases(opts, new_tags)
124
+ new_tags.each(){|tag|
125
+ next if tag !~ /v([0-9]*)\.[0-9]*/
126
+ major=$1.to_i
127
+ # Starting from v27, do not create the github release ourself as this is done by Azure
128
+ createRelease(opts, tag, major < AZURE_MIN_VERSION)
129
+ }
130
+ end
131
+ end
132
+
133
+ class RDMACoreCI < CI
134
+ AZURE_MIN_VERSION = 18
135
+ def initialize(repo)
136
+ super(repo)
137
+ @travis = GitMaintain::TravisCI.new(repo)
138
+ @azure = GitMaintain::AzureCI.new(repo, 'ucfconsort', 'ucfconsort')
111
139
 
140
+ # Auto generate all CI required methods
141
+ # Wicked ruby tricker to find all the public methods of CI but not of inherited classes
142
+ # to dynamically define these method in the object being created
143
+ (GitMaintain::CI.new(repo).public_methods() - Object.new.public_methods()).each(){|method|
144
+ # Skip specific emptyCache method
145
+ next if method == :emptyCache
146
+
147
+ self.define_singleton_method(method) { |br, *args|
148
+ if br.version =~ /([0-9]+)/
149
+ major=$1.to_i
150
+ elsif br.version == "master"
151
+ major=99999
152
+ else
153
+ raise("Unable to monitor branch #{br} on a CI")
154
+ end
155
+ if major < AZURE_MIN_VERSION
156
+ @travis.send(method, br, *args)
157
+ else
158
+ @azure.send(method, br, *args)
159
+ end
160
+ }
161
+ }
162
+ end
163
+ def emptyCache()
164
+ @travis.emptyCache()
165
+ @azure.emptyCache()
166
+ end
167
+ end
112
168
  GitMaintain::registerCustom(RDMACoreBranch::REPO_NAME,
113
- { GitMaintain::Branch => RDMACoreBranch })
169
+ {
170
+ GitMaintain::Branch => RDMACoreBranch,
171
+ GitMaintain::Repo => RDMACoreRepo,
172
+ GitMaintain::CI => RDMACoreCI,
173
+ })
114
174
  end
@@ -0,0 +1,66 @@
1
+ module GitMaintain
2
+ class GitMaintainBranch < Branch
3
+ REPO_NAME = "git-maintain"
4
+
5
+ def release(opts)
6
+ prev_ver=@repo.runGit("show HEAD:CHANGELOG | grep -A 1 -- '---------' | head -n 2 | tail -n 1 | awk '{ print $1}'").chomp()
7
+ ver_nums = prev_ver.split(".")
8
+
9
+ if opts[:manual_branch] == nil then
10
+ new_ver = (ver_nums[0 .. -2] + [ver_nums[-1].to_i() + 1 ]).join(".")
11
+ git_prev_ver = "v" + (ver_nums[-1] == "0" ? ver_nums[0 .. -2].join(".") : prev_ver)
12
+ else
13
+ new_ver = (ver_nums[0 .. -3] + [ver_nums[-2].to_i() + 1 ] + [ "0" ]).join(".")
14
+ git_prev_ver = "v" + prev_ver
15
+ end
16
+
17
+ changes=@repo.runGit("show HEAD:CHANGELOG | awk ' BEGIN {count=0} {if ($1 == \"------------------\") count++; if (count == 0) print $0}'")
18
+
19
+ puts "Preparing release #{prev_ver} => #{new_ver}"
20
+ rep = GitMaintain::checkLog(opts, @local_branch, git_prev_ver, "release")
21
+ if rep != "y" then
22
+ puts "Skipping release"
23
+ return
24
+ end
25
+
26
+ # Prepare tag message
27
+ tag_path=`mktemp`.chomp()
28
+ puts tag_path
29
+ tag_file = File.open(tag_path, "w+")
30
+ tag_file.puts "git-maintain-#{new_ver}"
31
+ tag_file.puts ""
32
+ tag_file.puts changes
33
+ tag_file.close()
34
+
35
+ @repo.run("cat <<EOF > CHANGELOG.new
36
+ ------------------
37
+ #{new_ver} #{`date '+ (%Y-%m-%d)'`.chomp()}
38
+ ------------------
39
+
40
+ $(cat CHANGELOG)
41
+ EOF
42
+ mv CHANGELOG.new CHANGELOG")
43
+
44
+ # Add and commit
45
+ @repo.runGit("add CHANGELOG")
46
+ @repo.runGitInteractive("commit -F #{tag_path} --verbose --edit --signoff")
47
+ if $? != 0 then
48
+ raise("Failed to commit on branch #{local_branch}")
49
+ end
50
+ @repo.runGitInteractive("tag -a -s v#{new_ver} --edit -F #{tag_path}")
51
+ if $? != 0 then
52
+ raise("Failed to tag branch #{local_branch}")
53
+ end
54
+ `rm -f #{tag_path}`
55
+ end
56
+ end
57
+ class GitMaintainRepo < Repo
58
+ def initialize(path)
59
+ super(path)
60
+ @NOTIFY_RELEASE = false
61
+ end
62
+ end
63
+ GitMaintain::registerCustom(GitMaintainBranch::REPO_NAME,
64
+ { GitMaintain::Branch => GitMaintainBranch,
65
+ GitMaintain::Repo => GitMaintainRepo})
66
+ end
data/lib/azure.rb ADDED
@@ -0,0 +1,98 @@
1
+ module GitMaintain
2
+ class AzureCI < CI
3
+ AZURE_URL='https://dev.azure.com/'
4
+
5
+ def initialize(repo, stable='', valid='')
6
+ super(repo)
7
+ @url = AZURE_URL
8
+ @stable_org=stable
9
+ @valid_org=valid
10
+ end
11
+
12
+ private
13
+ def getState(sha1, resp)
14
+ br = findBranch(sha1, resp)
15
+ return "not found" if br == nil
16
+ return "running" if br["result"] == nil
17
+ return br["result"].to_s()
18
+ end
19
+ def getLog(sha1, resp)
20
+ str=""
21
+ # br = findBranch(sha1, resp)
22
+ # raise("Travis build not found") if br == nil
23
+ # job_id = br["id"].to_s()
24
+ # logs= getJson(@url, "azure_log_list" + job_id,
25
+ # @repo.name + "/_apis/build/builds/#{job_id}/logs?api-version=5.1")
26
+ # 1.upto(logs["count"]) { |x|
27
+ # log(:DEBUG_CI, "Downloading log file #{x}/#{logs["count"]}")
28
+ # nzstr = getJson(@url, "azure_log_" + job_id + '_' + x.to_s(),
29
+ # @repo.name + "/_apis/build/builds/#{job_id}/logs/#{x}?api-version=5.1", false)
30
+ # # This is zipped. We need to extract it
31
+ # }
32
+ return str
33
+ end
34
+ def getTS(sha1, resp)
35
+ br = findBranch(sha1, resp)
36
+ raise("Travis build not found") if br == nil
37
+ return br["started_at"]
38
+ end
39
+ def checkState(sha1, resp)
40
+ st = getState(sha1, resp)
41
+ return st == "passed" || st == "succeeded"
42
+ end
43
+
44
+ def getBrValidJson()
45
+ raise("Validation organisation not provided") if @valid_org == ''
46
+ return getJson(@url + @valid_org + '/',
47
+ :azure_br_valid, @repo.name + '/_apis/build/builds?api-version=5.1')
48
+ end
49
+ def getBrStableJson()
50
+ raise("Stable organisation not provided") if @stable_org == ''
51
+ return getJson(@url + @stable_org + '/',
52
+ :azure_br_stable, @repo.name + '/_apis/build/builds?api-version=5.1')
53
+ end
54
+ def findBranch(sha1, resp)
55
+ log(:DEBUG_CI, "Looking for build for #{sha1}")
56
+ resp["value"].each(){|br|
57
+ commit= br["sourceVersion"]
58
+ raise("Incomplete JSON received from Travis") if commit == nil
59
+ log(:DEBUG_CI, "Found entry for sha #{commit}")
60
+ next if commit != sha1
61
+ return br
62
+ }
63
+ return nil
64
+ end
65
+
66
+ public
67
+ def getValidState(br, sha1)
68
+ return getState(sha1, getBrValidJson())
69
+ end
70
+ def checkValidState(br, sha1)
71
+ return checkState(sha1, getBrValidJson())
72
+ end
73
+ def getValidLog(br, sha1)
74
+ return getLog(sha1, getBrValidJson())
75
+ end
76
+ def getValidTS(br, sha1)
77
+ return getTS(sha1, getBrValidJson())
78
+ end
79
+
80
+ def getStableState(br, sha1)
81
+ return getState(sha1, getBrStableJson())
82
+ end
83
+ def checkStableState(br, sha1)
84
+ return checkState(sha1, getBrStableJson())
85
+ end
86
+ def getStableLog(br, sha1)
87
+ return getLog(sha1, getBrStableJson())
88
+ end
89
+ def getStableTS(br, sha1)
90
+ return getTS(sha1, getBrStableJson())
91
+ end
92
+ def isErrored(br, status)
93
+ # https://docs.microsoft.com/en-us/rest/api/azure/devops/build/builds/list?
94
+ # view=azure-devops-rest-5.1#buildresult
95
+ return status == "failed"
96
+ end
97
+ end
98
+ end