bard 1.2.0 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 30b53e09f78ef39dcc713fd006c886d507a4d935178cb7de92c478cb4aaee7cc
4
- data.tar.gz: 057d81fda808b9a8d31f08bbffb898f208dda6013fb625bc7a2fc39aacf5a26d
3
+ metadata.gz: 50507cf111440a4f0d9f6cd1ee580f6749f81534c1c2f507fb32adcf7d49cbe7
4
+ data.tar.gz: e0386582b40d92ca6d5d003f1b83f03c34ad19968338b23e468f08778bdec968
5
5
  SHA512:
6
- metadata.gz: 3f8cc746753d1c33ca28917892635c0379890314ba6e1e3f65a620b9e8688774f3c82c4b0b1c9aa44e527daddb2b9ea1e2fcda4bf5707a5082c2141cdd6323f1
7
- data.tar.gz: 82764e32ae8357c3f020549993d1f6ccff9652fc0aafbee1b1d168c9068d10aaafd62a3ee7e71406428e5ce0bbb515065181ea56295d8aa24bf3713b8ececce7
6
+ metadata.gz: e3790197e55287ec52f6f4ee62b4e7df4cb02d148182520a913ac2ca235344cd7bb62f3b3a4ed53bb50e549cb08594d39de72c8a52de00fa441d65c52ecd696c
7
+ data.tar.gz: 8a6525ca5efc614ed59f51c811d39733bec7d5c5e9c1966510006d221d0d5654402098cb9f492e7ce3289cda3d43748b9af1b726a25a22e9b98718f461ec5c90
@@ -0,0 +1,19 @@
1
+ require "delegate"
2
+
3
+ class Bard::CLI::Command < SimpleDelegator
4
+ def self.desc command, description
5
+ @command = command
6
+ @method = command.split(" ").first.to_sym
7
+ @description = description
8
+ end
9
+
10
+ def self.setup cli
11
+ cli.desc @command, @description
12
+
13
+ method = @method # put in local variable so next block can capture it
14
+ cli.define_method method do |*args|
15
+ command = Bard::CLI::New.new(self)
16
+ command.send method, *args
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,6 @@
1
1
  require "bard/git"
2
2
  require "bard/command"
3
+ require "bard/github_pages"
3
4
 
4
5
  module Bard::CLI::Deploy
5
6
  def self.included mod
@@ -7,6 +8,7 @@ module Bard::CLI::Deploy
7
8
 
8
9
  option :"skip-ci", type: :boolean
9
10
  option :"local-ci", type: :boolean
11
+ option :clone, type: :boolean
10
12
  desc "deploy [TO=production]", "checks that current branch is a ff with master, checks with ci, merges into master, deploys to target, and then deletes branch."
11
13
  def deploy to=:production
12
14
  branch = Bard::Git.current_branch
@@ -37,7 +39,17 @@ module Bard::CLI::Deploy
37
39
  run! "git push github"
38
40
  end
39
41
 
40
- config[to].run! "git pull origin master && bin/setup"
42
+ if options[:clone]
43
+ config[to].run! "git clone git@github.com:botandrosedesign/#{project_name}", home: true
44
+ invoke :master_key, nil, from: "local", to: to
45
+ config[to].run! "bin/setup && bard setup"
46
+ else
47
+ if config[to].github_pages
48
+ Bard::GithubPages.new(self).deploy(config[to])
49
+ else
50
+ config[to].run! "git pull origin master && bin/setup"
51
+ end
52
+ end
41
53
 
42
54
  puts green("Deploy Succeeded")
43
55
 
