minestrone 0.0.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.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +32 -0
  3. data/.gitignore +5 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +35 -0
  7. data/Rakefile +10 -0
  8. data/bin/capify +89 -0
  9. data/bin/min +5 -0
  10. data/docs/lib-codebase-map.md +162 -0
  11. data/docs/lib-dependency-graph.svg +129 -0
  12. data/lib/minestrone/callback.rb +45 -0
  13. data/lib/minestrone/cli/help.rb +131 -0
  14. data/lib/minestrone/cli/help.txt +72 -0
  15. data/lib/minestrone/cli/options.rb +232 -0
  16. data/lib/minestrone/cli.rb +159 -0
  17. data/lib/minestrone/command.rb +177 -0
  18. data/lib/minestrone/configuration/actions/file_transfer.rb +53 -0
  19. data/lib/minestrone/configuration/actions/inspect.rb +46 -0
  20. data/lib/minestrone/configuration/actions/invocation.rb +202 -0
  21. data/lib/minestrone/configuration/alias_task.rb +29 -0
  22. data/lib/minestrone/configuration/callbacks.rb +129 -0
  23. data/lib/minestrone/configuration/connections.rb +66 -0
  24. data/lib/minestrone/configuration/execution.rb +139 -0
  25. data/lib/minestrone/configuration/loading.rb +207 -0
  26. data/lib/minestrone/configuration/log_formatters.rb +75 -0
  27. data/lib/minestrone/configuration/namespaces.rb +225 -0
  28. data/lib/minestrone/configuration/servers.rb +70 -0
  29. data/lib/minestrone/configuration/variables.rb +115 -0
  30. data/lib/minestrone/configuration.rb +69 -0
  31. data/lib/minestrone/errors.rb +17 -0
  32. data/lib/minestrone/ext/string.rb +7 -0
  33. data/lib/minestrone/extensions.rb +56 -0
  34. data/lib/minestrone/logger.rb +171 -0
  35. data/lib/minestrone/processable.rb +50 -0
  36. data/lib/minestrone/recipes/deploy/assets.rb +194 -0
  37. data/lib/minestrone/recipes/deploy/bundler.rb +81 -0
  38. data/lib/minestrone/recipes/deploy/dependencies.rb +44 -0
  39. data/lib/minestrone/recipes/deploy/local_dependency.rb +45 -0
  40. data/lib/minestrone/recipes/deploy/remote_dependency.rb +119 -0
  41. data/lib/minestrone/recipes/deploy/scm/base.rb +204 -0
  42. data/lib/minestrone/recipes/deploy/scm/git.rb +284 -0
  43. data/lib/minestrone/recipes/deploy/scm/none.rb +54 -0
  44. data/lib/minestrone/recipes/deploy/scm.rb +22 -0
  45. data/lib/minestrone/recipes/deploy/strategy/base.rb +87 -0
  46. data/lib/minestrone/recipes/deploy/strategy/copy.rb +353 -0
  47. data/lib/minestrone/recipes/deploy/strategy/remote_cache.rb +80 -0
  48. data/lib/minestrone/recipes/deploy/strategy.rb +22 -0
  49. data/lib/minestrone/recipes/deploy.rb +639 -0
  50. data/lib/minestrone/recipes/standard.rb +23 -0
  51. data/lib/minestrone/recipes/templates/maintenance.rhtml +53 -0
  52. data/lib/minestrone/server_definition.rb +56 -0
  53. data/lib/minestrone/ssh.rb +81 -0
  54. data/lib/minestrone/task_definition.rb +82 -0
  55. data/lib/minestrone/transfer.rb +205 -0
  56. data/lib/minestrone/version.rb +11 -0
  57. data/lib/minestrone.rb +3 -0
  58. data/minestrone.gemspec +32 -0
  59. data/test/cli/execute_test.rb +130 -0
  60. data/test/cli/help_test.rb +178 -0
  61. data/test/cli/options_test.rb +315 -0
  62. data/test/cli/ui_test.rb +26 -0
  63. data/test/cli_test.rb +17 -0
  64. data/test/command_test.rb +305 -0
  65. data/test/configuration/actions/file_transfer_test.rb +61 -0
  66. data/test/configuration/actions/inspect_test.rb +76 -0
  67. data/test/configuration/actions/invocation_test.rb +258 -0
  68. data/test/configuration/alias_task_test.rb +110 -0
  69. data/test/configuration/callbacks_test.rb +201 -0
  70. data/test/configuration/connections_test.rb +192 -0
  71. data/test/configuration/execution_test.rb +176 -0
  72. data/test/configuration/loading_test.rb +149 -0
  73. data/test/configuration/namespace_dsl_test.rb +325 -0
  74. data/test/configuration/servers_test.rb +100 -0
  75. data/test/configuration/variables_test.rb +191 -0
  76. data/test/configuration_test.rb +77 -0
  77. data/test/deploy/local_dependency_test.rb +61 -0
  78. data/test/deploy/remote_dependency_test.rb +146 -0
  79. data/test/deploy/scm/base_test.rb +55 -0
  80. data/test/deploy/scm/git_test.rb +260 -0
  81. data/test/deploy/scm/none_test.rb +26 -0
  82. data/test/deploy/strategy/copy_test.rb +360 -0
  83. data/test/extensions_test.rb +69 -0
  84. data/test/fixtures/cli_integration.rb +5 -0
  85. data/test/fixtures/config.rb +4 -0
  86. data/test/fixtures/custom.rb +3 -0
  87. data/test/logger_formatting_test.rb +149 -0
  88. data/test/logger_test.rb +134 -0
  89. data/test/recipes_test.rb +26 -0
  90. data/test/server_definition_test.rb +121 -0
  91. data/test/ssh_test.rb +99 -0
  92. data/test/task_definition_test.rb +117 -0
  93. data/test/transfer_test.rb +172 -0
  94. data/test/utils.rb +28 -0
  95. data/test/version_test.rb +11 -0
  96. metadata +258 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6cd69ccb970305b22a5e19099df378e581cb3c15ff188ebdffcf2fef499e6bdd
