A modular deployment tool for Ruby applications that makes deployment simple and extensible.
# bard.rb
target :production do
ssh "[email protected]:22"
endbard deploy production- Modular Capabilities: Enable only the features you need
- Pluggable Strategies: SSH, GitHub Pages, or create your own
- Default Targets: Pre-configured for common Bot and Rose workflows
- Git Integration: Built-in branch management and safety checks
- CI Integration: Auto-detects GitHub Actions or Jenkins
- Data Syncing: Copy databases and assets between targets
Add to your Gemfile:
gem 'bard'Or install globally:
gem install bardA target is a deployment destination. Targets can be servers, serverless environments, static hosting, or anything else you can deploy to.
target :production do
ssh "[email protected]:22", path: "app"
endCapabilities are features enabled on targets. Common capabilities include:
- SSH: Remote command execution and file transfer
- Ping: Health check URLs
- Data: Database and file syncing
- Backup: Automatic backups during deployment
Strategies determine how code gets deployed. Built-in strategies:
- SSH: Deploy via git pull on remote server
- GitHub Pages: Deploy static site to gh-pages branch
- Custom: Define your own (Jets, Docker, Kubernetes, etc.)
Create a bard.rb file in your project root:
# Simple SSH deployment
target :production do
ssh "[email protected]:22",
path: "app",
gateway: "[email protected]:22"
end
# GitHub Pages static site
target :production do
github_pages "https://example.com"
end
# Custom strategy (Jets serverless)
require_relative 'lib/jets_deploy_strategy'
target :production do
jets "https://api.example.com", run_tests: true
endBard ships with default targets for Bot and Rose workflows. Override any in your bard.rb:
- :local - Local development (no SSH)
- :ci - Jenkins CI at staging.botandrose.com
- :staging - Staging server at staging.botandrose.com
- :gubs - Bot and Rose cloud server
# Override default staging to use Jets
target :staging do
jets "https://staging-api.example.com"
end
# Keep :ci, :gubs, :local as defaults# Deploy to production
bard deploy production
# Deploy to staging
bard deploy staging
# Deploy feature branch to staging (no merge)
bard stage feature-branch
# Skip CI checks
bard deploy production --skip-ci# Copy database and assets from production to local
bard data --from=production --to=local
# Copy staging data to local
bard data --from=staging --to=local
# Configure additional paths to sync
# bard.rb:
data "public/uploads", "public/system"# SSH into a target
bard ssh production
# Run a command on a target
bard run production "bundle exec rails console"# Run CI for current branch
bard ci
# Run tests locally
bard ci --local-ci
# Check CI status
bard ci --status# Open target URL in browser
bard open production
# Ping target to check health
bard ping production
# Show uncommitted changes
bard hurt
# Open changed files in vim
bard vim# Full server provisioning
bard provision [email protected]:22
# Configure nginx for current app
bard setupEnable SSH to run commands and transfer files:
target :production do
ssh "user@host:port",
path: "deploy/path",
gateway: "bastion@host:port",
ssh_key: "/path/to/key",
env: "RAILS_ENV=production"
endThis provides:
target.run!(command)- Execute remote command (raises on error)target.run(command)- Execute remote command (silent on error)target.exec!(command)- Replace process with remote commandtarget.copy_file(path, to: target)- Copy file to another targettarget.copy_dir(path, to: target)- Rsync directory to another target
Deploy by running git pull on remote server:
target :production do
ssh "[email protected]:22"
endDeployment runs: git pull origin master && bin/setup
Deploy static site to GitHub Pages:
target :production do
github_pages "https://example.com"
endDeployment:
- Starts Rails server locally
- Mirrors site with wget
- Creates orphan commit with static assets
- Force-pushes to
gh-pagesbranch
Create your own deployment strategy:
# lib/jets_deploy_strategy.rb
module Bard
class DeployStrategy
class Jets < DeployStrategy
def deploy
target_name = target.key.to_s
options = target.strategy_options(:jets)
run! "rake vips:build:#{target_name}" unless options[:skip_build]
run! "bundle exec rspec" if should_run_tests?(target_name, options)
run! "jets deploy #{options[:env] || target_name}"
end
private
def should_run_tests?(target_name, options)
return options[:run_tests] if options.key?(:run_tests)
target_name == "production"
end
end
end
endUse it in your bard.rb:
require_relative 'lib/jets_deploy_strategy'
target :production do
jets "https://api.example.com", run_tests: true
end
target :staging do
jets "https://staging-api.example.com", skip_build: true
endStrategies auto-register via Ruby's inherited hook - no manual registration needed!
Bard auto-detects your CI system:
- Finds
.github/workflows/ci.yml→ GitHub Actions - Otherwise → Jenkins (legacy)
Override via DSL:
# Force specific CI system
ci :github_actions
ci :jenkins
ci :local
# Disable CI
ci falseConfigure health check URLs:
target :production do
ssh "[email protected]:22"
ping "https://example.com", "/health", "/status"
endAuto-configured by deployment strategies:
# Ping URL automatically set from Jets URL
target :production do
jets "https://api.example.com"
endDatabase syncing is enabled by default when SSH is configured. Add file paths to sync:
# Global configuration
data "public/uploads", "public/system"
target :production do
ssh "[email protected]:22"
endThen sync:
bard data --from=production --to=localThis:
- Runs
bin/rake db:dumpon source - Copies
db/data.sql.gzvia SCP - Runs
bin/rake db:loadon destination - Rsyncs configured data paths
Control whether backups are created during deployment:
# Enable backups (default for SSH deployments)
backup true
# Disable backups (typical for serverless/static)
backup falsetarget :staging do
ssh "[email protected]:22"
end
target :production do
ssh "[email protected]:22"
end
data "public/uploads"
backup truerequire_relative 'lib/jets_deploy_strategy'
target :staging do
jets "https://staging-api.example.com"
end
target :production do
jets "https://api.example.com", run_tests: true
end
backup falserequire_relative 'lib/jets_deploy_strategy'
target :staging do
jets "https://staging-api.example.com"
ssh "[email protected]:22" # Enables SSH commands
end
target :production do
jets "https://api.example.com"
# No SSH in production
end
backup falsetarget :production do
github_pages "https://example.com"
end
backup false# Override default staging to use Jets
target :staging do
jets "https://staging-api.example.com"
end
# Keep :ci, :gubs, :local targets as defaultsSee MIGRATION_GUIDE.md for detailed migration instructions.
Key changes in v2.0:
serverrenamed totarget- SSH configuration uses hash options
- Strategy-first configuration
- Capability-based commands
Bard follows a modular, capability-based architecture:
- Core: Minimal git workflow and configuration
- Capabilities: Features enabled via DSL methods
- Strategies: Pluggable deployment strategies with auto-registration
- Subsystems: Independent and composable
See ARCHITECTURE.md for detailed architecture documentation.
See CUSTOM_STRATEGIES.md for a step-by-step guide to creating custom deployment strategies.
# Clone repository
git clone https://github.com/botandrose/bard.git
cd bard
# Install dependencies
bundle install
# Run tests
bundle exec rspec
# Run bard from source
bundle exec bin/bardMIT License. Copyright (c) 2018 Micah Geisel. See LICENSE for details.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request