@@ -0,0 +1,68 @@
1
+ require "bard/cli/command"
2
+ require "bard/github"
3
+
4
+ class Bard::CLI::New < Bard::CLI::Command
5
+ desc "new <project-name>", "creates new bard app named <project-name>"
6
+ def new project_name
7
+ @project_name = project_name
8
+ validate
9
+ create_project
10
+ push_to_github
11
+ stage
12
+ puts green("Project #{project_name} created!")
13
+ puts "Please cd ../#{project_name}"
14
+ end
15
+
16
+ attr_accessor :project_name
17
+
18
+ private
19
+
20
+ def validate
21
+ if project_name !~ /^[a-z][a-z0-9]*\Z/
22
+ puts red("!!! ") + "Invalid project name: #{yellow(project_name)}."
23
+ puts "The first character must be a lowercase letter, and all following characters must be a lowercase letter or number."
24
+ exit 1
25
+ end
26
+ end
27
+
28
+ def create_project
29
+ run! <<~BASH
30
+ env -i bash -lc '
31
+ export HOME=~
32
+ cd ..
33
+ source ~/.rvm/scripts/rvm
34
+ rvm use --create #{ruby_version}@#{project_name}
35
+
36
+ gem list rails -i && gem install rails --no-document
37
+ rails new #{project_name} --skip-kamal -m #{template_path}
38
+ '
39
+ BASH
40
+ end
41
+
42
+ def push_to_github
43
+ Bard::Github.new(project_name).create_repo
44
+ run! <<~BASH
45
+ cd ../#{project_name}
46
+ git add -A
47
+ git commit -m"initial commit."
48
+ git remote add origin git@github.com:botandrosedesign/#{project_name}
49
+ git push -u origin master
50
+ BASH
51
+ end
52
+
53
+ def stage
54
+ run! <<~BASH
55
+ cd ../#{project_name}
56
+ bard deploy --provision
57
+ BASH
58
+ end
59
+
60
+ def ruby_version
61
+ File.read(".ruby-version").chomp
62
+ end
63
+
64
+ def template_path
65
+ File.expand_path("new_rails_template.rb", __dir__)
66
+ end
67
+ end
68
+
@@ -0,0 +1,88 @@
1
+ ruby_version, project_name = (`rvm current name`.chomp).split("@")
2
+
3
+ file ".ruby-version", ruby_version
4
+ file ".ruby-gemset", project_name
5
+
6
+ file "Gemfile", <<~RUBY
7
+ source "https://rubygems.org"
8
+
9
+ gem "bootsnap", require: false
10
+ gem "rails", "~>8.0.0"
11
+ gem "bard-rails"
12
+ gem "sqlite3"
13
+
14
+ gem "sprockets-rails"
15
+ gem "dartsass-sprockets"
16
+ gem "bard-sass"
17
+
18
+ gem "importmap-rails"
19
+ gem "turbo-rails"
20
+ gem "stimulus-rails"
21
+
22
+ gem "solid_cache"
23
+ gem "solid_queue"
24
+ gem "solid_cable"
25
+
26
+ gem "image_processing"
27
+
28
+ group :development do
29
+ gem "web-console"
30
+ end
31
+
32
+ group :development, :test do
33
+ gem "debug", require: "debug/prelude"
34
+ gem "brakeman", require: false
35
+ gem "rubocop-rails-omakase", require: false
36
+ end
37
+
38
+ group :test do
39
+ gem "cucumber-rails", require: false
40
+ gem "cuprite-downloads"
41
+ gem "capybara-screenshot"
42
+ gem "database_cleaner"
43
+ gem "puma"
44
+ gem "chop"
45
+ gem "email_spec"
46
+ gem "timecop"
47
+ gem "rspec-rails"
48
+ end
49
+
50
+ group :production do
51
+ gem "foreman-export-systemd_user"
52
+ gem "puma"
53
+ end
54
+ RUBY
55
+
56
+ file "app/assets/config/manifest.js", <<~RUBY
57
+ //= link_tree ../images
58
+ //= link_directory ../stylesheets .css
59
+ //= link_tree ../../javascript .js
60
+ RUBY
61
+
62
+ run "rm -f app/assets/stylesheets/application.css"
63
+
64
+ file "app/assets/stylesheets/application.sass", <<~SASS
65
+ body
66
+ border: 10px solid red
67
+ SASS
68
+
69
+ gsub_file "app/views/layouts/application.html.erb", " <%# Includes all stylesheet files in app/assets/stylesheets %>\n", ''
70
+ gsub_file "app/views/layouts/application.html.erb", 'stylesheet_link_tag :app,', 'stylesheet_link_tag :application,'
71
+
72
+ file "app/views/static/index.html.slim", <<~SLIM
73
+ h1 #{project_name}
74
+ SLIM
75
+
76
+ insert_into_file "config/database.yml", <<~YAML, after: "database: storage/test.sqlite3"
77
+
78
+ staging:
79
+ <<: *default
80
+ database: storage/staging.sqlite3
81
+ YAML
82
+
83
+ after_bundle do
84
+ run "bard install"
85
+ run "bin/setup"
86
+ run "bard setup"
87
+ end
88
+
data/lib/bard/cli.rb CHANGED
@@ -31,8 +31,24 @@ module Bard
31
31
  include const_get(klass)