4
+ data.tar.gz: 7c01180ad806dd649ad13e5682d815179221c85c120aa60dc411d83fffd413de
5
+ SHA512:
6
+ metadata.gz: e8ddd3e8f828248e489f7b22bb9476cb962ea1d04e5973b9cb4a2eed0d3558bd91bdaa8e7142a9151649b041148fa9cb60440a97fcd7bd737a4a7db13b304f25
7
+ data.tar.gz: db1e39316df310daf33fd85aa3c11fecc671ad1ba19f9ccbe4d67e3d47aa370296cb182021e767f16c4b3b841a0cf72110d178c0bec54a69a7869435c044e26a
@@ -0,0 +1,32 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ pull_request:
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ name: Ruby ${{ matrix.ruby }}
14
+ strategy:
15
+ matrix:
16
+ ruby:
17
+ - '3.0'
18
+ - '3.1'
19
+ - '3.2'
20
+ - '3.3'
21
+ - '3.4'
22
+ - '4.0'
23
+
24
+ steps:
25
+ - uses: actions/checkout@v3
26
+ - name: Set up Ruby
27
+ uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: ${{ matrix.ruby }}
30
+ bundler-cache: true
31
+ - name: Run the default task
32
+ run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ .bundle
3
+ coverage
4
+ doc
5
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in minestrone.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'mocha', '~> 3.1'
8
+ gem 'rake', '~> 13.4'
9
+ gem 'test-unit', '~> 3.7'
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ MIT License (MIT)
2
+
3
+ Copyright (c) 2012-2020 Tom Clements, Lee Hambley
4
+ Copyright (c) 2005-2007 Jamis Buck <jamis@37signals.com>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Minestrone 🍲
2
+
3
+ Minestrone is a simplified fork of old [Capistrano](https://github.com/minestrone/minestrone) 2.x. A kind of… mini-capistrano.
4
+
5
+
6
+ ## Project description
7
+
8
+ Minestrone is a tool for deploying Ruby applications to a server, based on the code of the classic deploy tool Capistrano, the older 2.x version, but simplified and cleaned up, with various features removed that I decided I'm never going to need myself. The focus is on deploying Ruby apps to a single host from Git over SSH. It keeps the core deploy DSL with compatibility maintained where possible, the git remote cache and copy strategies, release rotation with rollbacks, and the logging/formatting code.
9
+
10
+
11
+ ### What is removed
12
+
13
+ * server roles, multiple servers and "primary" server designation – you only define a single server hostname and everything happens there
14
+ * support for any parallel execution
15
+ * multiple stages
16
+ * SSH gateways
17
+ * password authentication for SSH and Git
18
+ * Windows support
19
+ * REPL shell
20
+ * legacy SCMs – only `:git` and `:none` are left
21
+ * most deploy strategies – only `:remote_cache` and `:copy` are left
22
+ * any legacy/deprecated code from Capistrano 1.x era or for ancient versions of Ruby
23
+
24
+
25
+ ### Other API changes
26
+
27
+ * default deploy path is `/var/www/#{application}`
28
+ * `server` method in the DSL only accepts a single string + options
29
+ * Ruby 3.0+ is required
30
+
31
+
32
+ ### Project status
33
+
34
+ > [!WARNING]
35
+ > This project is an early, untested alpha version. Most of the work stripping out various parts from the old codebase was done using Codex AI coding agent (with manual code reviews to some degree). Use with caution.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/*_test.rb'
8
+ end
9
+
10
+ task :default => :test
data/bin/capify ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'fileutils'
5
+
6
+ OptionParser.new do |opts|
7
+ opts.banner = "Usage: #{File.basename($0)} [path]"
8
+
9
+ opts.on("-h", "--help", "Displays this help info") do
10
+ puts opts
11
+ exit 0
12
+ end
13
+
14
+ begin
15
+ opts.parse!(ARGV)
16
+ rescue OptionParser::ParseError => e
17
+ warn e.message
18
+ puts opts
19
+ exit 1
20
+ end
21
+ end
22
+
23
+ if ARGV.empty?
24
+ abort "Please specify the directory to capify, e.g. `#{File.basename($0)} .'"
25
+ elsif !File.exist?(ARGV.first)
26
+ abort "`#{ARGV.first}' does not exist."
27
+ elsif !File.directory?(ARGV.first)
28
+ abort "`#{ARGV.first}' is not a directory."
29
+ elsif ARGV.length > 1
30
+ abort "Too many arguments; please specify only the directory to capify."
31
+ end
32
+
33
+ def unindent(string)
34
+ indentation = string[/\A\s*/]
35
+ string.strip.gsub(/^#{indentation}/, "")
36
+ end
37
+
38
+ files = {
39
+ "Capfile" => unindent(<<-FILE),
40
+
41
+ load 'deploy'
42
+ load 'deploy/bundler'
43
+
44
+ # Uncomment if you are using Rails' asset pipeline
45
+ # load 'deploy/assets'
46
+
47
+ load 'config/deploy'
48
+ FILE
49
+
50
+ "config/deploy.rb" => 'set :application, "set your application name here"
51
+ set :repository, "set your repository location here"
52
+
53
+ # set :scm, :git # :git is the default, or set :none to disable
54
+
55
+ server "host.example.com"
56
+
57
+ # if you want to clean up old releases on each deploy uncomment this:
58
+ # after "deploy:restart", "deploy:cleanup"
59
+
60
+ # If you are using Passenger, uncomment this:
61
+ # namespace :deploy do
62
+ # task :start do ; end
63
+ # task :stop do ; end
64
+ # task :restart do
65
+ # run "#{try_sudo} touch #{File.join(current_path,\'tmp\',\'restart.txt\')}"
66
+ # end
67
+ # end'}
68
+
69
+ base = ARGV.shift
70
+
71
+ files.each do |file, content|
72
+ file = File.join(base, file)
73
+
74
+ if File.exist?(file)
75
+ warn "[skip] '#{file}' already exists"
76
+ elsif File.exist?(file.downcase)
77
+ warn "[skip] '#{file.downcase}' exists, which could conflict with `#{file}'"
78
+ else
79
+ unless File.exist?(File.dirname(file))
80
+ puts "[add] making directory '#{File.dirname(file)}'"
81
+ FileUtils.mkdir(File.dirname(file))
82
+ end
83
+
84
+ puts "[add] writing '#{file}'"
85
+ File.open(file, "w") { |f| f.write(content) }
86
+ end
87
+ end
88
+
89
+ puts "[done] capified!"
data/bin/min ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'minestrone/cli'
4
+
5
+ Minestrone::CLI.execute
@@ -0,0 +1,162 @@
1
+ # Minestrone `lib` Codebase Map
2
+
3
+ This document maps the files under `lib/`, the classes/modules they define, what they are for, and the main internal dependencies between them.
4
+
5
+ ## High-Level Shape
6
+
7
+ Minestrone is centered on `Minestrone::Configuration`. The root file loads the configuration DSL, extension/plugin support, and a small `String` helper. `Configuration` mixes in modules for variables, task namespaces, callbacks, single-server selection, recipe loading, SSH connection management, command execution, file transfer, and inspection helpers.
8
+
9
+ Built-in recipes live under `lib/minestrone/recipes`. The deploy recipe composes two plugin families:
10
+
11
+ - `Minestrone::Deploy::SCM`: source control adapters that return shell commands. This tree currently keeps only Git and the no-SCM local-copy adapter.
12
+ - `Minestrone::Deploy::Strategy`: deployment strategies that execute SCM commands locally or remotely.
13
+
14
+ ## File Inventory
15
+
16
+ | File | Classes/modules defined | Purpose | Main internal dependencies |
17
+ | --- | --- | --- | --- |
18
+ | `lib/minestrone.rb` | none directly | Main library entry point. Loads the configuration DSL, plugin extension system, and string helper. | `configuration`, `extensions`, `ext/string` |
19
+ | `lib/minestrone/callback.rb` | `Minestrone::Callback`, `ProcCallback`, `TaskCallback` | Represents callbacks registered around task lifecycle events. `ProcCallback` calls a block, `TaskCallback` executes another Minestrone task and prevents direct self-recursion. | Used by `configuration/callbacks` |
20
+ | `lib/minestrone/cli.rb` | `Minestrone::CLI` | Command-line facade that stores raw args, exposes UI prompts, turns parsed options into a `Configuration`, loads recipes, fires lifecycle hooks, executes requested actions, and handles top-level errors. | `minestrone`, `cli/help`, `cli/options`, `configuration`, `highline` |
21
+ | `lib/minestrone/cli/help.rb` | `Minestrone::CLI::Help` | Overrides CLI action execution for `-T` task listing and `-e` task explanation. Formats long help text. | Mixed into `CLI`; uses `TaskDefinition` data through `Configuration#task_list` and `#find_task` |
22
+ | `lib/minestrone/cli/help.txt` | none | ERB-like help text used by `CLI::Help#long_help`. | Read by `cli/help` |
23
+ | `lib/minestrone/cli/options.rb` | `Minestrone::CLI::Options` | Defines `OptionParser` switches, default config discovery, environment variable extraction, and simple value coercion for `-s` and `-S`. | Mixed into `CLI`; requires `optparse`; uses `Logger`, `Version`, `CLI.password_prompt` |
24
+ | `lib/minestrone/command.rb` | `Minestrone::Command` | Single-session remote command runner. Opens one SSH command channel, handles stdout/stderr callbacks, optional pty, environment injection, placeholder replacement, and remote command errors. | `errors`, `processable`, `Configuration.default_io_proc`, SSH session from `connections` |
25
+ | `lib/minestrone/configuration.rb` | `Minestrone::Configuration` | Central DSL object. Owns logger/debug/dry-run state, explicitly calls each included module's initialization hook, mixes in all configuration and action modules, and unblocks namespace method shadowing. | `logger`; all `configuration/*`; `configuration/actions/*` |
26
+ | `lib/minestrone/configuration/actions/file_transfer.rb` | `Minestrone::Configuration::Actions::FileTransfer` | Adds `put`, `get`, `upload`, `download`, and `transfer` DSL actions. Delegates actual work to `Minestrone::Transfer`. | `transfer`, `Connections#execute_on_server`, `Connections#session`, `run` |
27
+ | `lib/minestrone/configuration/actions/inspect.rb` | `Minestrone::Configuration::Actions::Inspect` | Adds `stream` and `capture` actions for running commands and consuming streamed or captured single-server output. | `errors`, `Invocation#invoke_command`, `sudo` |
28
+ | `lib/minestrone/configuration/actions/invocation.rb` | `Minestrone::Configuration::Actions::Invocation` | Adds `run`, `invoke_command`, `sudo`, command defaults, sudo prompt handling, and debug prompting. Converts DSL command calls into sequential `Command` execution. | `command`, `Servers#active_server`, `Connections#execute_on_server`, `CLI.debug_prompt`, `Variables` |
29
+ | `lib/minestrone/configuration/alias_task.rb` | `Minestrone::Configuration::AliasTask` | Adds `alias_task`, duplicating an existing task under a new name. | `Namespaces#find_task`, `#define_task`, `NoSuchTaskError` |
30
+ | `lib/minestrone/configuration/callbacks.rb` | `Minestrone::Configuration::Callbacks` | Adds task lifecycle hooks: `before`, `after`, `on`, `trigger`. Wraps task invocation so callbacks fire around every direct task call. | `callback`, `Execution#invoke_task_directly`, `Execution#find_and_execute_task` |
31
+ | `lib/minestrone/configuration/connections.rb` | `Minestrone::Configuration::Connections` | Manages the single SSH session, connection failure state, single-server connection establishment/teardown, and continuing after remote errors where requested. | `ssh`, `errors`, `Servers#active_server`, `Execution#current_task` |
32
+ | `lib/minestrone/configuration/execution.rb` | `Minestrone::Configuration::Execution`, `TaskCallFrame` | Runs tasks, tracks the current task stack, implements transactions and `on_rollback`, and locates/executes tasks by name. | `errors`, `Namespaces`, `Callbacks` |
33
+ | `lib/minestrone/configuration/loading.rb` | `Minestrone::Configuration::Loading`, `Loading::ClassMethods` | Loads recipes from files, strings, or procs. Provides a Minestrone-aware `require` that lets multiple configuration instances reload recipe DSL effects. | Used by `CLI`, recipes, extensions |
34
+ | `lib/minestrone/configuration/log_formatters.rb` | `Minestrone::Configuration::LogFormatters` | DSL for adding logger formatters and disabling formatting. | `logger` |
35
+ | `lib/minestrone/configuration/namespaces.rb` | `Minestrone::Configuration::Namespaces`, `Namespaces::Namespace`, `Kernel.method_added` hook | Implements `namespace`, `task`, `desc`, task lookup, namespace lookup, default tasks, and nested namespace forwarding to parent configuration. | `task_definition`, `alias_task`, `execution` |
36
+ | `lib/minestrone/configuration/servers.rb` | `Minestrone::Configuration::Servers` | Adds the single-host `server` DSL and resolves the configured server, with `HOST` as a one-host environment override. | `ServerDefinition`, `errors` |
37
+ | `lib/minestrone/configuration/variables.rb` | `Minestrone::Configuration::Variables` | Configuration variables with lazy proc evaluation, reset/unset, `fetch`, `[]`, and variable-backed `method_missing`. | Used by nearly every DSL and recipe file |
38
+ | `lib/minestrone/errors.rb` | `Minestrone::Error`, `CaptureError`, `NoSuchTaskError`, `NoMatchingServersError`, `RemoteError`, `ConnectionError`, `TransferError`, `CommandError`, `LocalArgumentError` | Shared exception hierarchy. Remote errors carry affected hosts. | Used by command, transfer, connections, execution, recipes, deploy adapters |
39
+ | `lib/minestrone/ext/string.rb` | reopens `String` | Adds `String#compact`, collapsing whitespace. Used to make heredoc shell commands one line. | Used by deploy assets and recipe command heredocs |
40
+ | `lib/minestrone/extensions.rb` | `Minestrone::ExtensionProxy`, `Minestrone::EXTENSIONS`, plugin methods | Plugin registration system. Adds proxy methods to `Configuration` instances and delegates unknown plugin method calls back to the configuration. | `Configuration`, `Error` |
41
+ | `lib/minestrone/logger.rb` | `Minestrone::Logger` | Level-based logger with TTY color/style formatters, timestamp/prepend/append/replace support, and default formatter registration. | Used by `Configuration`, CLI options, command/transfer/strategy/scm code |
42
+ | `lib/minestrone/processable.rb` | `Minestrone::Processable`, `Processable::SessionAssociation` | Shared single-session Net::SSH event loop helper. Preprocesses/postprocesses the session with `IO.select` and associates raised errors with that session. | Included by `Command`, `Transfer` |
43
+ | `lib/minestrone/recipes/deploy.rb` | recipe methods and tasks only | Primary deployment recipe. Defines deploy variables, helpers (`scm_default`, `depend`, `with_env`, `run_locally`, `try_sudo`, `try_runner`), and tasks for setup, update, update_code, symlinks, upload, rollback, migrations, cleanup, checks, cold deploy, start/stop, pending diff/log, and web maintenance mode. Defaults to Git when `.git` exists and `none` otherwise. | `deploy/scm`, `deploy/strategy`, `dependencies`, `Command`/`Transfer` through configuration actions |
44
+ | `lib/minestrone/recipes/deploy/assets.rb` | recipe methods and tasks only | Rails asset-pipeline extension. Hooks into deploy lifecycle to symlink shared assets, precompile, maintain manifest mtimes, clean expired assets, clean all assets, and roll back manifests. | Loads `deploy`; `json`, `yaml` via deploy, `Set` via deploy, `String#compact`, callbacks/tasks/actions |
45
+ | `lib/minestrone/recipes/deploy/dependencies.rb` | `Minestrone::Deploy::Dependencies` | Aggregates local and remote dependency checks and reports pass/fail. | `local_dependency`, `remote_dependency` |
46
+ | `lib/minestrone/recipes/deploy/local_dependency.rb` | `Minestrone::Deploy::LocalDependency` | Checks local command availability in `PATH`. | Used by `Dependencies`, `Strategy::Copy#check!` |
47
+ | `lib/minestrone/recipes/deploy/remote_dependency.rb` | `Minestrone::Deploy::RemoteDependency` | Checks remote directories, files, writability, commands, gems, deb/rpm packages, and expected command output. | `errors`, `Configuration#invoke_command`, `CommandError` |
48
+ | `lib/minestrone/recipes/deploy/scm.rb` | `Minestrone::Deploy::SCM` | Factory module for dynamic SCM adapter loading by name. | Dynamic requires `deploy/scm/<name>`; raises `Minestrone::Error` |
49
+ | `lib/minestrone/recipes/deploy/scm/base.rb` | `Minestrone::Deploy::SCM::Base`, `Base::LocalProxy` | Abstract SCM adapter API. Provides local-mode variable lookup, command construction, default command handling, logging, and abstract checkout/sync/diff/log/query hooks. | `Configuration` variables and logger; subclassed by all SCM adapters |
50
+ | `lib/minestrone/recipes/deploy/scm/git.rb` | `Minestrone::Deploy::SCM::Git` | Git adapter. Supports clone/export/sync, branches/remotes, shallow clones, submodules, diff/log, SHA resolution, and prompt responses for passwords, passphrases, host keys, and certs. | `scm/base`, `CLI.password_prompt` |
51
+ | `lib/minestrone/recipes/deploy/scm/none.rb` | `Minestrone::Deploy::SCM::None` | Non-SCM adapter for copying a local directory. Intended for `deploy_via :copy`; no real history support. | `scm/base` |
52
+ | `lib/minestrone/recipes/deploy/strategy.rb` | `Minestrone::Deploy::Strategy` | Factory module for dynamic deploy strategy loading by name. | Dynamic requires `deploy/strategy/<name>`; raises `Minestrone::Error` |
53
+ | `lib/minestrone/recipes/deploy/strategy/base.rb` | `Minestrone::Deploy::Strategy::Base` | Abstract deployment strategy API. Provides deploy check defaults, configuration method delegation, local `system` logging, and real revision access. | `deploy/dependencies`, `logger`, `Configuration` DSL |
54
+ | `lib/minestrone/recipes/deploy/strategy/copy.rb` | `Minestrone::Deploy::Strategy::Copy`, `Copy::Compression` | Local-copy strategy. Checks out/export locally or refreshes a local cache, optionally builds, excludes files, archives, uploads, extracts remotely, and cleans staging artifacts. | `strategy/base`, `fileutils`, `tempfile`, `LocalDependency`, `FileTransfer#upload`, SCM local proxy |
55
+ | `lib/minestrone/recipes/deploy/strategy/remote_cache.rb` | `Minestrone::Deploy::Strategy::RemoteCache` | Remote strategy maintaining a shared cached checkout under `shared_path`, then copying/rsyncing it to each release. Handles SCM prompt filtering and writes `REVISION`. | `strategy/base`, SCM `sync`/`checkout`/`handle_data`, remote `rsync` when exclusions exist |
56
+ | `lib/minestrone/recipes/standard.rb` | recipe tasks only | Standard recipe loaded by CLI. Defines `invoke` for one-off remote commands. | `configuration/actions/invocation` |
57
+ | `lib/minestrone/recipes/templates/maintenance.rhtml` | none | ERB/XHTML maintenance-page template used by `deploy:web:disable`. | Read by `recipes/deploy.rb` |
58
+ | `lib/minestrone/server_definition.rb` | `Minestrone::ServerDefinition` | Parses and stores `user@host:port` plus server options. Provides comparison, equality/hash, default user, and string rendering. | Used by `Servers`, `SSH`, `Connections` |
59
+ | `lib/minestrone/ssh.rb` | `Minestrone::SSH`, `SSH::Server` | SSH connection helper. Applies the originating `ServerDefinition` to the Net::SSH session and builds public-key-only connection options. | `net/ssh`, `ServerDefinition` |
60
+ | `lib/minestrone/task_definition.rb` | `Minestrone::TaskDefinition` | Stores task metadata: name, namespace, options, body, description, and rollback behavior. Formats descriptions and computes fully qualified names. | `server_definition`; used by `configuration/namespaces` and `execution` |
61
+ | `lib/minestrone/transfer.rb` | `Minestrone::Transfer`, `Transfer::SFTPTransferWrapper` | Single-session upload/download engine over SFTP or SCP. Normalizes host placeholders and IOs, tracks transfer failure, delegates event processing to `Processable`, and raises `TransferError`. | `net/scp`, `net/sftp`, `processable`, `errors`, SSH session |
62
+ | `lib/minestrone/version.rb` | `Minestrone::Version`, `Minestrone::VERSION` | Version constants and string rendering for Minestrone 2.15.11. | Used by CLI `--version` |
63
+
64
+ ## Dependency Graph
65
+
66
+ This graph shows the main internal runtime clusters rather than every standard-library require.
67
+
68
+ Saved image: [docs/lib-dependency-graph.svg](lib-dependency-graph.svg)
69
+
70
+ ```mermaid
71
+ flowchart TD
72
+ root["lib/minestrone.rb"] --> config["Minestrone::Configuration"]
73
+ root --> extensions["Minestrone.plugin / ExtensionProxy"]
74
+ root --> string_ext["String#compact"]
75
+
76
+ cli["Minestrone::CLI"] --> config
77
+ cli --> cli_options["CLI::Options"]
78
+ cli --> cli_help["CLI::Help"]
79
+
80
+ config --> variables["Configuration::Variables"]
81
+ config --> namespaces["Configuration::Namespaces"]
82
+ config --> execution["Configuration::Execution"]
83
+ config --> callbacks["Configuration::Callbacks"]
84
+ config --> servers_mod["Configuration::Servers"]
85
+ config --> loading["Configuration::Loading"]
86
+ config --> connections["Configuration::Connections"]
87
+ config --> invocation["Actions::Invocation"]
88
+ config --> transfer_actions["Actions::FileTransfer"]
89
+ config --> inspect_actions["Actions::Inspect"]
90
+ config --> log_formatters["Configuration::LogFormatters"]
91
+
92
+ namespaces --> task_definition["TaskDefinition"]
93
+ servers_mod --> server_definition["ServerDefinition"]
94
+ connections --> ssh["SSH"]
95
+ connections --> errors["Errors"]
96
+ invocation --> command["Command"]
97
+ transfer_actions --> transfer["Transfer"]
98
+ command --> processable["Processable"]
99
+ transfer --> processable
100
+ callbacks --> callback_classes["Callback / ProcCallback / TaskCallback"]
101
+ execution --> callbacks
102
+ execution --> namespaces
103
+
104
+ deploy_recipe["recipes/deploy.rb"] --> scm_factory["Deploy::SCM factory"]
105
+ deploy_recipe --> strategy_factory["Deploy::Strategy factory"]
106
+ deploy_recipe --> config
107
+ assets_recipe["recipes/deploy/assets.rb"] --> deploy_recipe
108
+
109
+ scm_factory --> scm_base["SCM::Base"]
110
+ scm_base --> scm_adapters["Git, None"]
111
+ strategy_factory --> strategy_base["Strategy::Base"]
112
+ strategy_base --> dependencies["Deploy::Dependencies"]
113
+ dependencies --> local_dep["LocalDependency"]
114
+ dependencies --> remote_dep["RemoteDependency"]
115
+ strategy_base --> strategies["Copy, RemoteCache"]
116
+ strategies --> scm_adapters
117
+ strategies --> config
118
+ ```
119
+
120
+ ## Static/Internal Require And Load Dependencies
121
+
122
+ These are the code-level edges visible from `require` and `load`, excluding Ruby standard-library and gem dependencies unless they are important to the file's role.
123
+
124
+ | File | Internal files loaded directly |
125
+ | --- | --- |
126
+ | `lib/minestrone.rb` | `minestrone/configuration`, `minestrone/extensions`, `minestrone/ext/string` |
127
+ | `lib/minestrone/cli.rb` | `minestrone`, `minestrone/cli/help`, `minestrone/cli/options`, `minestrone/configuration` |
128
+ | `lib/minestrone/cli/options.rb` | dynamically `minestrone/version` for `--version` |
129
+ | `lib/minestrone/command.rb` | `minestrone/errors`, `minestrone/processable` |
130
+ | `lib/minestrone/configuration.rb` | `minestrone/logger`; all `minestrone/configuration/*`; all `minestrone/configuration/actions/*` |
131
+ | `lib/minestrone/configuration/actions/file_transfer.rb` | `minestrone/transfer` |
132
+ | `lib/minestrone/configuration/actions/inspect.rb` | `minestrone/errors` |
133
+ | `lib/minestrone/configuration/actions/invocation.rb` | `minestrone/command` |
134
+ | `lib/minestrone/configuration/callbacks.rb` | `minestrone/callback` |
135
+ | `lib/minestrone/configuration/connections.rb` | `minestrone/ssh`, `minestrone/errors` |
136
+ | `lib/minestrone/configuration/execution.rb` | `minestrone/errors` |
137
+ | `lib/minestrone/configuration/namespaces.rb` | `minestrone/configuration/alias_task`, `minestrone/task_definition` |
138
+ | `lib/minestrone/configuration/servers.rb` | `minestrone/server_definition`, `minestrone/errors` |
139
+ | `lib/minestrone/recipes/deploy.rb` | `minestrone/recipes/deploy/scm`, `minestrone/recipes/deploy/strategy` |
140
+ | `lib/minestrone/recipes/deploy/assets.rb` | `load 'deploy'` unless `_cset` already exists |
141
+ | `lib/minestrone/recipes/deploy/dependencies.rb` | `minestrone/recipes/deploy/local_dependency`, `minestrone/recipes/deploy/remote_dependency` |
142
+ | `lib/minestrone/recipes/deploy/remote_dependency.rb` | `minestrone/errors` |
143
+ | `lib/minestrone/recipes/deploy/scm.rb` | dynamically `minestrone/recipes/deploy/scm/<name>` |
144
+ | `lib/minestrone/recipes/deploy/scm/git.rb` | `minestrone/recipes/deploy/scm/base` |
145
+ | `lib/minestrone/recipes/deploy/scm/none.rb` | `minestrone/recipes/deploy/scm/base` |
146
+ | `lib/minestrone/recipes/deploy/strategy.rb` | dynamically `minestrone/recipes/deploy/strategy/<name>` |
147
+ | `lib/minestrone/recipes/deploy/strategy/base.rb` | `minestrone/recipes/deploy/dependencies` |
148
+ | `lib/minestrone/recipes/deploy/strategy/remote_cache.rb` | `minestrone/recipes/deploy/strategy/base` |
149
+ | `lib/minestrone/recipes/deploy/strategy/copy.rb` | `minestrone/recipes/deploy/strategy/base` |
150
+ | `lib/minestrone/task_definition.rb` | `minestrone/server_definition` |
151
+ | `lib/minestrone/transfer.rb` | `minestrone/processable` |
152
+
153
+ ## Runtime Usage Notes
154
+
155
+ - `Configuration` is the central dependency hub. Most recipe and strategy code calls into it through DSL methods mixed in from its modules.
156
+ - `Command` and `Transfer` depend on `Processable` because they share the same single-session Net::SSH event-loop pattern.
157
+ - `ServerDefinition` is the single configured server identity object. It carries host/user/port/options into the `HOST` override path, SSH connection setup, command placeholders, transfer logging, and error reporting.
158
+ - `Callbacks` wraps `Execution#invoke_task_directly`; task lifecycle hooks therefore apply to all direct task execution paths, including CLI actions and recipe-invoked task aliases.
159
+ - `Deploy::SCM` and `Deploy::Strategy` are factories. They load adapter files by name and instantiate classes from generated constant names.
160
+ - SCM adapters generally do not execute commands. They return shell command strings and prompt handlers. Strategies decide whether those commands run locally, remotely, through caches, or through uploaded archives.
161
+ - `Strategy::Copy` is the main bridge from local SCM commands to remote deployment: it uses the SCM's local proxy, local filesystem staging, compression utilities, `upload`, and remote decompression.
162
+ - `recipes/deploy/assets.rb` is not a class extension. It is a recipe that mutates the current configuration by setting defaults, registering callbacks, adding helper methods, and defining `deploy:assets:*` tasks.
@@ -0,0 +1,129 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="1400" height="960" viewBox="0 0 1400 960" role="img" aria-labelledby="title desc">
3
+ <title id="title">Minestrone lib dependency graph</title>
4
+ <desc id="desc">Dependency graph generated from docs/lib-codebase-map.md Mermaid chart.</desc>
5
+ <defs>
6
+ <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
7
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#516071"/>
8
+ </marker>
9
+ <filter id="shadow" x="-10%" y="-10%" width="120%" height="130%">
10
+ <feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#0f172a" flood-opacity="0.12"/>
11
+ </filter>
12
+ </defs>
13
+ <rect width="100%" height="100%" fill="#f8fafc"/>
14
+ <text x="32" y="34" font-family="-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif" font-size="22" font-weight="700" fill="#0f172a">Minestrone lib dependency graph</text>
15
+ <text x="32" y="58" font-family="-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif" font-size="13" fill="#64748b">Generated from docs/lib-codebase-map.md</text>
16
+ <g fill="none" stroke="#516071" stroke-width="1.35" stroke-opacity="0.72" marker-end="url(#arrow)">
17
+ <path d="M 260 170 C 300 170, 300 170, 340 170"/>
18
+ <path d="M 260 170 C 300 170, 300 85, 340 85"/>
19
+ <path d="M 260 170 C 300 170, 300 255, 340 255"/>
20
+ <path d="M 260 340 C 300 340, 300 170, 340 170"/>
21
+ <path d="M 260 340 C 300 340, 300 340, 340 340"/>
22
+ <path d="M 260 340 C 300 340, 300 425, 340 425"/>
23
+ <path d="M 260 340 C 300 340, 300 510, 340 510"/>
24
+ <path d="M 600 170 C 640 170, 640 85, 680 85"/>
25
+ <path d="M 600 170 C 640 170, 640 145, 680 145"/>
26
+ <path d="M 600 170 C 640 170, 640 205, 680 205"/>
27
+ <path d="M 600 170 C 640 170, 640 265, 680 265"/>
28
+ <path d="M 600 170 C 640 170, 640 325, 680 325"/>
29
+ <path d="M 600 170 C 640 170, 640 385, 680 385"/>
30
+ <path d="M 600 170 C 640 170, 640 445, 680 445"/>
31
+ <path d="M 600 170 C 640 170, 640 505, 680 505"/>
32
+ <path d="M 600 170 C 640 170, 640 565, 680 565"/>
33
+ <path d="M 600 170 C 640 170, 640 625, 680 625"/>
34
+ <path d="M 940 145 C 980 145, 980 145, 1020 145"/>
35
+ <path d="M 940 325 C 980 325, 980 265, 1020 265"/>
36
+ <path d="M 940 385 C 980 385, 980 325, 1020 325"/>
37
+ <path d="M 940 385 C 980 385, 980 385, 1020 385"/>
38
+ <path d="M 940 445 C 980 445, 980 445, 1020 445"/>
39
+ <path d="M 940 505 C 980 505, 980 505, 1020 505"/>
40
+ <path d="M 1280 505 C 1300 505, 1300 565, 1020 565"/>
41
+ <path d="M 600 510 C 640 510, 640 565, 1020 565"/>
42
+ <path d="M 600 510 C 640 510, 640 445, 1020 445"/>
43
+ <path d="M 940 265 C 980 265, 980 625, 1020 625"/>
44
+ <path d="M 940 205 C 960 205, 960 265, 680 265"/>
45
+ <path d="M 260 595 C 300 595, 300 680, 340 680"/>
46
+ <path d="M 260 595 C 300 595, 300 765, 340 765"/>
47
+ <path d="M 260 595 C 300 595, 300 170, 340 170"/>
48
+ <path d="M 260 680 C 300 680, 300 595, 20 595"/>
49
+ <path d="M 260 765 C 300 765, 300 510, 340 510"/>
50
+ <path d="M 600 680 C 640 680, 640 680, 680 680"/>
51
+ <path d="M 940 680 C 980 680, 980 740, 1020 740"/>
52
+ <path d="M 600 765 C 640 765, 640 800, 680 800"/>
53
+ <path d="M 940 800 C 980 800, 980 800, 1020 800"/>
54
+ <path d="M 1280 800 C 1320 800, 1320 680, 1020 680"/>
55
+ <path d="M 1280 800 C 1320 800, 1320 170, 340 170"/>
56
+ </g>
57
+ <g font-family="-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif">
58
+ <rect x="20" y="141" width="240" height="58" rx="7" fill="#dcfce7" stroke="#16a34a" stroke-width="1.2" filter="url(#shadow)"/>
59
+ <text x="140" y="170" text-anchor="middle" dominant-baseline="middle" font-size="13" font-weight="650" fill="#0f172a">lib/minestrone.rb</text>
60
+ <rect x="340" y="141" width="260" height="58" rx="7" fill="#e0f2fe" stroke="#0284c7" stroke-width="1.2" filter="url(#shadow)"/>
61
+ <text x="470" y="170" text-anchor="middle" dominant-baseline="middle" font-size="13" font-weight="650" fill="#0f172a">Minestrone::Configuration</text>
62
+ <rect x="340" y="56" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
63
+ <text x="470" y="85" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Minestrone.plugin / ExtensionProxy</text>
64
+ <rect x="340" y="226" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
65
+ <text x="470" y="255" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">String#compact</text>
66
+ <rect x="20" y="311" width="240" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
67
+ <text x="140" y="340" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Minestrone::CLI</text>
68
+ <rect x="340" y="311" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
69
+ <text x="470" y="340" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">CLI::Execute</text>
70
+ <rect x="340" y="396" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
71
+ <text x="470" y="425" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">CLI::Options</text>
72
+ <rect x="340" y="481" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
73
+ <text x="470" y="510" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">CLI::Help / CLI::UI</text>
74
+ <rect x="680" y="56" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
75
+ <text x="810" y="85" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Configuration::Variables</text>
76
+ <rect x="680" y="116" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
77
+ <text x="810" y="145" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Configuration::Namespaces</text>
78
+ <rect x="680" y="176" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
79
+ <text x="810" y="205" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Configuration::Execution</text>
80
+ <rect x="680" y="236" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
81
+ <text x="810" y="265" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Configuration::Callbacks</text>
82
+ <rect x="680" y="296" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
83
+ <text x="810" y="325" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Configuration::Servers</text>
84
+ <rect x="680" y="356" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
85
+ <text x="810" y="385" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Configuration::Connections</text>
86
+ <rect x="680" y="416" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
87
+ <text x="810" y="445" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Actions::Invocation</text>
88
+ <rect x="680" y="476" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
89
+ <text x="810" y="505" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Actions::FileTransfer</text>
90
+ <rect x="680" y="536" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
91
+ <text x="810" y="565" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Actions::Inspect</text>
92
+ <rect x="680" y="596" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
93
+ <text x="810" y="625" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Configuration::Loading / LogFormatters</text>
94
+ <rect x="1020" y="116" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
95
+ <text x="1150" y="145" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">TaskDefinition</text>
96
+ <rect x="1020" y="236" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
97
+ <text x="1150" y="265" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Callback / ProcCallback / TaskCallback</text>
98
+ <rect x="1020" y="296" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
99
+ <text x="1150" y="325" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">ServerDefinition</text>
100
+ <rect x="1020" y="356" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
101
+ <text x="1150" y="385" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">SSH / Errors</text>
102
+ <rect x="1020" y="416" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
103
+ <text x="1150" y="445" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Command</text>
104
+ <rect x="1020" y="476" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
105
+ <text x="1150" y="505" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Transfer</text>
106
+ <rect x="1020" y="536" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
107
+ <text x="1150" y="565" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Processable</text>
108
+ <rect x="20" y="566" width="240" height="58" rx="7" fill="#e0f2fe" stroke="#0284c7" stroke-width="1.2" filter="url(#shadow)"/>
109
+ <text x="140" y="595" text-anchor="middle" dominant-baseline="middle" font-size="13" font-weight="650" fill="#0f172a">recipes/deploy.rb</text>
110
+ <rect x="340" y="651" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
111
+ <text x="470" y="680" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Deploy::SCM factory</text>
112
+ <rect x="340" y="736" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
113
+ <text x="470" y="765" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Deploy::Strategy factory</text>
114
+ <rect x="20" y="651" width="240" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
115
+ <text x="140" y="680" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">recipes/deploy/assets.rb</text>
116
+ <rect x="20" y="736" width="240" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
117
+ <text x="140" y="765" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">recipes/standard.rb</text>
118
+ <rect x="680" y="651" width="260" height="58" rx="7" fill="#e0f2fe" stroke="#0284c7" stroke-width="1.2" filter="url(#shadow)"/>
119
+ <text x="810" y="680" text-anchor="middle" dominant-baseline="middle" font-size="13" font-weight="650" fill="#0f172a">SCM::Base</text>
120
+ <rect x="1020" y="711" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
121
+ <text x="1150" y="740" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Git, None</text>
122
+ <rect x="680" y="771" width="260" height="58" rx="7" fill="#e0f2fe" stroke="#0284c7" stroke-width="1.2" filter="url(#shadow)"/>
123
+ <text x="810" y="800" text-anchor="middle" dominant-baseline="middle" font-size="13" font-weight="650" fill="#0f172a">Strategy::Base</text>
124
+ <rect x="1020" y="651" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
125
+ <text x="1150" y="680" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Deploy::Dependencies</text>
126
+ <rect x="1020" y="771" width="260" height="58" rx="7" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.2" filter="url(#shadow)"/>
127
+ <text x="1150" y="800" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">Copy, RemoteCache</text>
128
+ </g>
129
+ </svg>
@@ -0,0 +1,45 @@
1
+ module Minestrone
2
+ class Callback
3
+ attr_reader :source, :options, :only, :except
4
+
5
+ def initialize(source, options = {})
6
+ @source = source
7
+ @options = options
8
+ @only = Array(options[:only]).map { |v| v.to_s }
9
+ @except = Array(options[:except]).map { |v| v.to_s }
10
+ end
11
+
12
+ def applies_to?(task)
13
+ if task && only.any?
14
+ return only.include?(task.fully_qualified_name)
15
+ elsif task && except.any?
16
+ return !except.include?(task.fully_qualified_name)
17
+ else
18
+ return true
19
+ end
20
+ end
21
+ end
22
+
23
+ class ProcCallback < Callback
24
+ def call
25
+ source.call
26
+ end
27
+ end
28
+
29
+ class TaskCallback < Callback
30
+ attr_reader :config
31
+
32
+ def initialize(config, source, options = {})
33
+ super(source, options)
34
+ @config = config
35
+ end
36
+
37
+ def call
38
+ config.find_and_execute_task(source)
39
+ end
40
+
41
+ def applies_to?(task)
42
+ super && (task.nil? || task.fully_qualified_name != source.to_s)
43
+ end
44
+ end
45
+ end