bard 1.8.0 → 1.9.1
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/stage.rb +10 -1
- data/lib/bard/cli/vim.rb +5 -10
- data/lib/bard/cli.rb +13 -11
- data/lib/bard/command.rb +3 -3
- data/lib/bard/config.rb +4 -14
- 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/provision/ssh.rb +9 -2
- data/lib/bard/secrets.rb +10 -0
- data/lib/bard/server.rb +3 -2
- data/lib/bard/target.rb +3 -2
- 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/stage_spec.rb +20 -0
- data/spec/bard/cli/vim_spec.rb +5 -5
- data/spec/bard/config_spec.rb +12 -0
- data/spec/bard/github_spec.rb +1 -1
- data/spec/bard/plugin_spec.rb +79 -0
- data/spec/bard/provision/ssh_spec.rb +17 -4
- data/spec/spec_helper.rb +6 -1
- metadata +27 -3
- data/README.rdoc +0 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9d66092e3bc2b19b6010e668ead98981db7d41ce14434be33b02caa7c7c23e97
|
|
4
|
+
data.tar.gz: bbe41031b2b9c5974069bae36a5606063d3d4a75f43bf86ac61787b60e12eb9b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d13c12fc322c9cdcfa2ae0c8a6a5fd9c4e033e026ef423823494d02f63eec55a5bd1a7268689017b56bf7e4243ece08f2b041d41958b751f2808d5403529d745
|
|
7
|
+
data.tar.gz: 26a9703810bc8c2063803a8efc8720ca2bb9e9f6cb82667e18b00297b76256a745434a453cabd1bb6f1966337a6b1b27e6bcd62674671922d300ccdad53e25e3
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What is Bard?
|
|
6
|
+
|
|
7
|
+
Bard is a modular deployment CLI tool for Ruby applications. It provides:
|
|
8
|
+
- SSH-based deployment via git pull
|
|
9
|
+
- GitHub Pages static site deployment
|
|
10
|
+
- Custom pluggable deployment strategies
|
|
11
|
+
- Data syncing (database dumps and file rsync)
|
|
12
|
+
- CI integration (GitHub Actions/Jenkins)
|
|
13
|
+
- Server provisioning
|
|
14
|
+
|
|
15
|
+
## Development Commands
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Install dependencies
|
|
19
|
+
bundle install
|
|
20
|
+
|
|
21
|
+
# Run all tests (RSpec + Cucumber)
|
|
22
|
+
bundle exec rake
|
|
23
|
+
|
|
24
|
+
# Run only RSpec tests
|
|
25
|
+
bundle exec rspec
|
|
26
|
+
|
|
27
|
+
# Run a single spec file
|
|
28
|
+
bundle exec rspec spec/bard/target_spec.rb
|
|
29
|
+
|
|
30
|
+
# Run a specific test by line number
|
|
31
|
+
bundle exec rspec spec/bard/target_spec.rb:42
|
|
32
|
+
|
|
33
|
+
# Run Cucumber features (slow - avoid full suite)
|
|
34
|
+
bundle exec cucumber features/deploy.feature
|
|
35
|
+
|
|
36
|
+
# Run bard from source
|
|
37
|
+
bundle exec bin/bard
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
|
|
42
|
+
### Core Classes
|
|
43
|
+
|
|
44
|
+
- **`Bard::CLI`** (`lib/bard/cli.rb`) - Thor-based command dispatcher. Commands are modules in `lib/bard/cli/` included into CLI.
|
|
45
|
+
- **`Bard::Config`** (`lib/bard/config.rb`) - DSL parser for `bard.rb` files. Manages targets and settings.
|
|
46
|
+
- **`Bard::Target`** (`lib/bard/target.rb`) - Deployment destination with capabilities (ssh, ping, data). Supports dynamic strategy DSL via `method_missing`.
|
|
47
|
+
- **`Bard::Server`** (`lib/bard/server.rb`) - Legacy v1.x server representation (deprecated, use Target).
|
|
48
|
+
- **`Bard::DeployStrategy`** (`lib/bard/deploy_strategy.rb`) - Base class for deployment strategies. Subclasses auto-register via Ruby's `inherited` hook.
|
|
49
|
+
|
|
50
|
+
### Capability System
|
|
51
|
+
|
|
52
|
+
Targets track enabled capabilities (`:ssh`, `:ping`, `:github_pages`, etc.). Commands call `require_capability!` to ensure the target supports the operation.
|
|
53
|
+
|
|
54
|
+
### Strategy Auto-Registration
|
|
55
|
+
|
|
56
|
+
Custom strategies subclass `DeployStrategy` and are automatically registered by class name:
|
|
57
|
+
```ruby
|
|
58
|
+
class Bard::DeployStrategy::Jets < DeployStrategy # registers as :jets
|
|
59
|
+
def deploy; ...; end
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### File Organization
|
|
64
|
+
|
|
65
|
+
- `lib/bard/cli/*.rb` - CLI command modules (deploy, data, ssh, etc.)
|
|
66
|
+
- `lib/bard/ci/*.rb` - CI system integrations (github_actions, jenkins, local)
|
|
67
|
+
- `lib/bard/deploy_strategy/*.rb` - Built-in strategies (ssh, github_pages)
|
|
68
|
+
- `lib/bard/provision/*.rb` - Server provisioning modules
|
|
69
|
+
- `spec/` - RSpec unit tests
|
|
70
|
+
- `features/` - Cucumber integration tests
|
|
71
|
+
|
|
72
|
+
## Testing Notes
|
|
73
|
+
|
|
74
|
+
- Use `focus: true` in RSpec to run specific tests
|
|
75
|
+
- Cucumber tests use testcontainers and are slow - run specific feature files only
|
|
76
|
+
- SimpleCov tracks coverage across both RSpec and Cucumber runs
|
data/PLUGINS.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Plugin Development
|
|
2
|
+
|
|
3
|
+
Bard uses a plugin system to extend functionality. Plugins can add CLI commands, target methods, and config DSL methods.
|
|
4
|
+
|
|
5
|
+
## Plugin Structure
|
|
6
|
+
|
|
7
|
+
Plugins live in `lib/bard/plugins/` and register themselves:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# lib/bard/plugins/my_plugin.rb
|
|
11
|
+
require "bard/plugin"
|
|
12
|
+
|
|
13
|
+
Bard::Plugin.register :my_plugin do
|
|
14
|
+
# Add CLI commands (class must implement .setup)
|
|
15
|
+
cli "Bard::CLI::MyPlugin", require: "bard/cli/my_plugin"
|
|
16
|
+
|
|
17
|
+
# Add methods to Target
|
|
18
|
+
target_method :my_feature do |url = nil|
|
|
19
|
+
if url.nil?
|
|
20
|
+
@my_feature_url
|
|
21
|
+
else
|
|
22
|
+
@my_feature_url = url
|
|
23
|
+
enable_capability(:my_feature)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Add methods to Config
|
|
28
|
+
config_method :my_global_setting do |value = nil|
|
|
29
|
+
if value.nil?
|
|
30
|
+
@my_global_setting
|
|
31
|
+
else
|
|
32
|
+
@my_global_setting = value
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## CLI Commands
|
|
39
|
+
|
|
40
|
+
CLI commands inherit from `Bard::CLI::Command` and implement a `setup` class method:
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
# lib/bard/cli/my_plugin.rb
|
|
44
|
+
require "bard/cli/command"
|
|
45
|
+
|
|
46
|
+
class Bard::CLI::MyPlugin < Bard::CLI::Command
|
|
47
|
+
desc "mycommand", "Description of my command"
|
|
48
|
+
def mycommand
|
|
49
|
+
puts "Hello from my plugin!"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The `Command` base class provides:
|
|
55
|
+
- Automatic `setup` that registers the command with the CLI
|
|
56
|
+
- Delegation to the CLI instance (access to `config`, `project_name`, etc.)
|
|
57
|
+
- `desc` and `option` class methods for Thor integration
|
|
58
|
+
|
|
59
|
+
For Thor subcommand groups (nested under `bard mygroup`):
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
# lib/bard/cli/my_subcommand.rb
|
|
63
|
+
class Bard::CLI::MySubcommand < Thor
|
|
64
|
+
def self.setup(cli)
|
|
65
|
+
cli.register(self, "mygroup", "mygroup COMMAND", "My subcommand group")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
desc "action", "Do something"
|
|
69
|
+
def action
|
|
70
|
+
puts "Hello from subcommand!"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Adding Strategies
|
|
76
|
+
|
|
77
|
+
Plugins can add deployment strategies or CI runners:
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
# Custom deploy strategy
|
|
81
|
+
module Bard
|
|
82
|
+
class DeployStrategy
|
|
83
|
+
class MyCloud < DeployStrategy
|
|
84
|
+
def deploy
|
|
85
|
+
# Deployment logic here
|
|
86
|
+
run! "my-cloud deploy #{target.key}"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Custom CI runner
|
|
93
|
+
module Bard
|
|
94
|
+
class CI
|
|
95
|
+
class Runner
|
|
96
|
+
class MyCI < Runner
|
|
97
|
+
def run
|
|
98
|
+
# Start CI run
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def status
|
|
102
|
+
# Return current status
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Strategies auto-register via Ruby's `inherited` hook. The class name determines the strategy key (e.g., `MyCloud` → `:my_cloud`).
|
|
111
|
+
|
|
112
|
+
## Plugin Loading
|
|
113
|
+
|
|
114
|
+
Plugins are loaded automatically from `lib/bard/plugins/`. The load order is alphabetical by filename. For CI runners, the last registered runner becomes the default.
|
data/README.md
CHANGED
|
@@ -12,7 +12,7 @@ end
|
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
bard deploy
|
|
15
|
+
bard deploy
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## Features
|
|
@@ -115,17 +115,21 @@ end
|
|
|
115
115
|
### Deployment
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
# Deploy to production
|
|
119
|
-
bard deploy
|
|
118
|
+
# Deploy current branch to production (default)
|
|
119
|
+
bard deploy
|
|
120
120
|
|
|
121
|
-
# Deploy to
|
|
122
|
-
bard deploy
|
|
121
|
+
# Deploy a specific branch to production
|
|
122
|
+
bard deploy feature-branch
|
|
123
|
+
|
|
124
|
+
# Deploy to a different target
|
|
125
|
+
bard deploy --target=staging
|
|
126
|
+
bard deploy feature-branch --target=staging
|
|
123
127
|
|
|
124
128
|
# Deploy feature branch to staging (no merge)
|
|
125
129
|
bard stage feature-branch
|
|
126
130
|
|
|
127
131
|
# Skip CI checks
|
|
128
|
-
bard deploy
|
|
132
|
+
bard deploy --skip-ci
|
|
129
133
|
```
|
|
130
134
|
|
|
131
135
|
### Data Management
|
|
@@ -459,6 +463,10 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed architecture documentation.
|
|
|
459
463
|
|
|
460
464
|
See [CUSTOM_STRATEGIES.md](CUSTOM_STRATEGIES.md) for a step-by-step guide to creating custom deployment strategies.
|
|
461
465
|
|
|
466
|
+
## Plugin Development
|
|
467
|
+
|
|
468
|
+
See [PLUGINS.md](PLUGINS.md) for a guide to creating plugins.
|
|
469
|
+
|
|
462
470
|
## Development
|
|
463
471
|
|
|
464
472
|
```bash
|
data/features/ci.feature
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Feature: bard ci
|
|
2
|
+
Run continuous integration tests.
|
|
3
|
+
|
|
4
|
+
Background:
|
|
5
|
+
Given a test server is running
|
|
6
|
+
|
|
7
|
+
Scenario: no CI configured error
|
|
8
|
+
When I run expecting failure: bard ci
|
|
9
|
+
Then the output should contain "No CI found"
|
|
10
|
+
And the output should contain "Re-run with --skip-ci to bypass CI"
|
|
11
|
+
|
|
12
|
+
Scenario: local CI runs successfully
|
|
13
|
+
Given a local CI script that passes
|
|
14
|
+
When I run: bard ci --local-ci
|
|
15
|
+
Then the output should contain "Continuous integration: starting build"
|
|
16
|
+
And the output should contain "Continuous integration: success!"
|
|
17
|
+
|
|
18
|
+
Scenario: local CI reports failure
|
|
19
|
+
Given a local CI script that fails with "Test failed: expected 1 but got 2"
|
|
20
|
+
When I run expecting failure: bard ci --local-ci
|
|
21
|
+
Then the output should contain "Test failed: expected 1 but got 2"
|
|
22
|
+
And the output should contain "Automated tests failed!"
|
|
23
|
+
|
|
24
|
+
Scenario: --ci option runs specified CI runner
|
|
25
|
+
Given a local CI script that passes
|
|
26
|
+
When I run: bard ci --ci=local
|
|
27
|
+
Then the output should contain "Continuous integration: starting build"
|
|
28
|
+
And the output should contain "Continuous integration: success!"
|
|
29
|
+
|
|
30
|
+
Scenario: --ci option reports failure from specified runner
|
|
31
|
+
Given a local CI script that fails with "Custom runner failed"
|
|
32
|
+
When I run expecting failure: bard ci --ci=local
|
|
33
|
+
Then the output should contain "Custom runner failed"
|
|
34
|
+
And the output should contain "Automated tests failed!"
|
|
35
|
+
|
|
36
|
+
Scenario: deploy passes --ci option to CI
|
|
37
|
+
Given a local CI script that passes
|
|
38
|
+
And I create a file "ci-option-test.txt" with content "ci option test"
|
|
39
|
+
And I commit the changes with message "Add CI option test file"
|
|
40
|
+
When I run: bard deploy --ci=local
|
|
41
|
+
Then the output should contain "Continuous integration: starting build"
|
|
42
|
+
And the output should contain "Continuous integration: success!"
|
|
43
|
+
And the output should contain "Deploy Succeeded"
|
|
44
|
+
|
|
45
|
+
Scenario: deploy runs CI before deploying
|
|
46
|
+
Given a local CI script that passes
|
|
47
|
+
And I create a file "ci-test.txt" with content "ci test"
|
|
48
|
+
And I commit the changes with message "Add CI test file"
|
|
49
|
+
When I run: bard deploy --local-ci
|
|
50
|
+
Then the output should contain "Continuous integration: starting build"
|
|
51
|
+
And the output should contain "Continuous integration: success!"
|
|
52
|
+
And the output should contain "Deploy Succeeded"
|
|
53
|
+
|
|
54
|
+
Scenario: deploy aborts if CI fails
|
|
55
|
+
Given a local CI script that fails with "Build failed"
|
|
56
|
+
And I create a file "ci-fail.txt" with content "ci fail test"
|
|
57
|
+
And I commit the changes with message "Add CI fail test file"
|
|
58
|
+
When I run expecting failure: bard deploy --local-ci
|
|
59
|
+
Then the output should contain "Continuous integration: starting build"
|
|
60
|
+
And the output should contain "Build failed"
|
|
61
|
+
And the output should contain "Automated tests failed!"
|
|
62
|
+
And the output should not contain "Deploy Succeeded"
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Feature: bard deploy git workflow
|
|
2
|
+
Git workflow behaviors during deploy.
|
|
3
|
+
|
|
4
|
+
Background:
|
|
5
|
+
Given a test server is running
|
|
6
|
+
|
|
7
|
+
Scenario: deploy on master pushes unpushed commits
|
|
8
|
+
Given I create a file "local-only.txt" with content "local commit"
|
|
9
|
+
And I commit the changes with message "Add local only file"
|
|
10
|
+
When I run: bard deploy --skip-ci
|
|
11
|
+
Then the output should contain "Deploy Succeeded"
|
|
12
|
+
When I run: bard run "cat local-only.txt"
|
|
13
|
+
Then the output should contain "local commit"
|
|
14
|
+
|
|
15
|
+
Scenario: feature branch fast-forward merge
|
|
16
|
+
Given I create and switch to branch "feature-branch"
|
|
17
|
+
And I create a file "feature.txt" with content "feature content"
|
|
18
|
+
And I commit the changes with message "Add feature"
|
|
19
|
+
When I run: bard deploy --skip-ci
|
|
20
|
+
Then the output should contain "Deploy Succeeded"
|
|
21
|
+
And I should be on branch "master"
|
|
22
|
+
And branch "feature-branch" should not exist locally
|
|
23
|
+
And branch "feature-branch" should not exist on origin
|
|
24
|
+
When I run: bard run "cat feature.txt"
|
|
25
|
+
Then the output should contain "feature content"
|
|
26
|
+
|
|
27
|
+
Scenario: feature branch requires rebase
|
|
28
|
+
Given I create and switch to branch "feature-branch"
|
|
29
|
+
And I create a file "feature.txt" with content "feature content"
|
|
30
|
+
And I commit the changes with message "Add feature"
|
|
31
|
+
And master has an additional commit from another source
|
|
32
|
+
When I run: bard deploy --skip-ci
|
|
33
|
+
Then the output should contain "The master branch has advanced"
|
|
34
|
+
And the output should contain "Attempting rebase"
|
|
35
|
+
And the output should contain "Deploy Succeeded"
|
|
36
|
+
And I should be on branch "master"
|
|
37
|
+
When I run: bard run "cat feature.txt"
|
|
38
|
+
Then the output should contain "feature content"
|
|
39
|
+
When I run: bard run "cat remote-change.txt"
|
|
40
|
+
Then the output should contain "remote change"
|
|
41
|
+
|
|
42
|
+
Scenario: feature branch rebase conflict
|
|
43
|
+
Given I create and switch to branch "feature-branch"
|
|
44
|
+
And I create a file "conflict.txt" with content "feature content"
|
|
45
|
+
And I commit the changes with message "Add conflicting file"
|
|
46
|
+
And master has a conflicting commit to "conflict.txt"
|
|
47
|
+
When I run expecting failure: bard deploy --skip-ci
|
|
48
|
+
Then the output should contain "The master branch has advanced"
|
|
49
|
+
And the output should contain "Attempting rebase"
|
|
50
|
+
And the output should contain "Running command failed"
|
|
51
|
+
|
|
52
|
+
Scenario: branch cleanup after deploy
|
|
53
|
+
Given I create and switch to branch "cleanup-test"
|
|
54
|
+
And I create a file "cleanup.txt" with content "cleanup test"
|
|
55
|
+
And I commit the changes with message "Add cleanup test file"
|
|
56
|
+
And I push branch "cleanup-test" to origin
|
|
57
|
+
When I run: bard deploy --skip-ci
|
|
58
|
+
Then the output should contain "Deleting branch: cleanup-test"
|
|
59
|
+
And the output should contain "Deploy Succeeded"
|
|
60
|
+
And I should be on branch "master"
|
|
61
|
+
And branch "cleanup-test" should not exist locally
|
|
62
|
+
And branch "cleanup-test" should not exist on origin
|
|
63
|
+
|
|
64
|
+
Scenario: deploy a branch without checking it out
|
|
65
|
+
Given I create and switch to branch "feature-branch"
|
|
66
|
+
And I create a file "feature.txt" with content "feature content"
|
|
67
|
+
And I commit the changes with message "Add feature"
|
|
68
|
+
And I switch to branch "master"
|
|
69
|
+
When I run: bard deploy feature-branch --skip-ci
|
|
70
|
+
Then the output should contain "Deploy Succeeded"
|
|
71
|
+
And I should be on branch "master"
|
|
72
|
+
And branch "feature-branch" should not exist locally
|
|
73
|
+
When I run: bard run "cat feature.txt"
|
|
74
|
+
Then the output should contain "feature content"
|
|
75
|
+
|
|
76
|
+
Scenario: deploy a branch that requires rebase without checking it out
|
|
77
|
+
Given I create and switch to branch "feature-branch"
|
|
78
|
+
And I create a file "feature.txt" with content "feature content"
|
|
79
|
+
And I commit the changes with message "Add feature"
|
|
80
|
+
And I switch to branch "master"
|
|
81
|
+
And master has an additional commit from another source
|
|
82
|
+
When I run: bard deploy feature-branch --skip-ci
|
|
83
|
+
Then the output should contain "The master branch has advanced"
|
|
84
|
+
And the output should contain "Attempting rebase"
|
|
85
|
+
And the output should contain "Deploy Succeeded"
|
|
86
|
+
And I should be on branch "master"
|
|
87
|
+
When I run: bard run "cat feature.txt"
|
|
88
|
+
Then the output should contain "feature content"
|
|
@@ -37,3 +37,99 @@ Then /^a file "([^\"]+)" should exist locally$/ do |filename|
|
|
|
37
37
|
path = File.join(@test_dir, filename)
|
|
38
38
|
expect(File.exist?(path)).to be(true), "Expected file #{filename} to exist at #{path}"
|
|
39
39
|
end
|
|
40
|
+
|
|
41
|
+
# Branch management
|
|
42
|
+
Given /^I create and switch to branch "([^"]+)"$/ do |branch_name|
|
|
43
|
+
Dir.chdir(@test_dir) do
|
|
44
|
+
system("git checkout -b #{branch_name}", out: File::NULL, err: File::NULL)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Then /^I should be on branch "([^"]+)"$/ do |expected_branch|
|
|
49
|
+
Dir.chdir(@test_dir) do
|
|
50
|
+
current = `git rev-parse --abbrev-ref HEAD`.chomp
|
|
51
|
+
expect(current).to eq(expected_branch)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Given /^I push branch "([^"]+)" to origin$/ do |branch_name|
|
|
56
|
+
Dir.chdir(@test_dir) do
|
|
57
|
+
system("git push -u origin #{branch_name}", out: File::NULL, err: File::NULL)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
Then /^branch "([^"]+)" should not exist locally$/ do |branch_name|
|
|
62
|
+
Dir.chdir(@test_dir) do
|
|
63
|
+
result = system("git rev-parse --verify #{branch_name}", out: File::NULL, err: File::NULL)
|
|
64
|
+
expect(result).to be(false), "Expected branch #{branch_name} to not exist locally"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
Then /^branch "([^"]+)" should not exist on origin$/ do |branch_name|
|
|
69
|
+
Dir.chdir(@test_dir) do
|
|
70
|
+
system("git fetch --prune origin", out: File::NULL, err: File::NULL)
|
|
71
|
+
result = system("git rev-parse --verify origin/#{branch_name}", out: File::NULL, err: File::NULL)
|
|
72
|
+
expect(result).to be(false), "Expected branch #{branch_name} to not exist on origin"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Simulating remote changes
|
|
77
|
+
Given /^master has an additional commit from another source$/ do
|
|
78
|
+
run_ssh "cd ~/testproject && git pull origin master"
|
|
79
|
+
run_ssh "cd ~/testproject && echo 'remote change' > remote-change.txt"
|
|
80
|
+
run_ssh "cd ~/testproject && git add remote-change.txt"
|
|
81
|
+
run_ssh "cd ~/testproject && git commit -m 'Remote commit on master'"
|
|
82
|
+
run_ssh "cd ~/testproject && git push origin master"
|
|
83
|
+
|
|
84
|
+
Dir.chdir(@test_dir) do
|
|
85
|
+
system("git fetch origin", out: File::NULL, err: File::NULL)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
Given /^master has a conflicting commit to "([^"]+)"$/ do |filename|
|
|
90
|
+
run_ssh "cd ~/testproject && git pull origin master"
|
|
91
|
+
run_ssh "cd ~/testproject && echo 'conflicting content from remote' > #{filename}"
|
|
92
|
+
run_ssh "cd ~/testproject && git add #{filename}"
|
|
93
|
+
run_ssh "cd ~/testproject && git commit -m 'Remote conflicting commit'"
|
|
94
|
+
run_ssh "cd ~/testproject && git push origin master"
|
|
95
|
+
|
|
96
|
+
Dir.chdir(@test_dir) do
|
|
97
|
+
system("git fetch origin", out: File::NULL, err: File::NULL)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# CI setup
|
|
102
|
+
Given /^a local CI script that passes$/ do
|
|
103
|
+
Dir.chdir(@test_dir) do
|
|
104
|
+
File.write("bin/rake", <<~'SCRIPT')
|
|
105
|
+
#!/bin/bash
|
|
106
|
+
case "$1" in
|
|
107
|
+
ci) echo "All tests passed!"; exit 0 ;;
|
|
108
|
+
esac
|
|
109
|
+
SCRIPT
|
|
110
|
+
FileUtils.chmod(0o755, "bin/rake")
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
Given /^a local CI script that fails with "([^"]+)"$/ do |error_message|
|
|
115
|
+
Dir.chdir(@test_dir) do
|
|
116
|
+
File.write("bin/rake", <<~SCRIPT)
|
|
117
|
+
#!/bin/bash
|
|
118
|
+
case "$1" in
|
|
119
|
+
ci) echo "#{error_message}"; exit 1 ;;
|
|
120
|
+
esac
|
|
121
|
+
SCRIPT
|
|
122
|
+
FileUtils.chmod(0o755, "bin/rake")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
Given /^I switch to branch "([^"]+)"$/ do |branch_name|
|
|
127
|
+
Dir.chdir(@test_dir) do
|
|
128
|
+
system("git checkout #{branch_name}", out: File::NULL, err: File::NULL)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Output negation
|
|
133
|
+
Then /^the output should not contain "([^"]+)"$/ do |unexpected|
|
|
134
|
+
expect(@stdout).not_to include(unexpected)
|
|
135
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
root = File.expand_path("../../..", __FILE__)
|
|
3
|
+
|
|
4
|
+
require "simplecov"
|
|
5
|
+
SimpleCov.root(root)
|
|
6
|
+
SimpleCov.start do
|
|
7
|
+
command_name "Cucumber (subprocess #{$$})"
|
|
8
|
+
track_files "lib/**/*.rb"
|
|
9
|
+
add_filter "spec/"
|
|
10
|
+
add_filter "features/"
|
|
11
|
+
coverage_dir "#{root}/coverage"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
$LOAD_PATH.unshift("#{root}/lib")
|
|
15
|
+
require "bard/cli"
|
|
16
|
+
Bard::CLI.start ARGV
|
data/features/support/env.rb
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
require "simplecov"
|
|
2
|
+
SimpleCov.start do
|
|
3
|
+
command_name "Cucumber"
|
|
4
|
+
track_files "lib/**/*.rb"
|
|
5
|
+
add_filter "spec/"
|
|
6
|
+
add_filter "features/"
|
|
7
|
+
end
|
|
8
|
+
|
|
1
9
|
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
|
|
10
|
+
require "bard"
|
|
2
11
|
require 'rspec/expectations'
|
|
3
12
|
require 'fileutils'
|
|
4
13
|
|
|
5
|
-
ENV["PATH"] = "#{File.dirname(File.expand_path(__FILE__))}
|
|
14
|
+
ENV["PATH"] = "#{File.dirname(File.expand_path(__FILE__))}:#{ENV['PATH']}"
|
|
6
15
|
ENV["GIT_DIR"] = nil
|
|
7
16
|
ENV["GIT_WORK_TREE"] = nil
|
|
8
17
|
ENV["GIT_INDEX_FILE"] = nil
|
|
@@ -184,7 +184,8 @@ SCRIPT
|
|
|
184
184
|
|
|
185
185
|
def run_bard(command)
|
|
186
186
|
Dir.chdir(@test_dir) do
|
|
187
|
-
|
|
187
|
+
bard_coverage = File.join(ROOT, "features/support/bard-coverage")
|
|
188
|
+
@stdout, @status = Open3.capture2e("#{bard_coverage} #{command}")
|
|
188
189
|
end
|
|
189
190
|
end
|
|
190
191
|
|