busser 0.9.0 → 0.9.2
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/.github/workflows/publish.yml +22 -0
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +1 -4
- data/CHANGELOG.md +18 -0
- data/Gemfile +12 -5
- data/README.md +82 -0
- data/Rakefile +19 -1
- data/busser.gemspec +11 -8
- data/features/plugin_create_command.feature +7 -9
- data/lib/busser/command/deserialize.rb +4 -0
- data/lib/busser/command/plugin_create.rb +46 -3
- data/lib/busser/command/plugin_install.rb +40 -4
- data/lib/busser/command/plugin_list.rb +16 -4
- data/lib/busser/command/setup.rb +37 -3
- data/lib/busser/command/suite_cleanup.rb +3 -0
- data/lib/busser/command/suite_path.rb +3 -0
- data/lib/busser/command/test.rb +38 -1
- data/lib/busser/cucumber/hooks.rb +9 -0
- data/lib/busser/helpers.rb +24 -0
- data/lib/busser/plugin.rb +51 -9
- data/lib/busser/rubygems.rb +20 -0
- data/lib/busser/runner_plugin/dummy.rb +3 -0
- data/lib/busser/runner_plugin.rb +5 -0
- data/lib/busser/thor.rb +23 -0
- data/lib/busser/ui.rb +63 -0
- data/lib/busser/version.rb +2 -1
- data/release-please-config.json +3 -1
- data/spec/busser/command/deserialize_spec.rb +0 -1
- data/spec/busser/command/plugin_create_spec.rb +174 -0
- data/spec/busser/command/plugin_install_spec.rb +44 -0
- data/spec/busser/command/plugin_list_spec.rb +49 -0
- data/spec/busser/command/setup_spec.rb +120 -0
- data/spec/busser/command/test_spec.rb +36 -0
- data/spec/busser/helpers_spec.rb +10 -10
- data/spec/busser/plugin_spec.rb +0 -1
- data/spec/busser/ui_spec.rb +56 -10
- data/spec/spec_helper.rb +2 -3
- data/templates/plugin/Rakefile.erb +4 -24
- data/templates/plugin/features_env.rb.erb +4 -4
- data/templates/plugin/gemspec.erb +7 -8
- data/templates/plugin/github_workflow.yml.erb +26 -0
- metadata +13 -60
- data/templates/plugin/tailor.erb +0 -4
- data/templates/plugin/travis.yml.erb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cdaf83b2875620df49aa36203b6d4f7f2f6af8065ecbaa218705c949fa96fe04
|
|
4
|
+
data.tar.gz: 40471ed874096d5b55bb8c613a33a7729e761d691f6727e4a848edf0fe398dbd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 01b77c64592e8bed4f630149be35b89e5b3ac9935119f0c62216b5c16c0ae32ef3feb75c61d68ddf1127ea7bafff7de31f5d11297f2498501d9641b74eab163d
|
|
7
|
+
data.tar.gz: 8efbe414c2a434a98ff91be2f368bd2811cf8110bfce65c337859fbe3806ddca29751f9969a1fa9718c75b8ced4b92176ee33b137bf93b2046cace29fe77f0f6
|
|
@@ -43,3 +43,25 @@ jobs:
|
|
|
43
43
|
uses: actionshub/publish-gem-to-rubygems@f9126f7a2d36a4fd31a13e78fde5fbdcc4b7b251 # v2.0.6
|
|
44
44
|
with:
|
|
45
45
|
token: ${{ secrets.RUBYGEMS_API_KEY }}
|
|
46
|
+
|
|
47
|
+
# actionshub/publish-gem-to-rubygems logs a rejected push and still exits
|
|
48
|
+
# 0, so a release that never reached RubyGems shows up as a green job.
|
|
49
|
+
# Ask RubyGems directly instead of trusting the step. The v2 endpoint is
|
|
50
|
+
# 404 until the exact version is indexed, so -f turns "not there" into a
|
|
51
|
+
# non-zero exit rather than a substring match on `gem list` output.
|
|
52
|
+
- name: Verify the release reached RubyGems
|
|
53
|
+
if: ${{ steps.release.outputs.release_created }}
|
|
54
|
+
env:
|
|
55
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
56
|
+
run: |
|
|
57
|
+
set -euo pipefail
|
|
58
|
+
name="$(basename "$(ls ./*.gemspec)" .gemspec)"
|
|
59
|
+
for _ in $(seq 1 12); do
|
|
60
|
+
if curl -fsS -o /dev/null "https://rubygems.org/api/v2/rubygems/${name}/versions/${VERSION}.json"; then
|
|
61
|
+
echo "${name} ${VERSION} is on RubyGems"
|
|
62
|
+
exit 0
|
|
63
|
+
fi
|
|
64
|
+
sleep 15
|
|
65
|
+
done
|
|
66
|
+
echo "::error::${name} ${VERSION} never reached RubyGems. A permissions failure in the push step above does not fail that step -- read its log."
|
|
67
|
+
exit 1
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -33,6 +33,24 @@ main reason to take this version.
|
|
|
33
33
|
* Rewritten README, and development documentation moved to
|
|
34
34
|
CONTRIBUTING.md ([#63](https://github.com/test-kitchen/busser/pull/63))
|
|
35
35
|
|
|
36
|
+
## [0.9.2](https://github.com/test-kitchen/busser/compare/v0.9.1...v0.9.2) (2026-08-28)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Bug Fixes
|
|
40
|
+
|
|
41
|
+
* quote the prepare.sh path before handing it to a shell ([#73](https://github.com/test-kitchen/busser/issues/73)) ([00a24a4](https://github.com/test-kitchen/busser/commit/00a24a4d4c286f50ac698b2cda9e9600b1c54322))
|
|
42
|
+
* restore SSL verification if a plugin postinstall raises ([#72](https://github.com/test-kitchen/busser/issues/72)) ([7f26adb](https://github.com/test-kitchen/busser/commit/7f26adbca1682bd152afb8fc15d90feb55c15d8e))
|
|
43
|
+
* stop `busser plugin list` printing git errors and a phantom plugin ([#77](https://github.com/test-kitchen/busser/issues/77)) ([7a99ebd](https://github.com/test-kitchen/busser/commit/7a99ebd8453ddc836bc0abf0af0f639f07b8d554))
|
|
44
|
+
* tell Thor to exit non-zero when a command fails ([#76](https://github.com/test-kitchen/busser/issues/76)) ([218ba31](https://github.com/test-kitchen/busser/commit/218ba31b812db55cba2479ba6345d305743cb0c1))
|
|
45
|
+
|
|
46
|
+
## [0.9.1](https://github.com/test-kitchen/busser/compare/v0.9.0...v0.9.1) (2026-08-28)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### Bug Fixes
|
|
50
|
+
|
|
51
|
+
* generate a plugin project that resolves and builds ([#68](https://github.com/test-kitchen/busser/issues/68)) ([0c9a450](https://github.com/test-kitchen/busser/commit/0c9a450af83f086ac3627be938db856c9657208b))
|
|
52
|
+
* report signals and keep bundler out of the busser binstub ([#66](https://github.com/test-kitchen/busser/issues/66)) ([4fc9b35](https://github.com/test-kitchen/busser/commit/4fc9b350c7e3990c82ce4e229927be60a6431ee7))
|
|
53
|
+
|
|
36
54
|
## 0.8.0 / 2020-08-20
|
|
37
55
|
|
|
38
56
|
- Add http_proxy support to `busser plugin install`
|
data/Gemfile
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
source "https://rubygems.org"
|
|
2
2
|
|
|
3
|
-
gemspec
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
4
5
|
group :cookstyle do
|
|
5
|
-
gem "cookstyle"
|
|
6
|
+
gem "cookstyle", ">= 9.0"
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
group :test do
|
|
9
|
-
gem "
|
|
10
|
-
gem "base64" # cucumber needs it; not a default gem on Ruby 4.0
|
|
10
|
+
gem "aruba", ">= 2.4"
|
|
11
|
+
gem "base64", ">= 0.3" # cucumber needs it; not a default gem on Ruby 4.0
|
|
11
12
|
gem "cucumber", ">= 11.1"
|
|
12
|
-
gem "
|
|
13
|
+
gem "minitest", ">= 6.0"
|
|
14
|
+
gem "mocha", ">= 2.7"
|
|
15
|
+
gem "rake", ">= 13.4"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
group :development do
|
|
19
|
+
gem "yard", ">= 0.9.37"
|
|
13
20
|
end
|
data/README.md
CHANGED
|
@@ -87,6 +87,88 @@ busser test
|
|
|
87
87
|
busser test bash minitest
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
## Using Busser with Test Kitchen
|
|
91
|
+
|
|
92
|
+
This is how most people meet Busser, and it needs no `busser` commands of your
|
|
93
|
+
own. Select the verifier in `kitchen.yml`:
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
verifier:
|
|
97
|
+
name: busser
|
|
98
|
+
|
|
99
|
+
suites:
|
|
100
|
+
- name: default
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Then put tests in a directory named after the plugin that should run them,
|
|
104
|
+
inside the suite:
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
test/integration/default/bash/smoke_test.sh
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`kitchen verify` installs Busser and the matching plugin on the instance, then
|
|
111
|
+
runs the suite. Which plugin runs is decided by that directory name alone --
|
|
112
|
+
`bash/` is picked up by busser-bash, `minitest/` by busser-minitest, and so on.
|
|
113
|
+
There is nothing else to configure.
|
|
114
|
+
|
|
115
|
+
## A worked example, without Test Kitchen
|
|
116
|
+
|
|
117
|
+
To see Busser on its own, set a `BUSSER_ROOT` you can write to:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
export BUSSER_ROOT=/tmp/busser
|
|
121
|
+
busser setup
|
|
122
|
+
busser plugin install busser-bash
|
|
123
|
+
mkdir -p "$BUSSER_ROOT/suites/bash"
|
|
124
|
+
|
|
125
|
+
cat > "$BUSSER_ROOT/suites/bash/smoke_test.sh" <<'SH'
|
|
126
|
+
#!/usr/bin/env bash
|
|
127
|
+
set -euo pipefail
|
|
128
|
+
echo hello
|
|
129
|
+
SH
|
|
130
|
+
|
|
131
|
+
busser test bash
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
A passing run looks like this, and exits `0`:
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
-----> Running bash test suite
|
|
138
|
+
-----> [bash] smoke_test.sh
|
|
139
|
+
hello
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
A failing one names the command and exits non-zero:
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
-----> Running bash test suite
|
|
146
|
+
-----> [bash] smoke_test.sh
|
|
147
|
+
!!!!!! Command [bash /tmp/busser/suites/bash/smoke_test.sh] exit code was 1
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## When nothing runs
|
|
151
|
+
|
|
152
|
+
A suite whose files do not match what the plugin looks for produces this, and
|
|
153
|
+
**exits `0`**:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
-----> Running bash test suite
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
No tests ran, and nothing said so. If a suite looks like it is being skipped,
|
|
160
|
+
work through these in order:
|
|
161
|
+
|
|
162
|
+
1. **Is the plugin installed?** `busser plugin list` shows what is available.
|
|
163
|
+
Without the plugin, `busser test` has no runner for that directory.
|
|
164
|
+
2. **Is the directory named after the plugin?** Tests for busser-bash live in
|
|
165
|
+
`bash/`, not `tests/` or `scripts/`.
|
|
166
|
+
3. **Do the filenames match?** Each plugin globs for its own pattern -- for
|
|
167
|
+
example busser-bash takes `*_test.sh` and `*_spec.bash` but ignores
|
|
168
|
+
`mytest.sh`. Each plugin's README states its pattern.
|
|
169
|
+
4. **Is `BUSSER_ROOT` what you think?** `busser suite path` prints where suites
|
|
170
|
+
are actually being looked for.
|
|
171
|
+
|
|
90
172
|
## Contributing
|
|
91
173
|
|
|
92
174
|
Bug reports and pull requests are welcome. See
|
data/Rakefile
CHANGED
|
@@ -9,7 +9,25 @@ Rake::TestTask.new(:unit) do |t|
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
Cucumber::Rake::Task.new(:features) do |t|
|
|
12
|
-
t.cucumber_opts = ["features", "
|
|
12
|
+
t.cucumber_opts = ["features", "--format progress", "--fail-fast"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# yard lives in the :development group, which CI omits when it runs the tests.
|
|
16
|
+
# Requiring it unconditionally would make `rake test` fail there, so the real
|
|
17
|
+
# task is only defined when yard is installed and a stub explains its absence
|
|
18
|
+
# otherwise. Nothing in CI gates on documentation.
|
|
19
|
+
begin
|
|
20
|
+
require "yard"
|
|
21
|
+
|
|
22
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
|
23
|
+
t.files = ["lib/**/*.rb"]
|
|
24
|
+
t.options = ["--output-dir", "doc", "--markup", "markdown"]
|
|
25
|
+
end
|
|
26
|
+
rescue LoadError
|
|
27
|
+
desc "Generate YARD documentation (install the development group first)"
|
|
28
|
+
task :doc do
|
|
29
|
+
abort "yard is not available. Run `bundle install --with development` first."
|
|
30
|
+
end
|
|
13
31
|
end
|
|
14
32
|
|
|
15
33
|
desc "Run all test suites"
|
data/busser.gemspec
CHANGED
|
@@ -7,25 +7,28 @@ Gem::Specification.new do |spec|
|
|
|
7
7
|
spec.version = Busser::VERSION
|
|
8
8
|
spec.authors = ["Fletcher Nichol"]
|
|
9
9
|
spec.email = ["fnichol@nichol.ca"]
|
|
10
|
-
spec.description =
|
|
10
|
+
spec.description = "Busser - Runs tests for projects in Test Kitchen"
|
|
11
11
|
spec.summary = spec.description
|
|
12
12
|
spec.homepage = "https://github.com/test-kitchen/busser"
|
|
13
13
|
spec.license = "Apache-2.0"
|
|
14
14
|
|
|
15
|
-
spec.
|
|
15
|
+
spec.required_ruby_version = ">= 3.2"
|
|
16
|
+
|
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
16
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
17
19
|
spec.require_paths = ["lib"]
|
|
18
20
|
|
|
19
|
-
spec.
|
|
21
|
+
spec.metadata = {
|
|
22
|
+
"bug_tracker_uri" => "#{spec.homepage}/issues",
|
|
23
|
+
"changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md",
|
|
24
|
+
"documentation_uri" => "#{spec.homepage}/blob/main/README.md",
|
|
25
|
+
"homepage_uri" => spec.homepage,
|
|
26
|
+
"source_code_uri" => spec.homepage,
|
|
27
|
+
}
|
|
20
28
|
|
|
21
29
|
# thor 1.1.0 references DidYouMean::SPELL_CHECKERS, removed in Ruby 3.1,
|
|
22
30
|
# so the CLI crashed on startup on every supported Ruby
|
|
23
31
|
spec.add_dependency "thor", ">= 1.1"
|
|
24
32
|
# base64 is no longer a default gem; deserialize needs it at runtime
|
|
25
33
|
spec.add_dependency "base64"
|
|
26
|
-
|
|
27
|
-
spec.add_development_dependency "aruba", ">= 2.0"
|
|
28
|
-
spec.add_development_dependency "minitest"
|
|
29
|
-
spec.add_development_dependency "mocha"
|
|
30
|
-
spec.add_development_dependency "rake"
|
|
31
34
|
end
|
|
@@ -11,7 +11,7 @@ Feature: Plugin create command
|
|
|
11
11
|
## 0.1.0 / Unreleased
|
|
12
12
|
"""
|
|
13
13
|
And the file "busser-junit/Gemfile" should contain "gemspec"
|
|
14
|
-
And the file "busser-junit/Rakefile" should contain "
|
|
14
|
+
And the file "busser-junit/Rakefile" should contain "Cucumber::Rake::Task"
|
|
15
15
|
And the file "busser-junit/README.md" should contain:
|
|
16
16
|
"""
|
|
17
17
|
Busser::RunnerPlugin::Junit
|
|
@@ -28,15 +28,13 @@ Feature: Plugin create command
|
|
|
28
28
|
"""
|
|
29
29
|
Gemfile.lock
|
|
30
30
|
"""
|
|
31
|
-
And the file "busser-junit/.
|
|
31
|
+
And the file "busser-junit/.github/workflows/test.yml" should contain:
|
|
32
32
|
"""
|
|
33
|
-
|
|
33
|
+
bundle exec rake test
|
|
34
34
|
"""
|
|
35
|
-
And
|
|
36
|
-
""
|
|
37
|
-
|
|
38
|
-
"""
|
|
39
|
-
And a file named "busser-junit/.cane" should exist
|
|
35
|
+
And a file named "busser-junit/.travis.yml" should not exist
|
|
36
|
+
And a file named "busser-junit/.tailor" should not exist
|
|
37
|
+
And a file named "busser-junit/.cane" should not exist
|
|
40
38
|
And the file "busser-junit/lib/busser/junit/version.rb" should contain:
|
|
41
39
|
"""
|
|
42
40
|
module Busser
|
|
@@ -49,7 +47,7 @@ Feature: Plugin create command
|
|
|
49
47
|
"""
|
|
50
48
|
And the file "busser-junit/features/support/env.rb" should contain:
|
|
51
49
|
"""
|
|
52
|
-
require
|
|
50
|
+
require "busser/cucumber"
|
|
53
51
|
"""
|
|
54
52
|
And the file "busser-junit/features/plugin_install_command.feature" should contain:
|
|
55
53
|
"""
|
|
@@ -38,6 +38,10 @@ module Busser
|
|
|
38
38
|
|
|
39
39
|
class_option :perms, desc: "Unix permissions on destination file"
|
|
40
40
|
|
|
41
|
+
# Writes a file that was streamed in over stdin, checking it arrived
|
|
42
|
+
# intact before applying its permissions.
|
|
43
|
+
#
|
|
44
|
+
# @return [void]
|
|
41
45
|
def perform
|
|
42
46
|
file = File.expand_path(options[:destination])
|
|
43
47
|
contents = Base64.decode64(STDIN.read)
|
|
@@ -36,6 +36,9 @@ module Busser
|
|
|
36
36
|
class_option :license, aliases: "-l", default: "apachev2",
|
|
37
37
|
desc: "License type for gem (apachev2, mit, lgplv3, reserved)"
|
|
38
38
|
|
|
39
|
+
# Generates a new runner plugin project.
|
|
40
|
+
#
|
|
41
|
+
# @return [void]
|
|
39
42
|
def create
|
|
40
43
|
self.class.source_root(Busser.source_root.join("templates", "plugin"))
|
|
41
44
|
|
|
@@ -47,6 +50,9 @@ module Busser
|
|
|
47
50
|
|
|
48
51
|
private
|
|
49
52
|
|
|
53
|
+
# Writes the gemspec, Gemfile, Rakefile, README and licence.
|
|
54
|
+
#
|
|
55
|
+
# @return [void]
|
|
50
56
|
def create_core_files
|
|
51
57
|
empty_directory(target_dir)
|
|
52
58
|
|
|
@@ -57,11 +63,12 @@ module Busser
|
|
|
57
63
|
create_template("gemspec.erb", "#{config[:gem_name]}.gemspec")
|
|
58
64
|
create_template("license_#{config[:license]}.erb", license_filename)
|
|
59
65
|
create_template("gitignore.erb", ".gitignore")
|
|
60
|
-
create_template("
|
|
61
|
-
create_template("travis.yml.erb", ".travis.yml")
|
|
62
|
-
create_file(File.join(target_dir, ".cane"))
|
|
66
|
+
create_template("github_workflow.yml.erb", ".github/workflows/test.yml")
|
|
63
67
|
end
|
|
64
68
|
|
|
69
|
+
# Writes lib/, the version file and the runner plugin class.
|
|
70
|
+
#
|
|
71
|
+
# @return [void]
|
|
65
72
|
def create_source_files
|
|
66
73
|
empty_directory(File.join(target_dir, "lib/busser", name))
|
|
67
74
|
empty_directory(File.join(target_dir, "lib/busser/runner_plugin"))
|
|
@@ -76,6 +83,9 @@ module Busser
|
|
|
76
83
|
)
|
|
77
84
|
end
|
|
78
85
|
|
|
86
|
+
# Writes a starter cucumber suite for the new plugin.
|
|
87
|
+
#
|
|
88
|
+
# @return [void]
|
|
79
89
|
def create_features_files
|
|
80
90
|
empty_directory(File.join(target_dir, "features/support"))
|
|
81
91
|
|
|
@@ -97,6 +107,10 @@ module Busser
|
|
|
97
107
|
)
|
|
98
108
|
end
|
|
99
109
|
|
|
110
|
+
# Runs git init in the generated project, so the gemspec's
|
|
111
|
+
# `git ls-files` has something to read.
|
|
112
|
+
#
|
|
113
|
+
# @return [void]
|
|
100
114
|
def initialize_git
|
|
101
115
|
inside(target_dir) do
|
|
102
116
|
run("git init")
|
|
@@ -104,14 +118,21 @@ module Busser
|
|
|
104
118
|
end
|
|
105
119
|
end
|
|
106
120
|
|
|
121
|
+
# @param erb [String] template path, relative to the templates directory
|
|
122
|
+
# @param dest [String] destination path, relative to the target directory
|
|
123
|
+
# @return [void]
|
|
107
124
|
def create_template(erb, dest)
|
|
108
125
|
template(erb, File.join(target_dir, dest), config)
|
|
109
126
|
end
|
|
110
127
|
|
|
128
|
+
# @return [String] directory the new plugin is generated into
|
|
111
129
|
def target_dir
|
|
112
130
|
File.join(Dir.pwd, "busser-#{name}")
|
|
113
131
|
end
|
|
114
132
|
|
|
133
|
+
# Values the templates interpolate.
|
|
134
|
+
#
|
|
135
|
+
# @return [Hash] the template binding
|
|
115
136
|
def config
|
|
116
137
|
@config ||= begin
|
|
117
138
|
type_klass_name = "#{::Thor::Util.camel_case(options[:type])}Plugin"
|
|
@@ -128,21 +149,25 @@ module Busser
|
|
|
128
149
|
email: email,
|
|
129
150
|
license: options[:license],
|
|
130
151
|
license_string: license_string,
|
|
152
|
+
license_spdx: license_spdx,
|
|
131
153
|
year: Time.now.year,
|
|
132
154
|
}
|
|
133
155
|
end
|
|
134
156
|
end
|
|
135
157
|
|
|
158
|
+
# @return [String] the author name, from git config where available
|
|
136
159
|
def author
|
|
137
160
|
git_user_name = `git config user.name`.chomp
|
|
138
161
|
git_user_name.empty? ? "TODO: Write your name" : git_user_name
|
|
139
162
|
end
|
|
140
163
|
|
|
164
|
+
# @return [String] the author email, from git config where available
|
|
141
165
|
def email
|
|
142
166
|
git_user_email = `git config user.email`.chomp
|
|
143
167
|
git_user_email.empty? ? "TODO: Write your email" : git_user_email
|
|
144
168
|
end
|
|
145
169
|
|
|
170
|
+
# @return [String] full licence text for the chosen licence
|
|
146
171
|
def license_string
|
|
147
172
|
case options[:license]
|
|
148
173
|
when "mit" then "MIT"
|
|
@@ -154,6 +179,23 @@ module Busser
|
|
|
154
179
|
end
|
|
155
180
|
end
|
|
156
181
|
|
|
182
|
+
# RubyGems validates spec.license against the SPDX list and warns on
|
|
183
|
+
# anything else, so the gemspec cannot reuse the human readable name
|
|
184
|
+
# that the README wants. "All rights reserved" has no SPDX identifier,
|
|
185
|
+
# so those gemspecs declare no license at all.
|
|
186
|
+
def license_spdx
|
|
187
|
+
case options[:license]
|
|
188
|
+
when "mit" then "MIT"
|
|
189
|
+
when "apachev2" then "Apache-2.0"
|
|
190
|
+
when "lgplv3" then "LGPL-3.0-only"
|
|
191
|
+
when "reserved" then nil
|
|
192
|
+
else
|
|
193
|
+
raise ArgumentError, "No such license #{options[:license]}"
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# @return [String] the filename the licence is written to, which differs
|
|
198
|
+
# by licence
|
|
157
199
|
def license_filename
|
|
158
200
|
case options[:license]
|
|
159
201
|
when "mit" then "LICENSE.txt"
|
|
@@ -164,6 +206,7 @@ module Busser
|
|
|
164
206
|
end
|
|
165
207
|
end
|
|
166
208
|
|
|
209
|
+
# @return [String] the licence header comment prepended to source files
|
|
167
210
|
def license_comment
|
|
168
211
|
@license_comment ||= IO.read(File.join(target_dir, license_filename))
|
|
169
212
|
.gsub(/^/, "# ").gsub(/\s+$/, "")
|
|
@@ -40,6 +40,9 @@ module Busser
|
|
|
40
40
|
class_option :verbose, type: :boolean, default: false,
|
|
41
41
|
desc: "Set a more verbose output"
|
|
42
42
|
|
|
43
|
+
# Installs each requested plugin.
|
|
44
|
+
#
|
|
45
|
+
# @return [void]
|
|
43
46
|
def install_all
|
|
44
47
|
if options[:verbose]
|
|
45
48
|
Gem.configuration.verbose = 2 if options[:verbose]
|
|
@@ -53,6 +56,10 @@ module Busser
|
|
|
53
56
|
|
|
54
57
|
private
|
|
55
58
|
|
|
59
|
+
# Installs one plugin and runs its postinstall.
|
|
60
|
+
#
|
|
61
|
+
# @param plugin [String] gem name, optionally suffixed with @version
|
|
62
|
+
# @return [void]
|
|
56
63
|
def install(plugin)
|
|
57
64
|
gem_name, version = plugin.split("@")
|
|
58
65
|
name = gem_name.sub(/^busser-/, "")
|
|
@@ -65,6 +72,12 @@ module Busser
|
|
|
65
72
|
end
|
|
66
73
|
end
|
|
67
74
|
|
|
75
|
+
# Installs the plugin gem unless it is already available.
|
|
76
|
+
#
|
|
77
|
+
# @param gem [String] the gem name
|
|
78
|
+
# @param version [String, nil] a version requirement, or nil for any
|
|
79
|
+
# @param name [String] short plugin name, for the message
|
|
80
|
+
# @return [Boolean] true if the gem was newly installed
|
|
68
81
|
def install_plugin_gem(gem, version, name)
|
|
69
82
|
if internal_plugin?(name) || gem_installed?(gem, version)
|
|
70
83
|
info "Plugin #{name} already installed"
|
|
@@ -76,10 +89,17 @@ module Busser
|
|
|
76
89
|
end
|
|
77
90
|
end
|
|
78
91
|
|
|
92
|
+
# @param name [String] short plugin name
|
|
93
|
+
# @return [void]
|
|
79
94
|
def load_plugin(name)
|
|
80
95
|
Busser::Plugin.require!(Busser::Plugin.runner_plugin(name))
|
|
81
96
|
end
|
|
82
97
|
|
|
98
|
+
# Runs the plugin's postinstall block, which is where a plugin installs
|
|
99
|
+
# the test framework it drives.
|
|
100
|
+
#
|
|
101
|
+
# @param name [String] short plugin name
|
|
102
|
+
# @return [void]
|
|
83
103
|
def run_postinstall(name)
|
|
84
104
|
klass = Busser::Plugin.runner_class(::Thor::Util.camel_case(name))
|
|
85
105
|
if klass.respond_to?(:run_postinstall)
|
|
@@ -100,13 +120,29 @@ module Busser
|
|
|
100
120
|
#
|
|
101
121
|
# Please use with extreme caution.
|
|
102
122
|
#
|
|
123
|
+
# The restore is in an ensure block. Without one, a postinstall that
|
|
124
|
+
# raised left VERIFY_PEER set to VERIFY_NONE for the rest of the
|
|
125
|
+
# process -- and `busser plugin install` takes a list, so every gem
|
|
126
|
+
# downloaded for every later plugin in that same run would have had its
|
|
127
|
+
# certificate unchecked.
|
|
128
|
+
#
|
|
129
|
+
# @yield the block to run with peer verification dropped
|
|
130
|
+
# @return [void]
|
|
103
131
|
def drop_ssl_verify_peer
|
|
104
132
|
before = OpenSSL::SSL::VERIFY_PEER
|
|
133
|
+
set_ssl_verify_peer(OpenSSL::SSL::VERIFY_NONE)
|
|
134
|
+
begin
|
|
135
|
+
yield
|
|
136
|
+
ensure
|
|
137
|
+
set_ssl_verify_peer(before)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# @param value [Integer] the OpenSSL verify mode to install
|
|
142
|
+
# @return [void]
|
|
143
|
+
def set_ssl_verify_peer(value)
|
|
105
144
|
OpenSSL::SSL.send(:remove_const, "VERIFY_PEER")
|
|
106
|
-
OpenSSL::SSL.const_set("VERIFY_PEER",
|
|
107
|
-
yield
|
|
108
|
-
OpenSSL::SSL.send(:remove_const, "VERIFY_PEER")
|
|
109
|
-
OpenSSL::SSL.const_set("VERIFY_PEER", before)
|
|
145
|
+
OpenSSL::SSL.const_set("VERIFY_PEER", value)
|
|
110
146
|
end
|
|
111
147
|
end
|
|
112
148
|
end
|
|
@@ -28,6 +28,9 @@ module Busser
|
|
|
28
28
|
#
|
|
29
29
|
class PluginList < Busser::Thor::BaseGroup
|
|
30
30
|
|
|
31
|
+
# Prints the installed plugins and their versions.
|
|
32
|
+
#
|
|
33
|
+
# @return [void]
|
|
31
34
|
def list
|
|
32
35
|
if plugin_data.empty?
|
|
33
36
|
say "No plugins installed yet"
|
|
@@ -38,11 +41,20 @@ module Busser
|
|
|
38
41
|
|
|
39
42
|
private
|
|
40
43
|
|
|
44
|
+
# The dummy runner is a fixture shipped inside busser for its own tests,
|
|
45
|
+
# not something anyone installed. `busser test` already passes over it,
|
|
46
|
+
# so listing it as an installed plugin was inconsistent as well as
|
|
47
|
+
# confusing.
|
|
48
|
+
#
|
|
49
|
+
# @return [Array<Array(String, String)>] each installed plugin's short
|
|
50
|
+
# name and version
|
|
41
51
|
def plugin_data
|
|
42
|
-
@plugin_data ||= Busser::Plugin.runner_plugins
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
@plugin_data ||= Busser::Plugin.runner_plugins
|
|
53
|
+
.reject { |path| File.basename(path) == "dummy" }
|
|
54
|
+
.map do |path|
|
|
55
|
+
spec = Busser::Plugin.gem_from_path(path)
|
|
56
|
+
[File.basename(path), (spec && spec.version)]
|
|
57
|
+
end
|
|
46
58
|
end
|
|
47
59
|
end
|
|
48
60
|
end
|