bard 2.0.0.beta → 2.0.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.
Files changed (174) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +6 -1
  3. data/CLAUDE.md +76 -0
  4. data/MIGRATION_GUIDE.md +24 -9
  5. data/PLUGINS.md +99 -0
  6. data/README.md +14 -6
  7. data/Rakefile +3 -1
  8. data/bard.gemspec +2 -1
  9. data/cucumber.yml +1 -0
  10. data/features/ci.feature +63 -0
  11. data/features/data.feature +13 -0
  12. data/features/deploy.feature +14 -0
  13. data/features/deploy_git_workflow.feature +89 -0
  14. data/features/run.feature +14 -0
  15. data/features/step_definitions/bard_steps.rb +136 -0
  16. data/features/support/bard-coverage +16 -0
  17. data/features/support/env.rb +14 -39
  18. data/features/support/test_server.rb +216 -0
  19. data/lib/bard/cli.rb +14 -31
  20. data/lib/bard/command.rb +10 -69
  21. data/lib/bard/config.rb +40 -183
  22. data/lib/bard/copy.rb +28 -103
  23. data/lib/bard/plugins/data.rb +56 -0
  24. data/lib/bard/{ci → plugins/deploy/ci}/github_actions.rb +3 -4
  25. data/lib/bard/plugins/deploy/ci/jenkins.rb +176 -0
  26. data/lib/bard/{ci → plugins/deploy/ci}/local.rb +7 -7
  27. data/lib/bard/{ci → plugins/deploy/ci}/runner.rb +38 -4
  28. data/lib/bard/plugins/deploy/ci.rb +38 -0
  29. data/lib/bard/plugins/deploy/ssh_strategy.rb +27 -0
  30. data/lib/bard/{deploy_strategy.rb → plugins/deploy/strategy.rb} +1 -1
  31. data/lib/bard/plugins/deploy.rb +240 -0
  32. data/lib/bard/{git.rb → plugins/git.rb} +6 -3
  33. data/lib/bard/{github.rb → plugins/github.rb} +4 -6
  34. data/lib/bard/{deploy_strategy/github_pages.rb → plugins/github_pages/strategy.rb} +13 -6
  35. data/lib/bard/plugins/github_pages.rb +30 -0
  36. data/lib/bard/plugins/hurt.rb +13 -0
  37. data/{install_files → lib/bard/plugins/install}/.github/dependabot.yml +2 -1
  38. data/{install_files → lib/bard/plugins/install}/.github/workflows/cache-ci.yml +1 -1
  39. data/{install_files → lib/bard/plugins/install}/.github/workflows/ci.yml +2 -2
  40. data/lib/bard/plugins/install.rb +9 -0
  41. data/lib/bard/plugins/open.rb +20 -0
  42. data/lib/bard/{ping.rb → plugins/ping/check.rb} +4 -4
  43. data/lib/bard/plugins/ping/target_methods.rb +23 -0
  44. data/lib/bard/plugins/ping.rb +10 -0
  45. data/lib/bard/plugins/run.rb +19 -0
  46. data/lib/bard/plugins/setup.rb +54 -0
  47. data/lib/bard/plugins/ssh/connection.rb +75 -0
  48. data/lib/bard/plugins/ssh/copy.rb +95 -0
  49. data/lib/bard/{ssh_server.rb → plugins/ssh/server.rb} +17 -42
  50. data/lib/bard/plugins/ssh/target_methods.rb +20 -0
  51. data/lib/bard/plugins/ssh.rb +10 -0
  52. data/lib/bard/plugins/url/target_methods.rb +23 -0
  53. data/lib/bard/plugins/url.rb +1 -0
  54. data/lib/bard/plugins/vim.rb +6 -0
  55. data/lib/bard/retryable.rb +25 -0
  56. data/lib/bard/secrets.rb +10 -0
  57. data/lib/bard/target.rb +27 -185
  58. data/lib/bard/version.rb +1 -1
  59. data/lib/bard.rb +1 -3
  60. data/spec/acceptance/docker/Dockerfile +3 -2
  61. data/spec/bard/capability_spec.rb +8 -50
  62. data/spec/bard/ci/github_actions_spec.rb +117 -14
  63. data/spec/bard/ci/jenkins_spec.rb +139 -0
  64. data/spec/bard/ci/runner_spec.rb +61 -0
  65. data/spec/bard/ci_spec.rb +1 -1
  66. data/spec/bard/cli/ci_spec.rb +34 -27
  67. data/spec/bard/cli/data_spec.rb +7 -26
  68. data/spec/bard/cli/deploy_spec.rb +87 -46
  69. data/spec/bard/cli/hurt_spec.rb +3 -9
  70. data/spec/bard/cli/install_spec.rb +5 -11
  71. data/spec/bard/cli/master_key_spec.rb +5 -19
  72. data/spec/bard/cli/open_spec.rb +14 -30
  73. data/spec/bard/cli/ping_spec.rb +8 -23
  74. data/spec/bard/cli/run_spec.rb +27 -21
  75. data/spec/bard/cli/setup_spec.rb +10 -27
  76. data/spec/bard/cli/ssh_spec.rb +10 -25
  77. data/spec/bard/cli/stage_spec.rb +28 -23
  78. data/spec/bard/cli/vim_spec.rb +3 -9
  79. data/spec/bard/command_spec.rb +1 -8
  80. data/spec/bard/config_spec.rb +78 -98
  81. data/spec/bard/copy_spec.rb +54 -18
  82. data/spec/bard/deploy_strategy/ssh_spec.rb +65 -7
  83. data/spec/bard/deploy_strategy_spec.rb +1 -1
  84. data/spec/bard/dynamic_dsl_spec.rb +18 -98
  85. data/spec/bard/git_spec.rb +9 -5
  86. data/spec/bard/github_spec.rb +2 -2
  87. data/spec/bard/ping_spec.rb +5 -5
  88. data/spec/bard/ssh_copy_spec.rb +44 -0
  89. data/spec/bard/ssh_server_spec.rb +8 -101
  90. data/spec/bard/target_spec.rb +66 -109
  91. data/spec/spec_helper.rb +6 -1
  92. metadata +79 -143
  93. data/README.rdoc +0 -15
  94. data/features/bard_check.feature +0 -94
  95. data/features/bard_deploy.feature +0 -18
  96. data/features/bard_pull.feature +0 -112
  97. data/features/bard_push.feature +0 -112
  98. data/features/podman_testcontainers.feature +0 -16
  99. data/features/step_definitions/check_steps.rb +0 -47
  100. data/features/step_definitions/git_steps.rb +0 -73
  101. data/features/step_definitions/global_steps.rb +0 -56
  102. data/features/step_definitions/podman_steps.rb +0 -23
  103. data/features/step_definitions/rails_steps.rb +0 -44
  104. data/features/step_definitions/submodule_steps.rb +0 -110
  105. data/features/support/grit_ext.rb +0 -13
  106. data/features/support/io.rb +0 -32
  107. data/features/support/podman.rb +0 -153
  108. data/lib/bard/ci/jenkins.rb +0 -105
  109. data/lib/bard/ci/retryable.rb +0 -27
  110. data/lib/bard/ci.rb +0 -50
  111. data/lib/bard/cli/ci.rb +0 -66
  112. data/lib/bard/cli/command.rb +0 -26
  113. data/lib/bard/cli/data.rb +0 -45
  114. data/lib/bard/cli/deploy.rb +0 -85
  115. data/lib/bard/cli/hurt.rb +0 -20
  116. data/lib/bard/cli/install.rb +0 -16
  117. data/lib/bard/cli/master_key.rb +0 -17
  118. data/lib/bard/cli/new.rb +0 -101
  119. data/lib/bard/cli/new_rails_template.rb +0 -197
  120. data/lib/bard/cli/open.rb +0 -22
  121. data/lib/bard/cli/ping.rb +0 -18
  122. data/lib/bard/cli/provision.rb +0 -34
  123. data/lib/bard/cli/run.rb +0 -24
  124. data/lib/bard/cli/setup.rb +0 -56
  125. data/lib/bard/cli/ssh.rb +0 -14
  126. data/lib/bard/cli/stage.rb +0 -27
  127. data/lib/bard/cli/vim.rb +0 -13
  128. data/lib/bard/default_config.rb +0 -35
  129. data/lib/bard/deploy_strategy/ssh.rb +0 -19
  130. data/lib/bard/github_pages.rb +0 -134
  131. data/lib/bard/provision/app.rb +0 -10
  132. data/lib/bard/provision/apt.rb +0 -16
  133. data/lib/bard/provision/authorizedkeys.rb +0 -25
  134. data/lib/bard/provision/data.rb +0 -27
  135. data/lib/bard/provision/deploy.rb +0 -10
  136. data/lib/bard/provision/http.rb +0 -16
  137. data/lib/bard/provision/logrotation.rb +0 -30
  138. data/lib/bard/provision/masterkey.rb +0 -18
  139. data/lib/bard/provision/mysql.rb +0 -22
  140. data/lib/bard/provision/passenger.rb +0 -37
  141. data/lib/bard/provision/repo.rb +0 -72
  142. data/lib/bard/provision/rvm.rb +0 -22
  143. data/lib/bard/provision/ssh.rb +0 -72
  144. data/lib/bard/provision/swapfile.rb +0 -21
  145. data/lib/bard/provision/user.rb +0 -42
  146. data/lib/bard/provision.rb +0 -16
  147. data/lib/bard/server.rb +0 -117
  148. data/spec/bard/cli/command_spec.rb +0 -50
  149. data/spec/bard/cli/new_spec.rb +0 -73
  150. data/spec/bard/cli/provision_spec.rb +0 -42
  151. data/spec/bard/github_pages_spec.rb +0 -143
  152. data/spec/bard/provision/app_spec.rb +0 -33
  153. data/spec/bard/provision/apt_spec.rb +0 -39
  154. data/spec/bard/provision/authorizedkeys_spec.rb +0 -40
  155. data/spec/bard/provision/data_spec.rb +0 -54
  156. data/spec/bard/provision/deploy_spec.rb +0 -33
  157. data/spec/bard/provision/http_spec.rb +0 -57
  158. data/spec/bard/provision/logrotation_spec.rb +0 -34
  159. data/spec/bard/provision/masterkey_spec.rb +0 -63
  160. data/spec/bard/provision/mysql_spec.rb +0 -55
  161. data/spec/bard/provision/passenger_spec.rb +0 -81
  162. data/spec/bard/provision/repo_spec.rb +0 -208
  163. data/spec/bard/provision/rvm_spec.rb +0 -49
  164. data/spec/bard/provision/ssh_spec.rb +0 -229
  165. data/spec/bard/provision/swapfile_spec.rb +0 -32
  166. data/spec/bard/provision/user_spec.rb +0 -103
  167. data/spec/bard/provision_spec.rb +0 -28
  168. data/spec/bard/server_spec.rb +0 -127
  169. /data/lib/bard/{ci → plugins/deploy/ci}/state.rb +0 -0
  170. /data/{install_files → lib/bard/plugins/install}/apt_dependencies.rb +0 -0
  171. /data/{install_files → lib/bard/plugins/install}/ci +0 -0
  172. /data/{install_files → lib/bard/plugins/install}/setup +0 -0
  173. /data/{install_files → lib/bard/plugins/install}/specified_bundler.rb +0 -0
  174. /data/{install_files → lib/bard/plugins/install}/specified_ruby.rb +0 -0
