bard-new
A plugin for the bard CLI that scaffolds new Rails projects and provisions Ubuntu servers into Bot & Rose production targets.
Adds two subcommands:
bard new <project-name>— scaffold a new Rails app, push it to GitHub, and stage a deploy.bard provision [ssh_url]— idempotently provision a fresh Ubuntu 24.04 host into a production target.
Installation
gem install bard-new
The parent bard gem auto-requires installed plugins by convention, so the new commands appear under bard --help once the gem is installed.
bard new
bard new my_project
Steps:
- Validates the project name (lowercase letters and digits only, must start with a letter).
- Creates an RVM gemset (
ruby-4.0.2@<project-name>) and installs Rails (~> 8.1.0). - Runs
rails newagainstlib/bard/new/rails_template.rb, which:- writes a Gemfile with
bard-rails,solid_*, sprockets + dartsass, importmap/turbo/stimulus,exception_notification, andpuma - writes a
Procfile - adds a
bootstraprake task (runsdb:prepare, and in production runsassets:precompile, exports systemd-user units viaforeman, and restarts the service) - runs
bard install && bin/setup && bard setup
- writes a Gemfile with
- Creates a private GitHub repo, pushes the initial commit, uploads
config/master.keyas an Actions secret, and enables branch protection onmaster. - Stages the new project (
bard deploy --clone).
Options:
--skip-github— skip GitHub repo creation and push.--skip-stage— skip the staging deploy.
bard provision
bard provision deploy@new-server.example.com:22
If ssh_url is omitted, the :production target's SSH URL from bard.rb is used.
The command iterates through the provisioning steps in order and dispatches each to a class under Bard::Provision. Every step is idempotent — it inspects current state and skips work that's already done — so re-running against a partially or fully provisioned host is safe.
| Step | What it does |
|---|---|
SSH |
Hardens sshd, switches to the port configured on the production target. |
User |
Creates the deploy user. |
AuthorizedKeys |
Installs SSH keys. |
Swapfile |
Allocates a swapfile. |
Apt |
Installs base system packages. |
MySQL |
Installs and configures MySQL, creates the app database and user. |
Repo |
Clones the application repo into the deploy path. |
MasterKey |
Installs config/master.key. |
RVM |
Installs RVM and the project's Ruby version. |
App |
Runs bin/setup / app bootstrap. |
Nginx |
Installs and configures nginx + TLS. |
Deploy |
Performs the initial deploy. |
HTTP |
Verifies the site responds. |
LogRotation |
Configures logrotate. |
Data |
Syncs initial data. |
Options:
--steps step1 step2 …— run only a subset of steps (names match the table above).
Development
The test suite uses real Podman containers to exercise both commands end-to-end. You need:
- Podman with the user socket enabled:
systemctl --user start podman.socket
bundle install
# Full suite (rspec + cucumber)
bundle exec rake
# Unit specs
bundle exec rspec
bundle exec rspec spec/bard/new/provision/nginx_spec.rb
# Cucumber — tags select which container image gets built
bundle exec cucumber features/new.feature # @new
bundle exec cucumber features/provision.feature # @provision
Cucumber runs are slow because they build and boot containers; run individual features rather than the full suite.
Adding a provision step
- Add the class name to
PROVISION_STEPSinlib/bard/new/cli/provision.rbat the correct position — ordering matters (e.g.SSHmust run beforeUser, which must run beforeAuthorizedKeys). - Create
lib/bard/new/provision/<name>.rbdefiningBard::Provision::<Name>as a subclass ofBard::Provision(aStruct.new(:config, :ssh_url)) with a#callmethod. - Make
#callidempotent — check current state before making changes. - Follow the output convention:
print "Name:", then oneprint " action,"per side effect, thenputs " ✓". - Use
provision_serverto SSH to the host being provisioned (rawssh_url) andtargetfor the final production target frombard.rb. TheSSHstep rewritesssh_urlto the configured port mid-flight, so later steps connect to the reconfigured host. - Add
spec/bard/new/provision/<name>_spec.rb.
License
MIT. Copyright (c) Micah Geisel.