bard 1.8.0 → 1.9.0
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 +4 -4
- data/CLAUDE.md +76 -0
- data/PLUGINS.md +114 -0
- data/README.md +14 -6
- data/features/ci.feature +62 -0
- data/features/deploy_git_workflow.feature +88 -0
- data/features/step_definitions/bard_steps.rb +96 -0
- data/features/support/bard-coverage +16 -0
- data/features/support/env.rb +10 -1
- data/features/support/test_server.rb +2 -1
- data/lib/bard/ci/github_actions.rb +1 -2
- data/lib/bard/ci/jenkins.rb +82 -11
- data/lib/bard/ci/local.rb +6 -6
- data/lib/bard/ci/runner.rb +35 -1
- data/lib/bard/ci.rb +11 -23
- data/lib/bard/cli/ci.rb +45 -38
- data/lib/bard/cli/deploy.rb +40 -8
- data/lib/bard/cli/hurt.rb +10 -15
- data/lib/bard/cli/install.rb +7 -12
- data/lib/bard/cli/open.rb +12 -16
- data/lib/bard/cli/ping.rb +8 -14
- data/lib/bard/cli/run.rb +5 -3
- data/lib/bard/cli/vim.rb +5 -10
- data/lib/bard/cli.rb +7 -12
- data/lib/bard/config.rb +1 -13
- data/lib/bard/github.rb +2 -4
- data/lib/bard/plugin.rb +99 -0
- data/lib/bard/plugins/backup.rb +19 -0
- data/lib/bard/plugins/github_pages.rb +34 -0
- data/lib/bard/plugins/hurt.rb +5 -0
- data/lib/bard/plugins/install.rb +5 -0
- data/lib/bard/plugins/jenkins.rb +6 -0
- data/lib/bard/plugins/new.rb +5 -0
- data/lib/bard/plugins/ping.rb +6 -0
- data/lib/bard/plugins/provision.rb +5 -0
- data/lib/bard/plugins/vim.rb +5 -0
- data/lib/bard/secrets.rb +10 -0
- data/lib/bard/version.rb +1 -1
- data/spec/bard/ci/github_actions_spec.rb +116 -13
- data/spec/bard/ci/jenkins_spec.rb +139 -0
- data/spec/bard/ci/runner_spec.rb +61 -0
- data/spec/bard/cli/ci_spec.rb +34 -8
- data/spec/bard/cli/deploy_spec.rb +20 -8
- data/spec/bard/cli/hurt_spec.rb +2 -2
- data/spec/bard/cli/install_spec.rb +4 -4
- data/spec/bard/cli/open_spec.rb +10 -8
- data/spec/bard/cli/ping_spec.rb +5 -5
- data/spec/bard/cli/run_spec.rb +20 -1
- data/spec/bard/cli/vim_spec.rb +5 -5
- data/spec/bard/github_spec.rb +1 -1
- data/spec/bard/plugin_spec.rb +79 -0
- data/spec/spec_helper.rb +6 -1
- metadata +27 -3
- data/README.rdoc +0 -15
data/lib/bard/ci/jenkins.rb
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
require "json"
|
|
2
2
|
require "bard/ci/runner"
|
|
3
|
+
require "bard/secrets"
|
|
3
4
|
|
|
4
5
|
module Bard
|
|
5
6
|
class CI
|
|
6
7
|
class Jenkins < Runner
|
|
7
|
-
|
|
8
8
|
def exists?
|
|
9
|
-
`curl -s -I #{ci_host}/` =~ /\b200 OK\b/
|
|
9
|
+
`curl -s -I #{ci_host}/` =~ /\b200 OK\b/ or create!
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private def create!
|
|
13
|
+
git_url = `git remote get-url origin`.strip
|
|
14
|
+
config = JOB_CONFIG_XML.sub("GIT_URL", git_url)
|
|
15
|
+
if File.exist?("config/master.key")
|
|
16
|
+
master_key = File.read("config/master.key").strip
|
|
17
|
+
master_key_step = <<~XML.chomp
|
|
18
|
+
<hudson.tasks.Shell>
|
|
19
|
+
<command>echo #{master_key} > config/master.key</command>
|
|
20
|
+
</hudson.tasks.Shell>
|
|
21
|
+
|
|
22
|
+
XML
|
|
23
|
+
config = config.sub("<builders>\n", "<builders>\n #{master_key_step}")
|
|
24
|
+
end
|
|
25
|
+
`curl -s -X POST "http://#{auth}@ci.botandrose.com/createItem?name=#{project_name}" -H "Content-Type: application/xml" -d '#{config}'`
|
|
10
26
|
end
|
|
11
27
|
|
|
12
28
|
def console
|
|
@@ -23,7 +39,7 @@ module Bard
|
|
|
23
39
|
end
|
|
24
40
|
|
|
25
41
|
def start
|
|
26
|
-
command = "curl -s -I -X POST -L '#{ci_host}/buildWithParameters?GIT_REF=#{
|
|
42
|
+
command = "curl -s -I -X POST -L '#{ci_host}/buildWithParameters?GIT_REF=#{branch}'"
|
|
27
43
|
output = `#{command}`
|
|
28
44
|
@queueId = output[%r{Location: .+/queue/item/(\d+)/}, 1].to_i
|
|
29
45
|
end
|
|
@@ -31,7 +47,7 @@ module Bard
|
|
|
31
47
|
def building?
|
|
32
48
|
retry_with_backoff do
|
|
33
49
|
self.last_response = `curl -s #{ci_host}/#{job_id}/api/json?tree=building,result`
|
|
34
|
-
raise "Blank response from CI" if last_response.
|
|
50
|
+
raise "Blank response from CI" if last_response.empty?
|
|
35
51
|
end
|
|
36
52
|
last_response.include? '"building":true'
|
|
37
53
|
end
|
|
@@ -61,9 +77,9 @@ module Bard
|
|
|
61
77
|
private
|
|
62
78
|
|
|
63
79
|
def get_last_time_elapsed
|
|
64
|
-
retry_with_backoff do
|
|
80
|
+
response = retry_with_backoff do
|
|
65
81
|
response = `curl -s #{ci_host}/lastStableBuild/api/xml`
|
|
66
|
-
raise "Blank response from CI" if response.
|
|
82
|
+
raise "Blank response from CI" if response.empty?
|
|
67
83
|
response
|
|
68
84
|
end
|
|
69
85
|
response.match(/<duration>(\d+)<\/duration>/)
|
|
@@ -74,7 +90,7 @@ module Bard
|
|
|
74
90
|
end
|
|
75
91
|
|
|
76
92
|
def auth
|
|
77
|
-
"
|
|
93
|
+
@auth ||= "#{Bard::Secrets.fetch("jenkins-user")}:#{Bard::Secrets.fetch("jenkins-token")}"
|
|
78
94
|
end
|
|
79
95
|
|
|
80
96
|
def ci_host
|
|
@@ -85,8 +101,10 @@ module Bard
|
|
|
85
101
|
retry_with_backoff do
|
|
86
102
|
command = "curl -s -g '#{ci_host}/api/json?depth=1&tree=builds[queueId,number]'"
|
|
87
103
|
output = `#{command}`
|
|
88
|
-
raise "Blank response from CI" if output.
|
|
89
|
-
JSON.parse(output)["builds"]
|
|
104
|
+
raise "Blank response from CI" if output.empty?
|
|
105
|
+
builds = JSON.parse(output)["builds"]
|
|
106
|
+
raise "Build not found in builds list" if builds.empty?
|
|
107
|
+
builds.first["queueId"] == @queueId
|
|
90
108
|
end
|
|
91
109
|
end
|
|
92
110
|
|
|
@@ -94,11 +112,64 @@ module Bard
|
|
|
94
112
|
@job_id ||= begin
|
|
95
113
|
retry_with_backoff do
|
|
96
114
|
output = `curl -s -g '#{ci_host}/api/json?depth=1&tree=builds[queueId,number]'`
|
|
97
|
-
raise "Blank response from CI" if output.
|
|
98
|
-
output[
|
|
115
|
+
raise "Blank response from CI" if output.empty?
|
|
116
|
+
builds = JSON.parse(output)["builds"]
|
|
117
|
+
build = builds.find { |b| b["queueId"] == @queueId }
|
|
118
|
+
build["number"]
|
|
99
119
|
end
|
|
100
120
|
end
|
|
101
121
|
end
|
|
122
|
+
JOB_CONFIG_XML = <<~XML
|
|
123
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
124
|
+
<project>
|
|
125
|
+
<actions/>
|
|
126
|
+
<description></description>
|
|
127
|
+
<keepDependencies>false</keepDependencies>
|
|
128
|
+
<properties>
|
|
129
|
+
<hudson.model.ParametersDefinitionProperty>
|
|
130
|
+
<parameterDefinitions>
|
|
131
|
+
<hudson.model.StringParameterDefinition>
|
|
132
|
+
<name>GIT_REF</name>
|
|
133
|
+
<description></description>
|
|
134
|
+
<defaultValue>master</defaultValue>
|
|
135
|
+
</hudson.model.StringParameterDefinition>
|
|
136
|
+
</parameterDefinitions>
|
|
137
|
+
</hudson.model.ParametersDefinitionProperty>
|
|
138
|
+
</properties>
|
|
139
|
+
<scm class="hudson.plugins.git.GitSCM" plugin="git@3.3.0">
|
|
140
|
+
<configVersion>2</configVersion>
|
|
141
|
+
<userRemoteConfigs>
|
|
142
|
+
<hudson.plugins.git.UserRemoteConfig>
|
|
143
|
+
<url>GIT_URL</url>
|
|
144
|
+
</hudson.plugins.git.UserRemoteConfig>
|
|
145
|
+
</userRemoteConfigs>
|
|
146
|
+
<branches>
|
|
147
|
+
<hudson.plugins.git.BranchSpec>
|
|
148
|
+
<name>$GIT_REF</name>
|
|
149
|
+
</hudson.plugins.git.BranchSpec>
|
|
150
|
+
</branches>
|
|
151
|
+
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
|
|
152
|
+
<submoduleCfg class="list"/>
|
|
153
|
+
<extensions/>
|
|
154
|
+
</scm>
|
|
155
|
+
<canRoam>true</canRoam>
|
|
156
|
+
<disabled>false</disabled>
|
|
157
|
+
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
|
158
|
+
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
|
159
|
+
<triggers/>
|
|
160
|
+
<concurrentBuild>false</concurrentBuild>
|
|
161
|
+
<builders>
|
|
162
|
+
<hudson.tasks.Shell>
|
|
163
|
+
<command>bash -l -c bin/setup</command>
|
|
164
|
+
</hudson.tasks.Shell>
|
|
165
|
+
<hudson.tasks.Shell>
|
|
166
|
+
<command>bash -l -c bin/ci</command>
|
|
167
|
+
</hudson.tasks.Shell>
|
|
168
|
+
</builders>
|
|
169
|
+
<publishers/>
|
|
170
|
+
<buildWrappers/>
|
|
171
|
+
</project>
|
|
172
|
+
XML
|
|
102
173
|
end
|
|
103
174
|
end
|
|
104
175
|
end
|
data/lib/bard/ci/local.rb
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
require "
|
|
1
|
+
require "tempfile"
|
|
2
2
|
require "bard/ci/runner"
|
|
3
3
|
|
|
4
4
|
module Bard
|
|
5
5
|
class CI
|
|
6
6
|
class Local < Runner
|
|
7
|
-
|
|
8
7
|
def exists?
|
|
9
8
|
true
|
|
10
9
|
end
|
|
@@ -16,7 +15,8 @@ module Bard
|
|
|
16
15
|
protected
|
|
17
16
|
|
|
18
17
|
def start
|
|
19
|
-
@
|
|
18
|
+
@output_file = Tempfile.new("bard-ci")
|
|
19
|
+
@wait_thread = Process.detach(spawn("CLEAN=true bin/rake ci", [:out, :err] => @output_file))
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def building?
|
|
@@ -47,9 +47,9 @@ module Bard
|
|
|
47
47
|
sleep(2)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
@
|
|
51
|
-
@console = @
|
|
52
|
-
@
|
|
50
|
+
@output_file.rewind
|
|
51
|
+
@console = @output_file.read
|
|
52
|
+
@output_file.close!
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
end
|
data/lib/bard/ci/runner.rb
CHANGED
|
@@ -6,12 +6,43 @@ module Bard
|
|
|
6
6
|
class Runner < Struct.new(:project_name, :branch, :sha)
|
|
7
7
|
include Retryable
|
|
8
8
|
|
|
9
|
+
@runners = {}
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
attr_reader :runners
|
|
13
|
+
|
|
14
|
+
def inherited(subclass)
|
|
15
|
+
super
|
|
16
|
+
name = extract_runner_name(subclass)
|
|
17
|
+
runners[name] = subclass if name
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def [](name)
|
|
21
|
+
runners[name.to_sym]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Returns the last registered runner (most recently loaded wins)
|
|
25
|
+
def default
|
|
26
|
+
runners.values.last
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def extract_runner_name(klass)
|
|
32
|
+
klass.name&.split("::")&.last
|
|
33
|
+
&.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
34
|
+
&.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
35
|
+
&.downcase
|
|
36
|
+
&.to_sym
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
9
40
|
def run
|
|
10
41
|
start
|
|
11
42
|
@start_time = Time.new.to_i
|
|
12
43
|
@last_time_elapsed = get_last_time_elapsed
|
|
13
44
|
save_state
|
|
14
|
-
wait_until_started
|
|
45
|
+
wait_until_started
|
|
15
46
|
|
|
16
47
|
poll_until_complete { |elapsed, last_time| yield elapsed, last_time }
|
|
17
48
|
|
|
@@ -62,6 +93,9 @@ module Bard
|
|
|
62
93
|
raise NotImplementedError, "#{self.class}#success? not implemented"
|
|
63
94
|
end
|
|
64
95
|
|
|
96
|
+
def wait_until_started
|
|
97
|
+
end
|
|
98
|
+
|
|
65
99
|
def get_last_time_elapsed
|
|
66
100
|
nil
|
|
67
101
|
end
|
data/lib/bard/ci.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
require "forwardable"
|
|
2
|
+
require "bard/ci/runner"
|
|
2
3
|
|
|
3
4
|
module Bard
|
|
4
5
|
class CI
|
|
5
|
-
def initialize
|
|
6
|
+
def initialize(project_name, branch, runner_name: nil)
|
|
6
7
|
@project_name = project_name
|
|
7
8
|
@branch = branch
|
|
8
|
-
@
|
|
9
|
+
@runner_name = runner_name
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
extend Forwardable
|
|
@@ -13,18 +14,6 @@ module Bard
|
|
|
13
14
|
|
|
14
15
|
private
|
|
15
16
|
|
|
16
|
-
def local?
|
|
17
|
-
@local
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def github_actions?
|
|
21
|
-
File.exist?(".github/workflows/ci.yml")
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def jenkins?
|
|
25
|
-
!local? && !github_actions?
|
|
26
|
-
end
|
|
27
|
-
|
|
28
17
|
def runner
|
|
29
18
|
@runner ||= choose_runner_class.new(@project_name, @branch, sha)
|
|
30
19
|
end
|
|
@@ -34,15 +23,14 @@ module Bard
|
|
|
34
23
|
end
|
|
35
24
|
|
|
36
25
|
def choose_runner_class
|
|
37
|
-
if
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Jenkins
|
|
26
|
+
if @runner_name
|
|
27
|
+
runner_class = Runner[@runner_name]
|
|
28
|
+
raise "Unknown CI runner: #{@runner_name}" unless runner_class
|
|
29
|
+
runner_class
|
|
30
|
+
else
|
|
31
|
+
runner_class = Runner.default
|
|
32
|
+
raise "No CI runner available" unless runner_class
|
|
33
|
+
runner_class
|
|
46
34
|
end
|
|
47
35
|
end
|
|
48
36
|
end
|
data/lib/bard/cli/ci.rb
CHANGED
|
@@ -6,56 +6,63 @@ module Bard::CLI::CI
|
|
|
6
6
|
mod.class_eval do
|
|
7
7
|
|
|
8
8
|
option :"local-ci", type: :boolean
|
|
9
|
+
option :ci, type: :string
|
|
9
10
|
option :status, type: :boolean
|
|
10
11
|
option :resume, type: :boolean
|
|
11
12
|
desc "ci [branch=HEAD]", "runs ci against BRANCH"
|
|
12
13
|
def ci branch=Bard::Git.current_branch
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
runner_name = if options["local-ci"]
|
|
15
|
+
:local
|
|
16
|
+
elsif options["ci"]
|
|
17
|
+
options["ci"].to_sym
|
|
18
|
+
else
|
|
19
|
+
config.ci
|
|
20
|
+
end
|
|
21
|
+
ci = Bard::CI.new(project_name, branch, runner_name: runner_name)
|
|
22
|
+
unless ci.exists?
|
|
23
|
+
puts red("No CI found for #{project_name}!")
|
|
24
|
+
puts "Re-run with --skip-ci to bypass CI, if you absolutely must, and know what you're doing."
|
|
25
|
+
exit 1
|
|
26
|
+
end
|
|
16
27
|
|
|
17
|
-
|
|
18
|
-
puts "Continuous integration: resuming build..."
|
|
19
|
-
success = ci.resume do |elapsed_time, last_time|
|
|
20
|
-
if last_time
|
|
21
|
-
percentage = (elapsed_time.to_f / last_time.to_f * 100).to_i
|
|
22
|
-
output = " Estimated completion: #{percentage}%"
|
|
23
|
-
else
|
|
24
|
-
output = " No estimated completion time. Elapsed time: #{elapsed_time} sec"
|
|
25
|
-
end
|
|
26
|
-
print "\x08" * output.length
|
|
27
|
-
print output
|
|
28
|
-
$stdout.flush
|
|
29
|
-
end
|
|
30
|
-
else
|
|
31
|
-
puts "Continuous integration: starting build on #{branch}..."
|
|
28
|
+
return puts ci.status if options["status"]
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
print output
|
|
42
|
-
$stdout.flush
|
|
30
|
+
if options["resume"]
|
|
31
|
+
puts "Continuous integration: resuming build..."
|
|
32
|
+
success = ci.resume do |elapsed_time, last_time|
|
|
33
|
+
if last_time
|
|
34
|
+
percentage = (elapsed_time.to_f / last_time.to_f * 100).to_i
|
|
35
|
+
output = " Estimated completion: #{percentage}%"
|
|
36
|
+
else
|
|
37
|
+
output = " No estimated completion time. Elapsed time: #{elapsed_time} sec"
|
|
43
38
|
end
|
|
39
|
+
print "\x08" * output.length
|
|
40
|
+
print output
|
|
41
|
+
$stdout.flush
|
|
44
42
|
end
|
|
43
|
+
else
|
|
44
|
+
puts "Continuous integration: starting build on #{branch}..."
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
success = ci.run do |elapsed_time, last_time|
|
|
47
|
+
if last_time
|
|
48
|
+
percentage = (elapsed_time.to_f / last_time.to_f * 100).to_i
|
|
49
|
+
output = " Estimated completion: #{percentage}%"
|
|
50
|
+
else
|
|
51
|
+
output = " No estimated completion time. Elapsed time: #{elapsed_time} sec"
|
|
52
|
+
end
|
|
53
|
+
print "\x08" * output.length
|
|
54
|
+
print output
|
|
55
|
+
$stdout.flush
|
|
54
56
|
end
|
|
57
|
+
end
|
|
55
58
|
|
|
59
|
+
if success
|
|
60
|
+
puts
|
|
61
|
+
puts "Continuous integration: success!"
|
|
56
62
|
else
|
|
57
|
-
puts
|
|
58
|
-
puts
|
|
63
|
+
puts
|
|
64
|
+
puts ci.console
|
|
65
|
+
puts red("Automated tests failed!")
|
|
59
66
|
exit 1
|
|
60
67
|
end
|
|
61
68
|
end
|
data/lib/bard/cli/deploy.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require "bard/git"
|
|
2
2
|
require "bard/command"
|
|
3
3
|
require "bard/github_pages"
|
|
4
|
+
require "tmpdir"
|
|
4
5
|
|
|
5
6
|
module Bard::CLI::Deploy
|
|
6
7
|
def self.included mod
|
|
@@ -8,37 +9,68 @@ module Bard::CLI::Deploy
|
|
|
8
9
|
|
|
9
10
|
option :"skip-ci", type: :boolean
|
|
10
11
|
option :"local-ci", type: :boolean
|
|
12
|
+
option :ci, type: :string
|
|
11
13
|
option :clone, type: :boolean
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
option :target, type: :string, default: "production"
|
|
15
|
+
desc "deploy [BRANCH]", "deploys branch to target (default: current branch to production)"
|
|
16
|
+
def deploy branch=nil
|
|
17
|
+
branch ||= Bard::Git.current_branch
|
|
15
18
|
|
|
16
19
|
if branch == "master"
|
|
17
20
|
if !Bard::Git.up_to_date_with_remote?(branch)
|
|
18
21
|
run! "git push origin #{branch}:#{branch}"
|
|
19
22
|
end
|
|
20
|
-
invoke :ci, [branch], options.slice("local-ci") unless options["skip-ci"]
|
|
23
|
+
invoke :ci, [branch], options.slice("local-ci", "ci") unless options["skip-ci"]
|
|
21
24
|
|
|
22
25
|
else
|
|
23
|
-
run! "git fetch origin
|
|
26
|
+
run! "git fetch origin"
|
|
27
|
+
if Bard::Git.current_branch != "master"
|
|
28
|
+
run! "git fetch origin master:master"
|
|
29
|
+
end
|
|
24
30
|
|
|
25
31
|
unless Bard::Git.fast_forward_merge?("origin/master", branch)
|
|
26
32
|
puts "The master branch has advanced. Attempting rebase..."
|
|
27
|
-
|
|
33
|
+
if branch == Bard::Git.current_branch
|
|
34
|
+
run! "git rebase origin/master"
|
|
35
|
+
else
|
|
36
|
+
tmpdir = Dir.mktmpdir("bard-rebase")
|
|
37
|
+
begin
|
|
38
|
+
run! "git worktree add --detach #{tmpdir} #{branch}"
|
|
39
|
+
success = Dir.chdir(tmpdir) { system("git rebase origin/master") }
|
|
40
|
+
rebased_sha = Dir.chdir(tmpdir) { `git rev-parse HEAD`.strip } if success
|
|
41
|
+
run! "git worktree remove #{tmpdir} --force"
|
|
42
|
+
unless success
|
|
43
|
+
puts red("!!! ") + "Rebase failed due to conflicts."
|
|
44
|
+
puts "Please rebase #{branch} manually:"
|
|
45
|
+
puts " git checkout #{branch}"
|
|
46
|
+
puts " git rebase origin/master"
|
|
47
|
+
exit 1
|
|
48
|
+
end
|
|
49
|
+
run! "git branch -f #{branch} #{rebased_sha}"
|
|
50
|
+
ensure
|
|
51
|
+
FileUtils.rm_rf(tmpdir) if Dir.exist?(tmpdir)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
28
54
|
end
|
|
29
55
|
|
|
30
56
|
run! "git push -f origin #{branch}:#{branch}"
|
|
31
57
|
|
|
32
|
-
invoke :ci, [branch], options.slice("local-ci") unless options["skip-ci"]
|
|
58
|
+
invoke :ci, [branch], options.slice("local-ci", "ci") unless options["skip-ci"]
|
|
33
59
|
|
|
34
60
|
run! "git push origin #{branch}:master"
|
|
35
|
-
|
|
61
|
+
if Bard::Git.current_branch != "master"
|
|
62
|
+
run! "git fetch origin master:master"
|
|
63
|
+
else
|
|
64
|
+
run! "git pull origin master"
|
|
65
|
+
end
|
|
36
66
|
end
|
|
37
67
|
|
|
38
68
|
if `git remote` =~ /\bgithub\b/
|
|
39
69
|
run! "git push github"
|
|
40
70
|
end
|
|
41
71
|
|
|
72
|
+
to = options[:target].to_sym
|
|
73
|
+
|
|
42
74
|
if options[:clone]
|
|
43
75
|
config[to].run! "git clone git@github.com:botandrosedesign/#{project_name} #{config[to].path}", home: true
|
|
44
76
|
invoke :master_key, [], from: "local", to: to
|
data/lib/bard/cli/hurt.rb
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
def self.included mod
|
|
3
|
-
mod.class_eval do
|
|
1
|
+
require "bard/cli/command"
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
3
|
+
class Bard::CLI::Hurt < Bard::CLI::Command
|
|
4
|
+
desc "hurt <command>", "reruns a command until it fails"
|
|
5
|
+
def hurt *args
|
|
6
|
+
(1..).each do |count|
|
|
7
|
+
puts "Running attempt #{count}"
|
|
8
|
+
system *args
|
|
9
|
+
unless $?.success?
|
|
10
|
+
puts "Ran #{count-1} times before failing"
|
|
11
|
+
break
|
|
15
12
|
end
|
|
16
|
-
|
|
17
13
|
end
|
|
18
14
|
end
|
|
19
15
|
end
|
|
20
|
-
|
data/lib/bard/cli/install.rb
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
def self.included mod
|
|
3
|
-
mod.class_eval do
|
|
1
|
+
require "bard/cli/command"
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
class Bard::CLI::Install < Bard::CLI::Command
|
|
4
|
+
desc "install", "copies bin/setup and bin/ci scripts into current project."
|
|
5
|
+
def install
|
|
6
|
+
install_files_path = File.expand_path(File.join(__dir__, "../../../install_files"))
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
end
|
|
8
|
+
system "cp -R #{install_files_path}/* bin/"
|
|
9
|
+
system "cp -R #{install_files_path}/.github ./"
|
|
14
10
|
end
|
|
15
11
|
end
|
|
16
|
-
|
data/lib/bard/cli/open.rb
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
def self.included mod
|
|
3
|
-
mod.class_eval do
|
|
1
|
+
require "bard/cli/command"
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
class Bard::CLI::Open < Bard::CLI::Command
|
|
4
|
+
desc "open [server=production]", "opens the url in the web browser."
|
|
5
|
+
def open server=:production
|
|
6
|
+
exec "xdg-open #{open_url server}"
|
|
7
|
+
end
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
private
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
18
|
-
end
|
|
11
|
+
def open_url server
|
|
12
|
+
if server.to_sym == :ci
|
|
13
|
+
"https://github.com/botandrosedesign/#{project_name}/actions/workflows/ci.yml"
|
|
14
|
+
else
|
|
15
|
+
config[server].ping.first
|
|
19
16
|
end
|
|
20
17
|
end
|
|
21
18
|
end
|
|
22
|
-
|
data/lib/bard/cli/ping.rb
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
+
require "bard/cli/command"
|
|
1
2
|
require "bard/ping"
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
down_urls = Bard::Ping.call(config[server])
|
|
11
|
-
down_urls.each { |url| puts "#{url} is down!" }
|
|
12
|
-
exit 1 if down_urls.any?
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
end
|
|
4
|
+
class Bard::CLI::Ping < Bard::CLI::Command
|
|
5
|
+
desc "ping [server=production]", "hits the server over http to verify that its up."
|
|
6
|
+
def ping server=:production
|
|
7
|
+
server = config[server]
|
|
8
|
+
down_urls = Bard::Ping.call(config[server])
|
|
9
|
+
down_urls.each { |url| puts "#{url} is down!" }
|
|
10
|
+
exit 1 if down_urls.any?
|
|
16
11
|
end
|
|
17
12
|
end
|
|
18
|
-
|
data/lib/bard/cli/run.rb
CHANGED
|
@@ -9,10 +9,12 @@ module Bard::CLI::Run
|
|
|
9
9
|
Thor::THOR_RESERVED_WORDS -= ["run"]
|
|
10
10
|
$VERBOSE = original_verbose
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
option :target, type: :string, default: "production"
|
|
13
|
+
option :home, type: :boolean
|
|
14
|
+
desc "run <command>", "run the given command on the specified target"
|
|
13
15
|
def run *args
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
target = config[options[:target].to_sym]
|
|
17
|
+
target.run! *args.join(" "), verbose: true, home: options[:home]
|
|
16
18
|
rescue Bard::Command::Error => e
|
|
17
19
|
puts red("!!! ") + "Running command failed: #{yellow(e.message)}"
|
|
18
20
|
exit 1
|
data/lib/bard/cli/vim.rb
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
def self.included mod
|
|
3
|
-
mod.class_eval do
|
|
1
|
+
require "bard/cli/command"
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
end
|
|
3
|
+
class Bard::CLI::Vim < Bard::CLI::Command
|
|
4
|
+
desc "vim [branch=master]", "open all files that have changed since master"
|
|
5
|
+
def vim branch="master"
|
|
6
|
+
exec "vim -p `(git diff #{branch} --name-only; git ls-files --others --exclude-standard) | grep -v '^app/assets/images/' | grep -v '^app/assets/stylesheets/' | while read f; do [ -f \"$f\" ] && ! file -b \"$f\" | grep -q \"binary\" && echo \"$f\"; done | tac`"
|
|
11
7
|
end
|
|
12
8
|
end
|
|
13
|
-
|