32
32
  end
33
33
 
34
+ {
35
+ new: "New",
36
+ }.each do |command, klass|
37
+ require "bard/cli/#{command}"
38
+ const_get(klass).setup(self)
39
+ end
40
+
34
41
  def self.exit_on_failure? = true
35
42
 
43
+ no_commands do
44
+ def run!(...)
45
+ Bard::Command.run!(...)
46
+ rescue Bard::Command::Error => e
47
+ puts red("!!! ") + "Running command failed: #{yellow(e.message)}"
48
+ exit 1
49
+ end
50
+ end
51
+
36
52
  private
37
53
 
38
54
  def config
@@ -42,13 +58,6 @@ module Bard
42
58
  def project_name
43
59
  @project_name ||= File.expand_path(".").split("/").last
44
60
  end
45
-
46
- def run!(...)
47
- Bard::Command.run!(...)
48
- rescue Bard::Command::Error => e
49
- puts red("!!! ") + "Running command failed: #{yellow(e.message)}"
50
- exit 1
51
- end
52
61
  end
53
62
  end
54
63
 
data/lib/bard/config.rb CHANGED
@@ -75,5 +75,17 @@ module Bard
75
75
  raise ArgumentError
76
76
  end
77
77
  end
78
+
79
+ # short-hand for michael
80
+
81
+ def github_pages url=nil
82
+ server :production do
83
+ github_pages true
84
+ ssh false
85
+ ping url
86
+ end
87
+
88
+ backup false
89
+ end
78
90
  end
79
91
  end
data/lib/bard/github.rb CHANGED
@@ -19,6 +19,14 @@ module Bard
19
19
  end
20
20
  end
21
21
 
22
+ def delete path, params={}
23
+ request(path) do |uri|
24
+ Net::HTTP::Delete.new(uri).tap do |r|
25
+ r.body = JSON.dump(params)
26
+ end
27
+ end
28
+ end
29
+
22
30
  def read_file path, branch: "master"
23
31
  metadata = get("contents/#{path}", ref: branch)
24
32
  Base64.decode64(metadata["content"])
@@ -28,6 +36,17 @@ module Bard
28
36
  post("keys", title:, key:)
29
37
  end
30
38
 
39
+ def create_repo
40
+ post("https://api.github.com/orgs/botandrosedesign/repos", {
41
+ name: project_name,
42
+ private: true,
43
+ })
44
+ end
45
+
46
+ def delete_repo
47
+ delete("https://api.github.com/repos/botandrosedesign/#{project_name}")
48
+ end
49
+
31
50
  private
32
51
 
33
52
  def github_apikey
@@ -63,7 +82,7 @@ module Bard
63
82
  response.body
64
83
  end
65
84
  else
66
- raise [req.method, req.uri, req.to_hash, response].inspect
85
+ raise [req.method, req.uri, req.to_hash, response, response.body].inspect
67
86
  end
68
87
  end
69
88
  end
