intello-shipit-cli 0.6.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rbenv-vars +2 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1 -0
- data/.ruby-style.yml +249 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Guardfile +27 -0
- data/LICENSE +21 -0
- data/README.md +154 -0
- data/Rakefile +6 -0
- data/doc/mr.png +0 -0
- data/exe/shipit +129 -0
- data/lib/shipit/cli/configuration.rb +81 -0
- data/lib/shipit/cli/configuration_file.rb +58 -0
- data/lib/shipit/cli/git.rb +58 -0
- data/lib/shipit/cli/sanitizer.rb +18 -0
- data/lib/shipit/cli/server.rb +48 -0
- data/lib/shipit/cli/version.rb +5 -0
- data/lib/shipit/cli/work.rb +138 -0
- data/lib/shipit/cli.rb +45 -0
- data/lib/shipit/motd +15 -0
- data/script/bootstrap +9 -0
- data/script/console +14 -0
- data/script/package +7 -0
- data/script/release +43 -0
- data/script/test +6 -0
- data/shipit-cli.gemspec +34 -0
- metadata +241 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
module Shipit
|
4
|
+
module Cli
|
5
|
+
# This class maintains all system-wide configuration for *shipit*. It properly
|
6
|
+
# applies the correct source of configuration values based on the different contexts and
|
7
|
+
# also makes sure that compulsory data are not missing.
|
8
|
+
#
|
9
|
+
class Configuration
|
10
|
+
# List of all the configuration attributes stored for use within the gem
|
11
|
+
ATTRIBUTES = [:endpoint, :private_token, :protected_branches]
|
12
|
+
|
13
|
+
attr_accessor :endpoint, :private_token, :protected_branches
|
14
|
+
|
15
|
+
# Apply a configuration hash to a configuration instance
|
16
|
+
#
|
17
|
+
# @example Override one of the configuration attributes
|
18
|
+
# config = Shipit::Cli::Configuration.new
|
19
|
+
# config.apply(private_token: 'supersecret')
|
20
|
+
# config.private_token #=> "supersecret"
|
21
|
+
#
|
22
|
+
# @param attributes [Hash] list of key/values to apply to the configuration
|
23
|
+
# @return [Object] the configuration object
|
24
|
+
#
|
25
|
+
def apply(attributes = {})
|
26
|
+
prepared_attributes = prepare_attributes attributes
|
27
|
+
prepared_attributes.each_pair do |attribute, value|
|
28
|
+
send("#{attribute}=", value)
|
29
|
+
end
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
# The configuration instance formatted as a stringified hash
|
34
|
+
#
|
35
|
+
# @example Override one of the configuration attributes
|
36
|
+
# config = Shipit::Cli::Configuration.new
|
37
|
+
# config.to_hash
|
38
|
+
# #=> { "endpoint" => "https://gitlab.example.com/api/v3", "private_token" => "supersecret" }
|
39
|
+
#
|
40
|
+
# @return [Hash] the configuration object as a Hash
|
41
|
+
#
|
42
|
+
def to_hash
|
43
|
+
config_hash = ATTRIBUTES.inject({}) do |hash, attr|
|
44
|
+
hash["#{attr}"] = instance_variable_get("@#{attr}")
|
45
|
+
hash
|
46
|
+
end
|
47
|
+
Shipit::Cli::Sanitizer.symbolize config_hash
|
48
|
+
end
|
49
|
+
|
50
|
+
# Write a configuration summary to STDOUT, useful for output in the CLI
|
51
|
+
#
|
52
|
+
def to_stdout
|
53
|
+
to_hash.each_pair do |attribute, value|
|
54
|
+
puts format("%-20s %-50s", "#{attribute}:", value)
|
55
|
+
end
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def motd_list
|
60
|
+
File.readlines(File.expand_path('../../motd', __FILE__)).map(&:chomp)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# Symbolize keys and remove nil or duplicate attributes
|
66
|
+
# The attributes usually passed to our configuration class by the CLI
|
67
|
+
# are usually full of duplicates and unconsistant keys, we make sure
|
68
|
+
# to clean up that input, before doing any configuration work.
|
69
|
+
#
|
70
|
+
# @param attributes [Hash] list of key/values
|
71
|
+
# @return [Hash] a clean list of key/values
|
72
|
+
#
|
73
|
+
def prepare_attributes(attributes)
|
74
|
+
# Convert string keys to symbols
|
75
|
+
symboled_attributes = Shipit::Cli::Sanitizer.symbolize attributes
|
76
|
+
# Clean up user_attributes from unwanted, nil and duplicate options
|
77
|
+
symboled_attributes.select { |key, _| ATTRIBUTES.include? key }.delete_if { |_, v| v.nil? }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module Shipit
|
4
|
+
module Cli
|
5
|
+
class ConfigurationFile
|
6
|
+
ATTR_READER = [:endpoint, :private_token, :protected_branches]
|
7
|
+
attr_reader(*ATTR_READER)
|
8
|
+
|
9
|
+
def initialize(path, configuration = nil)
|
10
|
+
@path = path
|
11
|
+
@file = load_file
|
12
|
+
@configuration = configuration || load_configuration
|
13
|
+
end
|
14
|
+
|
15
|
+
def exist?
|
16
|
+
File.exist?(@path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_hash
|
20
|
+
config_hash = ATTR_READER.inject({}) do |hash, attr|
|
21
|
+
hash["#{attr}"] = instance_variable_get("@#{attr}")
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
Shipit::Cli::Sanitizer.symbolize config_hash
|
25
|
+
end
|
26
|
+
|
27
|
+
def persist
|
28
|
+
File.open(@path, "w") do |f|
|
29
|
+
f.write @configuration.to_yaml
|
30
|
+
end
|
31
|
+
reload!
|
32
|
+
end
|
33
|
+
|
34
|
+
def reload!
|
35
|
+
@file = load_file
|
36
|
+
@configuration = load_configuration
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def load_file
|
42
|
+
if exist?
|
43
|
+
Shipit::Cli::Sanitizer.symbolize YAML.load_file(@path)
|
44
|
+
else
|
45
|
+
{}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def load_configuration
|
50
|
+
if @file
|
51
|
+
ATTR_READER.each do |attr|
|
52
|
+
instance_variable_set "@#{attr}", @file[attr]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Shipit
|
2
|
+
module Cli
|
3
|
+
class Git
|
4
|
+
GIT = ENV["SHIPIT_GIT"] || "git"
|
5
|
+
ORIGIN = ENV["SHIPIT_ORIGIN"] || "origin"
|
6
|
+
VERBOSE = ENV["SHIPIT_GIT_VERBOSE"] ? "--verbose" : "--quiet"
|
7
|
+
|
8
|
+
COMMANDS = {
|
9
|
+
new: {
|
10
|
+
desc: "create new branch `branch`",
|
11
|
+
commands: [
|
12
|
+
'"#{GIT} push #{origin} #{current_branch}:refs/heads/#{branch} --no-verify #{VERBOSE}"',
|
13
|
+
'"#{GIT} fetch #{origin} #{VERBOSE}"',
|
14
|
+
'"#{GIT} branch --track #{branch} #{origin}/#{branch} #{VERBOSE}"',
|
15
|
+
'"#{GIT} checkout #{branch} #{VERBOSE}"',
|
16
|
+
'"#{GIT} commit --allow-empty -m \"#{message}\" #{VERBOSE}"',
|
17
|
+
'"#{GIT} push --no-verify #{VERBOSE}"'
|
18
|
+
]
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
# Ex: Shipit::Cli::Git.run(command: :new, target_branch: "master", branch: "my-new-branch", message: "empty commit")
|
23
|
+
def self.run(opt)
|
24
|
+
if COMMANDS.keys.include?(opt[:command].to_sym)
|
25
|
+
current_branch = opt[:target_branch]
|
26
|
+
branch = opt[:branch]
|
27
|
+
origin = ORIGIN
|
28
|
+
message = opt.fetch(:message, "").gsub("`", "'")
|
29
|
+
dry_run = opt.fetch(:dry_run, false)
|
30
|
+
grepped_protected_branches = Array(Shipit::Cli.config.protected_branches)
|
31
|
+
.push("master")
|
32
|
+
.push("develop")
|
33
|
+
.push(get_current_branch)
|
34
|
+
.uniq.map{ |b| "| grep -v #{b} " }.join
|
35
|
+
COMMANDS[opt[:command].to_sym][:commands].map do |x|
|
36
|
+
command = exec_cmd(eval(x), dry_run)
|
37
|
+
exit_now!("There was an error running the last Git command. See the trace for more info.") if dry_run == false && command == false
|
38
|
+
end
|
39
|
+
else
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.get_current_branch
|
45
|
+
(`#{GIT} branch 2> /dev/null | grep '^\*'`).gsub(/[\*\s]/, "")
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.exec_cmd(str, dry_run = false)
|
49
|
+
return true unless str
|
50
|
+
if dry_run
|
51
|
+
puts " - #{str}"
|
52
|
+
else
|
53
|
+
system("#{str}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Shipit
|
2
|
+
module Cli
|
3
|
+
class Sanitizer
|
4
|
+
def self.symbolize(obj)
|
5
|
+
return obj.inject({}) do |memo, (k, v)|
|
6
|
+
memo.tap { |m| m[k.to_sym] = symbolize(v) }
|
7
|
+
end if obj.is_a? Hash
|
8
|
+
|
9
|
+
return obj.inject([]) do |memo, v|
|
10
|
+
memo << symbolize(v)
|
11
|
+
memo
|
12
|
+
end if obj.is_a? Array
|
13
|
+
|
14
|
+
obj
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "json"
|
2
|
+
require "uri"
|
3
|
+
require "net/http"
|
4
|
+
require "net/https"
|
5
|
+
|
6
|
+
module Shipit
|
7
|
+
module Cli
|
8
|
+
class Server
|
9
|
+
def initialize(url, options = {})
|
10
|
+
@uri = URI(url)
|
11
|
+
@scheme = @uri.scheme || "https"
|
12
|
+
@method = options[:method] || :get
|
13
|
+
@body = options[:body]
|
14
|
+
@private_token = options[:private_token] || Shipit::Cli.config.private_token
|
15
|
+
@authorization_header = "Token #{@private_token}"
|
16
|
+
@http = set_http(@uri, @scheme)
|
17
|
+
end
|
18
|
+
|
19
|
+
def request
|
20
|
+
case @method
|
21
|
+
when :post
|
22
|
+
@request = Net::HTTP::Post.new(@uri.request_uri, initheader = { "Content-Type" => "application/json" })
|
23
|
+
@request.body = @body.to_json
|
24
|
+
else
|
25
|
+
@request = Net::HTTP::Get.new(@uri.request_uri)
|
26
|
+
end
|
27
|
+
|
28
|
+
@request["authorization"] = @authorization_header
|
29
|
+
@request
|
30
|
+
end
|
31
|
+
|
32
|
+
def response
|
33
|
+
@response ||= @http.request(request)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def set_http(uri, scheme)
|
39
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
40
|
+
if scheme == "https"
|
41
|
+
http.use_ssl = true
|
42
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
43
|
+
end
|
44
|
+
http
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require "active_support/all"
|
2
|
+
|
3
|
+
module Shipit
|
4
|
+
module Cli
|
5
|
+
class Work
|
6
|
+
attr_reader :client, :issue_id, :global_options
|
7
|
+
|
8
|
+
# @param issue_id [Integer] The issue GitLab IID
|
9
|
+
# @param target_branch [String] "master", "develop"...
|
10
|
+
# @param global_options [Hash] A hash of options
|
11
|
+
# - dry_run : If true will not perform the commands
|
12
|
+
# - client : an instance of the GitLab client
|
13
|
+
def initialize(issue_id, global_options)
|
14
|
+
@issue_id = issue_id
|
15
|
+
@global_options = global_options
|
16
|
+
@client = global_options.fetch(:client)
|
17
|
+
end
|
18
|
+
|
19
|
+
# 1. Get issue : https://docs.gitlab.com/ee/api/issues.html#single-issue
|
20
|
+
# 2. Validate issue properties
|
21
|
+
# 3. Create branch : https://docs.gitlab.com/ee/api/branches.html#create-repository-branch
|
22
|
+
# 4. First commit : https://docs.gitlab.com/ee/api/commits.html#create-a-commit-with-multiple-files-and-actions
|
23
|
+
# 5. New merge request : https://docs.gitlab.com/ee/api/merge_requests.html#create-mr
|
24
|
+
def perform(target_branch)
|
25
|
+
# 1. Load issue
|
26
|
+
issue = fetch_remote_issue(issue_id).to_hash
|
27
|
+
# 2. Validate issue
|
28
|
+
validate_issue(issue)
|
29
|
+
# 3. Add additional issue attributes
|
30
|
+
enhanced_issue = enhance_issue(issue, target_branch)
|
31
|
+
# 4. Create remote branch & checkout
|
32
|
+
create_source_branch(enhanced_issue)
|
33
|
+
# 5. Create merge request
|
34
|
+
create_merge_request(enhanced_issue)
|
35
|
+
# 6. Motivation!
|
36
|
+
puts ""
|
37
|
+
Shipit::Cli.ascii
|
38
|
+
rescue => e
|
39
|
+
exit_now! e
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Boolean]
|
43
|
+
def dry_run?
|
44
|
+
global_options["dry_run"] == true
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# @param id [Integer] The issue IID to fetch from GitLab
|
50
|
+
def fetch_remote_issue(id)
|
51
|
+
client.issue(project_path, id)
|
52
|
+
rescue Gitlab::Error::NotFound => e
|
53
|
+
exit_now! "Issue #{id} not found for project #{project_name} on the remote GitLab server."
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_source_branch(issue)
|
57
|
+
commands = Shipit::Cli::Git.run(command: :new,
|
58
|
+
branch: issue["source_branch"],
|
59
|
+
message: issue["first_commit_message"],
|
60
|
+
target_branch: issue["target_branch"],
|
61
|
+
dry_run: global_options["dry_run"])
|
62
|
+
raise "There was an error creating your working branch.\nPROTIP: Review the previous trace and fix the errors before retrying." if !dry_run? && commands.any? { |c| c == false }
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_merge_request(issue)
|
66
|
+
return if dry_run?
|
67
|
+
opts = issue.slice("source_branch", "target_branch", "assignee_id", "labels", "milestone_id", "remove_source_branch")
|
68
|
+
client.create_merge_request(project_path,
|
69
|
+
issue["merge_request_title"],
|
70
|
+
opts)
|
71
|
+
rescue Gitlab::Error => e
|
72
|
+
exit_now! "There was a problem creating your merge request on the GitLab server. Please do it manually.\nError : #{e.message}"
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param issue [Hash] A hash of properties
|
76
|
+
# @return true if issue if valid
|
77
|
+
def validate_issue(issue)
|
78
|
+
errors = []
|
79
|
+
errors << "Assignee missing" if issue["assignees"].empty? # returns an array of assignees (Array of hash)
|
80
|
+
errors << "Milestone missing" if issue["milestone"].to_s.empty? # returns a hash with the milestone properties
|
81
|
+
errors << "Labels missing" if issue["labels"].empty? # returns an array of strings
|
82
|
+
exit_now!("Invalid remote GitLab issue. Please fix the following warnings : #{errors.join(", ")}") if errors.any?
|
83
|
+
end
|
84
|
+
|
85
|
+
def enhance_issue(issue, target_branch)
|
86
|
+
# 1. Build properties
|
87
|
+
issue_id = issue["iid"]
|
88
|
+
labels = issue["labels"].join(", ")
|
89
|
+
assignee = issue["assignees"].first
|
90
|
+
sane_title = issue["title"].gsub(/[^0-9A-Za-z ,.]/, '').strip
|
91
|
+
assignee_initials = assignee["name"].split.map(&:first).join.downcase.gsub(/[^a-z]/, '').strip
|
92
|
+
assignee_id = assignee["id"]
|
93
|
+
issue_title = sane_title.parameterize[0..20]
|
94
|
+
first_commit_message = "[#{labels}] Fixes ##{issue_id} - #{sane_title}"
|
95
|
+
mr_title = "[WIP] [#{labels}] ##{issue_id} - #{sane_title}"
|
96
|
+
|
97
|
+
# 2. Add to issue properties
|
98
|
+
issue["source_branch"] = [issue["labels"].first, assignee_initials, issue_id, issue_title].compact.join("-")
|
99
|
+
issue["first_commit_message"] = first_commit_message
|
100
|
+
issue["target_branch"] = target_branch
|
101
|
+
issue["merge_request_title"] = mr_title
|
102
|
+
issue["assignee_id"] = assignee_id
|
103
|
+
issue["milestone_id"] = issue["milestone"]["id"]
|
104
|
+
issue["remove_source_branch"] = true
|
105
|
+
issue["labels"] = labels
|
106
|
+
issue
|
107
|
+
end
|
108
|
+
|
109
|
+
# Branch names are constructed like so :
|
110
|
+
# {label}-{assignee initials}-{issue id}-{issue title}
|
111
|
+
#
|
112
|
+
# @return [String]
|
113
|
+
def define_source_branch_name
|
114
|
+
[first_label, assignee_initials, @id, issue_title].compact.join("-")
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return [String]
|
118
|
+
def project_git_url
|
119
|
+
@project_git_url ||= `git config --local remote.origin.url`.chomp
|
120
|
+
end
|
121
|
+
|
122
|
+
# @return [String]
|
123
|
+
def project_name
|
124
|
+
@project_name ||= project_git_url.split("/").last.gsub(".git", "")
|
125
|
+
end
|
126
|
+
|
127
|
+
# @return [String]
|
128
|
+
def project_namespace
|
129
|
+
@project_namespace ||= project_git_url.split(":").last.split("/").first
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [String]
|
133
|
+
def project_path
|
134
|
+
@project_path ||= [project_namespace, project_name].join("/")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/lib/shipit/cli.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require "shipit/cli/configuration"
|
2
|
+
require "shipit/cli/configuration_file"
|
3
|
+
require "shipit/cli/sanitizer"
|
4
|
+
require "shipit/cli/git"
|
5
|
+
require "shipit/cli/server"
|
6
|
+
require "shipit/cli/version"
|
7
|
+
require "shipit/cli/work"
|
8
|
+
|
9
|
+
module Shipit
|
10
|
+
module Cli
|
11
|
+
class << self
|
12
|
+
# Keep track of the configuration values set after a configuration
|
13
|
+
# has been applied
|
14
|
+
#
|
15
|
+
# @example Return a configuration value
|
16
|
+
# Shipit::Cli.config.foo #=> "bar"
|
17
|
+
#
|
18
|
+
# @return [Object] the configuration object
|
19
|
+
#
|
20
|
+
def config
|
21
|
+
@config ||= Shipit::Cli::Configuration.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def configure(attributes = {})
|
25
|
+
config.apply attributes
|
26
|
+
end
|
27
|
+
|
28
|
+
def ascii
|
29
|
+
label = "*" + @config.motd_list.sample[0..37].upcase.center(38) + "*"
|
30
|
+
|
31
|
+
puts "****************************************"
|
32
|
+
puts label
|
33
|
+
puts "* *"
|
34
|
+
puts "* | | | *"
|
35
|
+
puts "* )_) )_) )_) *"
|
36
|
+
puts "* )___))___))___)\\ *"
|
37
|
+
puts "* )____)____)_____)\\ *"
|
38
|
+
puts "* _____|____|____|____\\__ *"
|
39
|
+
puts "*--------\\ /---------*"
|
40
|
+
puts "* ^^^^^^^^^^^^^^^^^^^^^^ *"
|
41
|
+
puts "****************************************"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/shipit/motd
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
F*CK IT, SHIP IT
|
2
|
+
FAILURE IS ALWAYS AN OPTION
|
3
|
+
I can haz Ship It?
|
4
|
+
I dare you to ship. I dare you!
|
5
|
+
It's hip to ship
|
6
|
+
Keep it simple, ship it fast
|
7
|
+
NEVER GIVE UP, NEVER SURRENDER
|
8
|
+
REAL ARTISTS SHIP
|
9
|
+
Ship it baby!
|
10
|
+
TO ERR IS HUMAN BUT TO ARR IS PIRATE
|
11
|
+
IT'S GOING TO BE ALL RIGHT
|
12
|
+
IT'S GONNA BLOW THEM ALL AWAY
|
13
|
+
Smurferation, Smurferation, Smurf
|
14
|
+
All boundaries are conventions
|
15
|
+
Ship it or die trying
|
data/script/bootstrap
ADDED
data/script/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "shipit/cli"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/script/package
ADDED
data/script/release
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
# Usage: script/release
|
3
|
+
# Build the package, tag a commit, push it to origin, and then release the
|
4
|
+
# package to our private gem repository.
|
5
|
+
|
6
|
+
# Let's source required ENV variables
|
7
|
+
source .rbenv-vars
|
8
|
+
set -e
|
9
|
+
|
10
|
+
# Get latest tag
|
11
|
+
|
12
|
+
# http://git-scm.com/docs/git-fetch
|
13
|
+
# `-t`: Fetch all tags from the remote
|
14
|
+
echo "Fetching origin with all remote tags..."
|
15
|
+
git fetch -t origin
|
16
|
+
|
17
|
+
latest_tag=$(git describe --always origin/master --abbrev=0 --match="v*")
|
18
|
+
latest_release=${latest_tag:1}
|
19
|
+
echo "Did you update the VERSION in lib/shipit-cli/version.rb ?"
|
20
|
+
read -p "It should be > $latest_release [y/N]: " response
|
21
|
+
|
22
|
+
if [[ $response =~ ^(y|Y)$ ]]; then
|
23
|
+
# Build the gem
|
24
|
+
echo "Preparing the gem package in pkg/*"
|
25
|
+
# Output format: intello-shipit-cli 1.0.2 built to pkg/intello-shipit-cli-1.0.2.gem.
|
26
|
+
version="$(script/package | grep Version: | awk '{print $2}')"
|
27
|
+
# Did we get a version?
|
28
|
+
if [ -z "$version" ]; then echo "You have to give me a semantic tag, like 1.0.0"; exit 1; fi
|
29
|
+
echo "Tagging your code to v$version"
|
30
|
+
echo ""
|
31
|
+
|
32
|
+
echo "Make sure you are GPG ready."
|
33
|
+
echo "You should have run this at one point:"
|
34
|
+
echo "$ git config --global user.signingkey [gpg-key-id]"
|
35
|
+
git tag -s "v$version" -m "Release v$version"
|
36
|
+
git push origin
|
37
|
+
git push origin "v$version"
|
38
|
+
echo ""
|
39
|
+
echo "Publishing to remote gem repository."
|
40
|
+
gem push pkg/intello-shipit-cli-${version}.gem
|
41
|
+
else
|
42
|
+
echo "You canceled the operation, nothing was done."
|
43
|
+
fi
|
data/script/test
ADDED
data/shipit-cli.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "shipit/cli/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "intello-shipit-cli"
|
8
|
+
spec.version = Shipit::Cli::VERSION
|
9
|
+
spec.authors = ["Benjamin Thouret"]
|
10
|
+
spec.email = ["benjamin.thouret@intello.com"]
|
11
|
+
|
12
|
+
spec.summary = %w{Designed to simplify working with Gitlab,
|
13
|
+
its main purpose is to kickstart working on an issue.}
|
14
|
+
spec.homepage = "https://gitlab.com/intello/shipit-cli"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activesupport"
|
22
|
+
spec.add_dependency "gli", "~> 2.13"
|
23
|
+
spec.add_dependency "gitlab", "~> 4.3.0"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 2.0.1"
|
26
|
+
spec.add_development_dependency "guard"
|
27
|
+
spec.add_development_dependency "guard-ctags-bundler"
|
28
|
+
spec.add_development_dependency "guard-rspec"
|
29
|
+
spec.add_development_dependency "guard-rubocop"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
spec.add_development_dependency "rspec"
|
32
|
+
spec.add_development_dependency "rubocop"
|
33
|
+
spec.add_development_dependency "simplecov"
|
34
|
+
end
|