git-maintain 0.7.0 → 0.9.0rc1

Sign up to get free protection for your applications and to get access to all the features.
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