@@ -0,0 +1,112 @@
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
+
13
+ puts "Starting deployment to GitHub Pages..."
14
+
15
+ build_site
16
+ tree_sha = create_tree_from_build
17
+ new_commit = create_commit(tree_sha)
18
+ commit_and_push new_commit
19
+ end
20
+
21
+ private
22
+
23
+ def build_site
24
+ FileUtils.rm_rf "tmp/github-build-".sub(@sha, "*")
25
+ run! <<~BASH
26
+ bundle exec rake assets:clean assets:precompile
27
+ RAILS_ENV=production bundle exec rails s -p 3000 -d --pid tmp/pids/server.pid
28
+
29
+ # Create the output directory and enter it
30
+ BUILD=#{@build_dir}
31
+ rm -rf $BUILD
32
+ mkdir -p $BUILD
33
+ cp -R public/assets $BUILD/
34
+ cd $BUILD
35
+
36
+ # wait until server responds
37
+ curl --retry 5 --retry-delay 2 -s -o /dev/null "http://0.0.0.0:3000"
38
+
39
+ # Mirror the site to the build folder, ignoring links with query params
40
+ wget --reject-regex "(.*)\\?(.*)" -FEmnH http://0.0.0.0:3000/
41
+ echo #{@domain} > CNAME
42
+
43
+ # Kill the server
44
+ cd -
45
+ cat tmp/pids/server.pid | xargs -I {} kill {}
46
+
47
+ # Clean up the assets
48
+ rm -rf public/assets
49
+ BASH
50
+ end
51
+
52
+ def create_tree_from_build
53
+ # Create temporary index
54
+ git_index_file = ".git/tmp-index"
55
+ git = "GIT_INDEX_FILE=#{git_index_file} git"
56
+ run! "#{git} read-tree --empty"
57
+
58
+ # Add build files to temporary index
59
+ Dir.chdir(@build_dir) do
60
+ Dir.glob('**/*', File::FNM_DOTMATCH).each do |file|
61
+ next if file == '.' || file == '..'
62
+ if File.file?(file)
63
+ run! "#{git} update-index --add --cacheinfo 100644 $(#{git} hash-object -w #{file}) #{file}"
64
+ end
65
+ end
66
+ end
67
+
68
+ # Create tree object from index
69
+ tree_sha = `#{git} write-tree`.chomp
70
+
71
+ # Clean up temporary index
72
+ FileUtils.rm_f(git_index_file)
73
+
74
+ tree_sha
75
+ end
76
+
77
+ def create_commit tree_sha
78
+ # Get parent commit if branch exists
79
+ parent = get_parent_commit
80
+
81
+ # Create commit object
82
+ message = "'Deploying to #{@branch} from @ #{@sha} 🚀'"
83
+ args = ['commit-tree', tree_sha]
84
+ args += ['-p', parent] if parent
85
+ args += ['-m', message]
86
+
87
+ commit_sha = `git #{args.join(' ')}`.chomp
88
+
89
+ commit_sha
90
+ end
91
+
92
+ def get_parent_commit
93
+ sha = Git.sha_of("#{@branch}^{commit}")
94
+ return sha if $?.success?
95
+ nil # Branch doesn't exist yet
96
+ end
97
+
98
+ def commit_and_push commit_sha
99
+ if branch_exists?
100
+ run! "git update-ref refs/heads/#{@branch} #{commit_sha}"
101
+ else
102
+ run! "git branch #{@branch} #{commit_sha}"
103
+ end
104
+ run! "git push -f origin #{@branch}:refs/heads/#{@branch}"
105
+ end
106
+
107
+ def branch_exists?
108
+ system("git show-ref --verify --quiet refs/heads/#{@branch}")
109
+ end
110
+ end
111
+ end
112
+
data/lib/bard/server.rb CHANGED
@@ -3,7 +3,7 @@ require "bard/command"
3
3
  require "bard/copy"
4
4
 
5
5
  module Bard
6
- class Server < Struct.new(:project_name, :key, :ssh, :path, :ping, :gateway, :ssh_key, :env)
6
+ class Server < Struct.new(:project_name, :key, :ssh, :path, :ping, :gateway, :ssh_key, :env, :github_pages)
7
7
  def self.define project_name, key, &block
8
8
  new(project_name, key).tap do |server|
9
9
  server.instance_eval &block
@@ -24,7 +24,7 @@ module Bard
24
24
  end
25
25
  end
26
26
 
27
- setting :ssh, :path, :ping, :gateway, :ssh_key, :env
27
+ setting :ssh, :path, :ping, :gateway, :ssh_key, :env, :github_pages
28
28
 
29
29
  def ping(*args)
30
30
  if args.length == 0
data/lib/bard/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Bard
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bard
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micah Geisel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-26 00:00:00.000000000 Z
11
+ date: 2024-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -139,11 +139,14 @@ files:
139
139
  - lib/bard/ci/local.rb
140
140
  - lib/bard/cli.rb
141
141
  - lib/bard/cli/ci.rb
142
+ - lib/bard/cli/command.rb
142
143
  - lib/bard/cli/data.rb
143
144
  - lib/bard/cli/deploy.rb
144
145
  - lib/bard/cli/hurt.rb
145
146
  - lib/bard/cli/install.rb
146
147
  - lib/bard/cli/master_key.rb
148
+ - lib/bard/cli/new.rb
149
+ - lib/bard/cli/new_rails_template.rb
147
150
  - lib/bard/cli/open.rb
148
151
  - lib/bard/cli/ping.rb
149
152
  - lib/bard/cli/provision.rb
@@ -157,6 +160,7 @@ files:
157
160
  - lib/bard/copy.rb
158
161
  - lib/bard/git.rb
159
162
  - lib/bard/github.rb
163
+ - lib/bard/github_pages.rb
160
164
  - lib/bard/ping.rb
161
165
  - lib/bard/provision.rb
162
166
  - lib/bard/provision/app.rb