intello-shipit-cli 0.6.0.rc1
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.
- 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
|