@@ -1,197 +0,0 @@
1
- ruby_version, project_name = (`rvm current name`.chomp).split("@")
2
- rails_version = Gem.loaded_specs["railties"].version
3
-
4
- file ".ruby-version", ruby_version
5
- file ".ruby-gemset", project_name
6
- file ".gitignore", <<~GITIGNORE
7
- # See https://help.github.com/articles/ignoring-files for more about ignoring files.
8
- #
9
- # If you find yourself ignoring temporary files generated by your text editor
10
- # or operating system, you probably want to add a global ignore instead:
11
- # git config --global core.excludesfile '~/.gitignore_global'
12
-
13
- # Ignore bundler config.
14
- /.bundle
15
-
16
- # Ignore all logfiles and tempfiles.
17
- /log/*
18
- /tmp/*
19
- !/log/.keep
20
- !/tmp/.keep
21
-
22
- # Ignore master key for decrypting credentials and more.
23
- /config/master.key
24
-
25
- # ignore coverage reports
26
- /coverage
27
-
28
- # Ignore database dumps
29
- /db/data.*
30
-
31
- # Ignore storage (uploaded files in development and any SQLite databases).
32
- /storage/*
33
-
34
- # Ignore Syncthing
35
- .stfolder/
36
-
37
- # Thank Apple!
38
- .DS_Store
39
- GITIGNORE
40
-
41
- file "Gemfile", <<~RUBY
42
- source "https://rubygems.org"
43
-
44
- gem "bootsnap", require: false
45
- gem "rails", "~> #{rails_version}"
46
- gem "solid_cache"
47
- gem "solid_queue"
48
- gem "solid_cable"
49
- gem "bard-rails"
50
- gem "sqlite3"
51
- gem "image_processing"
52
- gem "puma"
53
- gem "exception_notification"
54
-
55
- # css
56
- gem "sprockets-rails"
57
- gem "dartsass-sprockets"
58
- gem "bard-sass"
59
-
60
- # js
61
- gem "importmap-rails"
62
- gem "turbo-rails"
63
- gem "stimulus-rails"
64
-
65
- group :development do
66
- gem "web-console"
67
- end
68
-
69
- group :development, :test do
70
- gem "debug", require: "debug/prelude"
71
- # gem "parallel_tests", "~>3.9.0" # 3.10 pegs CPU
72
- gem "brakeman", require: false
73
- gem "rubocop-rails-omakase", require: false
74
- end
75
-
76
- group :test do
77
- gem "cucumber-rails", require: false
78
- gem "cuprite-downloads"
79
- gem "capybara-screenshot"
80
- gem "database_cleaner"
81
- gem "chop"
82
- gem "email_spec"
83
- gem "timecop"
84
- gem "rspec-rails"
85
- end
86
-
87
- group :production do
88
- gem "foreman-export-systemd_user"
89
- end
90
- RUBY
91
-
92
- file "config/initializers/exception_notification.rb", <<~RUBY
93
- require "exception_notification/rails"
94
-
95
- ExceptionNotification.configure do |config|
96
- config.ignored_exceptions = []
97
-
98
- # Adds a condition to decide when an exception must be ignored or not.
99
- # The ignore_if method can be invoked multiple times to add extra conditions.
100
- config.ignore_if do |exception, options|
101
- not Rails.env.production?
102
- end
103
-
104
- config.ignore_if do |exception, options|
105
- %w[
106
- ActiveRecord::RecordNotFound
107
- AbstractController::ActionNotFound
108
- ActionController::RoutingError
109
- ActionController::InvalidAuthenticityToken
110
- ActionView::MissingTemplate
111
- ActionController::BadRequest
112
- ActionDispatch::Http::Parameters::ParseError
113
- ActionDispatch::Http::MimeNegotiation::InvalidType
114
- ].include?(exception.class.to_s)
115
- end
116
-
117
- config.add_notifier :email, {
118
- email_prefix: "[\#{File.basename(Dir.pwd)}] ",
119
- exception_recipients: "micah@botandrose.com",
120
- smtp_settings: Rails.application.credentials.exception_notification_smtp_settings,
121
- }
122
- end
123
-
124
- if defined?(Rake::Application)
125
- Rake::Application.prepend Module.new {
126
- def display_error_message error
127
- ExceptionNotifier.notify_exception(error)
128
- super
129
- end
130
-
131
- def invoke_task task_name
132
- super
133
- rescue RuntimeError => exception
134
- if exception.message.starts_with?("Don't know how to build task")
135
- ExceptionNotifier.notify_exception(exception)
136
- end
137
- raise exception
138
- end
139
- }
140
- end
141
-
142
- ActionController::Live.prepend Module.new {
143
- def log_error exception
144
- ExceptionNotifier.notify_exception exception, env: request.env
145
- super
146
- end
147
- }
148
- RUBY
149
-
150
- file "app/assets/config/manifest.js", <<~RUBY
151
- //= link_tree ../images
152
- //= link_directory ../stylesheets .css
153
- //= link_tree ../../javascript .js
154
- RUBY
155
-
156
- run "rm -f app/assets/stylesheets/application.css"
157
-
158
- file "app/assets/stylesheets/application.sass", <<~SASS
159
- body
160
- border: 10px solid red
161
- SASS
162
-
163
- gsub_file "app/views/layouts/application.html.erb", " <%# Includes all stylesheet files in app/assets/stylesheets %>\n", ''
164
- gsub_file "app/views/layouts/application.html.erb", 'stylesheet_link_tag :app,', 'stylesheet_link_tag :application,'
165
-
166
- file "app/views/static/index.html.slim", <<~SLIM
167
- h1 #{project_name}
168
- SLIM
169
-
170
- insert_into_file "config/database.yml", <<~YAML, after: "database: storage/test.sqlite3"
171
-
172
- staging:
173
- <<: *default
174
- database: storage/staging.sqlite3
175
- YAML
176
-
177
- insert_into_file "config/database.yml", <<-YAML, after: "# database: path/to/persistent/storage/production.sqlite3"
178
-
179
- cable:
180
- <<: *default
181
- # database: path/to/persistent/storage/production_cable.sqlite3
182
- migrations_paths: db/cable_migrate
183
- queue:
184
- <<: *default
185
- # database: path/to/persistent/storage/production_queue.sqlite3
186
- migrations_paths: db/queue_migrate
187
- YAML
188
-
189
- gsub_file "config/database.yml", "path/to/persistent/", ""
190
-
191
- gsub_file "config/environments/production.rb", / (config\.logger.+STDOUT.*)$/, ' # \1'
192
-
193
- after_bundle do
194
- run "bard install"
195
- run "bin/setup"
196
- run "bard setup"
197
- end
data/lib/bard/cli/open.rb DELETED
@@ -1,22 +0,0 @@
1
- module Bard::CLI::Open
2
- def self.included mod
3
- mod.class_eval do
4
-
5
- desc "open [server=production]", "opens the url in the web browser."
6
- def open server=:production
7
- exec "xdg-open #{open_url server}"
8
- end
9
-
10
- private
11
-
12
- def open_url server
13
- if server.to_sym == :ci
14
- "https://github.com/botandrosedesign/#{project_name}/actions/workflows/ci.yml"
15
- else
16
- config[server].ping.first
17
- end
18
- end
19
- end
20
- end
21
- end
22
-
data/lib/bard/cli/ping.rb DELETED
@@ -1,18 +0,0 @@
1
- require "bard/ping"
2
-
3
- module Bard::CLI::Ping
4
- def self.included mod
5
- mod.class_eval do
6
-
7
- desc "ping [server=production]", "hits the server over http to verify that its up."
8
- def ping server=:production
9
- server = config[server]
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
16
- end
17
- end
18
-
@@ -1,34 +0,0 @@
1
- require "bard/cli/command"
2
- require "bard/provision"
3
-
4
- class Bard::CLI::Provision < Bard::CLI::Command
5
- STEPS = %w[
6
- SSH
7
- User
8
- AuthorizedKeys
9
- Swapfile
10
- Apt
11
- MySQL
12
- Repo
13
- MasterKey
14
- RVM
15
- App
16
- Passenger
17
- HTTP
18
- LogRotation
19
- Data
20
- Deploy
21
- ]
22
-
23
- desc "provision [ssh_url] --steps=all", "takes an optional ssh url to a raw ubuntu 22.04 install, and readies it in the shape of :production"
24
- option :steps, type: :array, default: STEPS
25
- def provision ssh_url=config[:production].ssh
26
- # unfreeze the string for later mutation
27
- ssh_url = ssh_url.dup
28
- options[:steps].each do |step|
29
- require "bard/provision/#{step.downcase}"
30
- Bard::Provision.const_get(step).call(config, ssh_url)
31
- end
32
- end
33
- end
34
-
data/lib/bard/cli/run.rb DELETED
@@ -1,24 +0,0 @@
1
- require "bard/command"
2
-
3
- module Bard::CLI::Run
4
- def self.included mod
5
- mod.class_eval do
6
-
7
- # HACK: we don't use Thor::Base#run, so its okay to stomp on it here
8
- original_verbose, $VERBOSE = $VERBOSE, nil
9
- Thor::THOR_RESERVED_WORDS -= ["run"]
10
- $VERBOSE = original_verbose
11
-
12
- desc "run <command>", "run the given command on production"
13
- def run *args
14
- server = config[:production]
15
- server.run! *args.join(" "), verbose: true
16
- rescue Bard::Command::Error => e
17
- puts red("!!! ") + "Running command failed: #{yellow(e.message)}"
18
- exit 1
19
- end
20
-
21
- end
22
- end
23
- end
24
-
@@ -1,56 +0,0 @@
1
- require "uri"
2
-
3
- module Bard::CLI::Setup
4
- def self.included mod
5
- mod.class_eval do
6
-
7
- desc "setup", "installs app in nginx"
8
- def setup
9
- system "sudo tee /etc/nginx/snippets/common.conf >/dev/null <<-EOF
10
- listen 80;
11
-
12
- passenger_enabled on;
13
-
14
- location ~* \\.(ico|css|js|gif|jp?g|png|webp) {
15
- access_log off;
16
- if (\\$request_filename ~ \"-[0-9a-f]{32,}\\.\") {
17
- expires max;
18
- add_header Cache-Control public;
19
- }
20
- }
21
-
22
- gzip_static on;
23
- EOF"
24
-
25
- path = "/etc/nginx/sites-available/#{project_name}"
26
- system "sudo tee #{path} >/dev/null <<-EOF
27
- server {
28
- include /etc/nginx/snippets/common.conf;
29
- server_name #{nginx_server_name};
30
- root #{Dir.pwd}/public;
31
- }
32
- EOF"
33
-
34
- dest_path = path.sub("sites-available", "sites-enabled")
35
- system "sudo ln -sf #{path} #{dest_path}" if !File.exist?(dest_path)
36
-
37
- system "sudo service nginx restart"
38
- end
39
-
40
- private
41
-
42
- def nginx_server_name
43
- case ENV["RAILS_ENV"]
44
- when "production"
45
- (config[:production].ping.map do |str|
46
- "*.#{URI.parse(str).host}"
47
- end + ["_"]).join(" ")
48
- when "staging" then "#{project_name}.botandrose.com"
49
- else "#{project_name}.localhost"
50
- end
51
- end
52
-
53
- end
54
- end
55
- end
56
-
data/lib/bard/cli/ssh.rb DELETED
@@ -1,14 +0,0 @@
1
- module Bard::CLI::SSH
2
- def self.included mod
3
- mod.class_eval do
4
-
5
- option :home, type: :boolean
6
- desc "ssh [to=production]", "logs into the specified server via SSH"
7
- def ssh to=:production
8
- config[to].exec! "exec $SHELL -l", home: options[:home]
9
- end
10
-
11
- end
12
- end
13
- end
14
-
@@ -1,27 +0,0 @@
1
- require "bard/git"
2
- require "bard/command"
3
-
4
- module Bard::CLI::Stage
5
- def self.included mod
6
- mod.class_eval do
7
-
8
- desc "stage [branch=HEAD]", "pushes current branch, and stages it"
9
- def stage branch=Bard::Git.current_branch
10
- unless config.servers.key?(:production)
11
- raise Thor::Error.new("`bard stage` is disabled until a production server is defined. Until then, please use `bard deploy` to deploy to the staging server.")
12
- end
13
-
14
- run! "git push -u origin #{branch}", verbose: true
15
- config[:staging].run! "git fetch && git checkout -f origin/#{branch} && bin/setup"
16
- puts green("Stage Succeeded")
17
-
18
- ping :staging
19
- rescue Bard::Command::Error => e
20
- puts red("!!! ") + "Running command failed: #{yellow(e.message)}"
21
- exit 1
22
- end
23
-
24
- end
25
- end
26
- end
27
-
data/lib/bard/cli/vim.rb DELETED
@@ -1,13 +0,0 @@
1
- module Bard::CLI::Vim
2
- def self.included mod
3
- mod.class_eval do
4
-
5
- desc "vim [branch=master]", "open all files that have changed since master"
6
- def vim branch="master"
7
- 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`"
8
- end
9
-
10
- end
11
- end
12
- end
13
-
@@ -1,35 +0,0 @@
1
- module Bard
2
- # Default configuration that is loaded before user's bard.rb
3
- # Users can override any of these targets in their bard.rb
4
- DEFAULT_CONFIG = lambda do |config, project_name|
5
- # Local development target
6
- config.instance_eval do
7
- target :local do
8
- ssh false
9
- path "./"
10
- ping "#{project_name}.local"
11
- end
12
-
13
- # Bot and Rose cloud server
14
- target :gubs do
15
- ssh "botandrose@cloud.hackett.world:22022",
16
- path: "Sites/#{project_name}"
17
- ping false
18
- end
19
-
20
- # CI target (Jenkins)
21
- target :ci do
22
- ssh "jenkins@staging.botandrose.com:22022",
23
- path: "jobs/#{project_name}/workspace"
24
- ping false
25
- end
26
-
27
- # Staging server
28
- target :staging do
29
- ssh "www@staging.botandrose.com:22022",
30
- path: project_name
31
- ping "#{project_name}.botandrose.com"
32
- end
33
- end
34
- end
35
- end
@@ -1,19 +0,0 @@
1
- require "bard/deploy_strategy"
2
-
3
- module Bard
4
- class DeployStrategy
5
- class SSH < DeployStrategy
6
- def deploy
7
- # Require SSH capability
8
- target.require_capability!(:ssh)
9
-
10
- # Determine branch
11
- branch = target.instance_variable_get(:@branch) || "master"
12
-
13
- # Run git pull and setup on remote server
14
- target.run! "git pull origin #{branch}"
15
- target.run! "bin/setup"
16
- end
17
- end
18
- end
19
- end
@@ -1,134 +0,0 @@
1
- require 'delegate'
2
- require 'fileutils'
3
- require 'bard/git'
4
-
5
- module Bard
6
- class GithubPages < SimpleDelegator
7
- def deploy server
8
- @sha = Git.sha_of(Git.current_branch)
9
- @build_dir = "tmp/github-build-#{@sha}"
10
- @branch = "gh-pages"
11
- @domain = server.ping.first
12
- @domain = URI.parse(@domain).hostname if @domain
13
-
14
- puts "Starting deployment to GitHub Pages..."
15
-
16
- build_site
17
- tree_sha = create_tree_from_build
18
- new_commit = create_commit(tree_sha)
19
- commit_and_push new_commit
20
- end
21
-
22
- private
23
-
24
- def build_site
25
- with_locked_port do |port|
26
- system "rm -rf #{@build_dir.sub(@sha, "*")}"
27
- run! <<~SH
28
- set -e
29
- RAILS_ENV=production bundle exec rails s -p #{port} -d --pid tmp/pids/server.pid
30
- OUTPUT=$(bundle exec rake assets:clean assets:precompile 2>&1) || echo "$OUTPUT"
31
-
32
- # Create the output directory and enter it
33
- BUILD=#{@build_dir}
34
- rm -rf $BUILD
35
- mkdir -p $BUILD
36
- cp -R public/assets $BUILD/
37
- cd $BUILD
38
-
39
- # wait until server responds
40
- echo waiting...
41
- curl -s --retry 5 --retry-delay 2 http://localhost:#{port} >/dev/null 2>&1
42
-
43
- echo copying...
44
- # Mirror the site to the build folder, ignoring links with query params
45
- wget -nv -r -l inf --no-remove-listing -FEnH --reject-regex "(\\.*)\\?(.*)" http://localhost:#{port}/ 2>&1
46
-
47
- echo #{@domain} > CNAME
48
- SH
49
- ensure # cleanup
50
- run! <<~SH
51
- cat tmp/pids/server.pid | xargs -I {} kill {}
52
- rm -rf public/assets
53
- SH
54
- end
55
- end
56
-
57
- def with_locked_port
58
- (3000..3020).each do |port|
59
- lock_file = "/tmp/bard_github_pages_#{port}.lock"
60
- file = File.open(lock_file, File::RDWR | File::CREAT, 0644)
61
- if file.flock(File::LOCK_EX | File::LOCK_NB)
62
- begin
63
- yield port
64
- return
65
- ensure
66
- file.flock(File::LOCK_UN)
67
- file.close
68
- end
69
- else
70
- file.close
71
- end
72
- end
73
- raise "Could not find an available port for GitHub Pages deployment (checked 3000-3020)."
74
- end
75
-
76
- def create_tree_from_build
77
- # Create temporary index
78
- git_index_file = ".git/tmp-index"
79
- git = "GIT_INDEX_FILE=#{git_index_file} git"
80
- run! "#{git} read-tree --empty"
81
-
82
- # Add build files to temporary index
83
- Dir.chdir(@build_dir) do
84
- Dir.glob('**/*', File::FNM_DOTMATCH).each do |file|
85
- next if file == '.' || file == '..'
86
- if File.file?(file)
87
- run! "#{git} update-index --add --cacheinfo 100644 $(#{git} hash-object -w #{file}) #{file}"
88
- end
89
- end
90
- end
91
-
92
- # Create tree object from index
93
- tree_sha = `#{git} write-tree`.chomp
94
-
95
- # Clean up temporary index
96
- FileUtils.rm_f(git_index_file)
97
-
98
- tree_sha
99
- end
100
-
101
- def create_commit tree_sha
102
- # Get parent commit if branch exists
103
- parent = get_parent_commit
104
-
105
- # Create commit object
106
- message = "'Deploying to #{@branch} from @ #{@sha} 🚀'"
107
- args = ['commit-tree', tree_sha]
108
- args += ['-p', parent] if parent
109
- args += ['-m', message]
110
-
111
- commit_sha = `git #{args.join(' ')}`.chomp
112
-
113
- commit_sha
114
- end
115
-
116
- def get_parent_commit
117
- Git.sha_of("#{@branch}^{commit}")
118
- end
119
-
120
- def commit_and_push commit_sha
121
- if branch_exists?
122
- run! "git update-ref refs/heads/#{@branch} #{commit_sha}"
123
- else
124
- run! "git branch #{@branch} #{commit_sha}"
125
- end
126
- run! "git push -f origin #{@branch}:refs/heads/#{@branch}"
127
- end
128
-
129
- def branch_exists?
130
- system("git show-ref --verify --quiet refs/heads/#{@branch}")
131
- end
132
- end
133
- end
134
-
@@ -1,10 +0,0 @@
1
- # run bin/setup
2
-
3
- class Bard::Provision::App < Bard::Provision
4
- def call
5
- print "App:"
6
- provision_server.run! "bin/setup"
7
- puts " ✓"
8
- end
9
- end
10
-
@@ -1,16 +0,0 @@
1
- # apt sanity
2
-
3
- class Bard::Provision::Apt < Bard::Provision
4
- def call
5
- print "Apt:"
6
- provision_server.run! [
7
- %(echo "\\$nrconf{restart} = \\"a\\";" | sudo tee /etc/needrestart/conf.d/90-autorestart.conf),
8
- "sudo apt-get update -y",
9
- "sudo apt-get upgrade -y",
10
- "sudo apt-get install -y curl",
11
- ].join("; "), home: true
12
-
13
- puts " ✓"
14
- end
15
- end
16
-
@@ -1,25 +0,0 @@
1
- # install public keys if missing
2
-
3
- class Bard::Provision::AuthorizedKeys < Bard::Provision
4
- def call
5
- print "Authorized Keys:"
6
-
7
- KEYS.each do |search_text, full_key|
8
- file = "~/.ssh/authorized_keys"
9
- provision_server.run! <<~SH, home: true
10
- if ! grep -F -q "#{search_text}" #{file}; then
11
- echo "#{full_key}" >> #{file}
12
- fi
13
- SH
14
- end
15
-
16
- puts " ✓"
17
- end
18
-
19
- KEYS = {
20
- "micah@haku" => "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDAH235mtpxPQucd0bIgdufo1bR3By2+a+NPHiZS1P7SpI73evN9+hY7ri+gLscPLRWeoy1ig/TbyfN1AqJmfqIaskZdYOdcEQdOum4AwDMY5L6OAq2o5NER047RqDxE6Pjm2nfRVVw2Dz38eeco+ouchCI+sY5pJL/wEZItrCpPjKvwo56uln1rL6Smd4Kh98ZBKTGL8xKs95rNmFdBCCq4eUE28JDgkJAiLDZ/4u2LNrgEr7/brkUieZjaZ4BacBi8EQvyvMWmZ0g2MoG+Ptxn/3K2nd1QqdhfINqHBVCi8UbkP08B0Msif/7Dycuxd7DU9cVZ3RgnhLtbIsQ8HaYVj5yCKB6CuX3lv3H4YKBghBC/TnJD5Nq5xcSYTW0BKKrusCb/OoOk5AUV+BGM1+R70fno8reVEBUlZDkWapHxmqgNnf1byL7Aol/L5SWgyfSLT6b5FjI6g/U+dhaecYY9T9g/GWo+JiwZktc094O0ujlQHoibMY2M0csVfvO9Oc= micah@haku",
21
- "gubs@Theia.local" => "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEApJh0E8ZlaLbMUWGvryAhEBRnnI519ZKz586vdQTuIPlDb9xhe5m3Ys8Fk9LKqJUQNxBV6qCGOXNgNdWySkk2ChmmgDnPfr7/31ZuOAASFbUY0PtaDXUsMVvs1Uu2VhtRU9gSduGonEHG7iBpAuBI23CxU4yPS6o3pv7L9xwnmULes5F9S4/nDvPig15h9byInyHOLDV0XjHFS+2OlSWO/xC8uqH5CdlxXFAmPQ0R69qmILl0rcTPyNMLJGcJGUzb/LMRJX/RDyTpZeJPjH4V+zksQ/4YQ3LWvLrlZL6QLuM285ve4mQa3vBY4WMqNlp4Ig3ZCFOpMKmpvTn7pFUmKw== gubs@Theia.local",
22
- }
23
- end
24
-
25
-
@@ -1,27 +0,0 @@
1
- # copy data from production
2
-
3
- class Bard::Provision::Data < Bard::Provision
4
- def call
5
- print "Data:"
6
-
7
- print " Dumping #{server.key} database to file"
8
- server.run! "bin/rake db:dump"
9
-
10
- print " Transfering file from #{server.key},"
11
- server.copy_file "db/data.sql.gz", to: provision_server, verbose: false
12
-
13
- print " Loading file into database,"
14
- provision_server.run! "bin/rake db:load"
15
-
16
- config.data.each do |path|
17
- print " Synchronizing files in #{path},"
18
- server.copy_dir path, to: provision_server, verbose: false
19
- end
20
-
21
- puts " ✓"
22
- end
23
- end
24
-
25
-
26
-
27
-