minestrone 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b1c0aa45e3a7ce26a5241ab6656d206d0b2db2c38687384f0cbba242bd67537
4
- data.tar.gz: 5cef64bc80b01887fe19456cd67c8734cb9123af190bca72a3f3c9f45b63aa27
3
+ metadata.gz: e3c8964c359e7dabb2d3d14bd09a093d4d4bbabbb8ce75bf47e2949eb2e711ea
4
+ data.tar.gz: 8772884a6badaf622abc7b794c5dc971bbab040fc403537402cfade082014a66
5
5
  SHA512:
6
- metadata.gz: 4e1a874230014eb04210586cbfbecb5ec23bea4fcb2038db1b8a442966210d12c714e9024907d9f4364686d7c076fe64589adb6a253c1789524dc7ec52be499d
7
- data.tar.gz: 17bf22d3069227d7e8f84bb268d21deddae4d3970563810bfe58fa7605425b118bd931a7198eca519a18db941276a5faaf277b935fc4628a2d0e2880b264cb52
6
+ metadata.gz: 7c5aff5e3ac5ab932ac0d9f1adaf88b8fbdc646ee5056e219858a3c85574f90a60882aa35c9c38df1c293101eec28d91afbb844b2e9bb9cea13417ee12cebfd0
7
+ data.tar.gz: 587306f72ed2e29c81c29593e5a7cf7c765a184544b37fa94bbd5b45d0c1334bed073ed1928a38c539e737b220246c4506fa7ec8c06cfc044042ec8ca4a4a7af
data/CHANGELOG.md CHANGED
@@ -1,8 +1,15 @@
1
+ ## [0.0.3] - 2026-10-24
2
+
3
+ - updated `capify` script to generate an updated and simplified deploy config
4
+ - bumped up `net-ssh`, `net-scp` and `net-sftp` required versions
5
+ - bumped up required Ruby version to 3.3+
6
+ - `ed25519` and `bcrypt_pbkdf` don't need to be separately included in the Gemfile
7
+
1
8
  ## [0.0.2] - 2026-07-26
2
9
 
3
10
  - added `upload_file` as an alias for `upload` (which in deploy tasks is shadowed by the `deploy:upload` task)
4
11
  - added `append` & `remove` for adding/removing to array variables (from Capistrano 3)
5
- - renamed `_cset` to `set_if_empty` and make it a public API (also from Capistrano 3)
12
+ - renamed `_cset` to `set_if_empty` and made it a public API (also from Capistrano 3)
6
13
  - in migration and assets tasks, use `RACK_ENV` instead of `RAILS_ENV`, unless `rails_env` is explicitly defined (Rails also accepts `RACK_ENV`, but Sinatra/Rack doesn't accept `RAILS_ENV`)
7
14
  - `:use_sudo` is now disabled by default
8
15
  - renamed `version_dir` to `releases_dir` for consistency
@@ -10,8 +17,7 @@
10
17
  - removed `deploy:cold`, `deploy:start` and `deploy:stop` tasks
11
18
  - removed `:normalize_asset_timestamps` and `:public_children`
12
19
 
13
-
14
- ## Minestrone 0.0.1 - 2026-05-25
20
+ ## Minestrone [0.0.1] - 2026-05-25
15
21
 
16
22
  Changes from Capistrano 2.15.11:
17
23
 
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'http://rubygems.org'
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in minestrone.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -36,7 +36,8 @@ Minestrone is a tool for deploying Ruby applications to a server, based on the c
36
36
  * added `upload_file` as alias for `upload`
37
37
  * added `append` and `remove` for adding/removing items from array variables
38
38
  * renamed `_cset` to `set_if_empty`
39
- * Ruby 3.0+ is required
39
+ * Ruby 3.3+ is required
40
+ * `ed25519` and `bcrypt_pbkdf` don't need to be separately included in the Gemfile
40
41
 
41
42
 
42
43
  ### Project status
data/SECURITY.md ADDED
@@ -0,0 +1,16 @@
1
+ # Security Policy
2
+
3
+ ## How To Report a Vulnerability
4
+
5
+ If you find a potential vulnerability in one of my projects, it's recommended not to report it through a standard publicly-readable issue report, in order to avoid giving possible clues to any potential attackers who could abuse it before it's fixed (see: ["Just a rumour of a bug is enough to find a security exploit these days"](https://anil.recoil.org/notes/rumour-is-the-exploit)).
6
+
7
+ You can use one of these to contact me instead:
8
+
9
+ - [@mackuba.eu](https://bsky.app/profile/did:plc:oio4hkxaop4ao4wz2pp3f4cr) on Bluesky (my DMs should be open, or mention me discretely with a request for contact)
10
+ - [@mackuba@martianbase.net](https://martianbase.net/@mackuba) on Mastodon (my personal instance)
11
+ - email: mackuba `@` protonmail.ch (optionally with [this PGP key](https://mail-api.proton.me/pks/lookup?op=get&search=mackuba@protonmail.ch))
12
+ - ["Report a vulnerability"](https://github.com/mackuba/minestrone/security/advisories/new) form on GitHub
13
+
14
+ I do not check my Twitter/X or LinkedIn accounts regularly.
15
+
16
+ Note: please don't submit AI-reported issues that have not been verified manually :)
data/bin/capify CHANGED
@@ -32,49 +32,46 @@ end
32
32
 
33
33
  def unindent(string)
34
34
  indentation = string[/\A\s*/]
35
- string.strip.gsub(/^#{indentation}/, "")
35
+ string.strip.gsub(/^#{indentation}/, "") + "\n"
36
36
  end
37
37
 
38
38
  files = {
39
39
  "Capfile" => unindent(<<-FILE),
40
-
41
40
  load 'deploy'
41
+ load 'deploy/bundler'
42
42
 
43
- # Uncomment if you are using Rails' asset pipeline
43
+ # Uncomment if you are using Rails asset pipeline
44
44
  # load 'deploy/assets'
45
45
 
46
- load 'config/deploy' # remove this line to skip loading any of the default tasks
46
+ load 'config/deploy'
47
47
  FILE
48
48
 
49
- "config/deploy.rb" => 'set :application, "set your application name here"
50
- set :repository, "set your repository location here"
51
-
52
- # set :scm, :git # You can set :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
53
- # Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
49
+ "config/deploy.rb" => unindent(<<-FILE),
50
+ server "host.example.com"
54
51
 
55
- role :web, "your web-server here" # Your HTTP server, Apache/etc
56
- role :app, "your app-server here" # This may be the same as your `Web` server
57
- role :db, "your primary db-server here", :primary => true # This is where Rails migrations will run
58
- role :db, "your slave db-server here"
52
+ set :application, "set your application name here"
53
+ set :repository, "set your git repository URL here"
59
54
 
60
- # if you want to clean up old releases on each deploy uncomment this:
61
- # after "deploy:restart", "deploy:cleanup"
55
+ # customize if needed
56
+ # set :keep_releases, 5
57
+ # set :rake, "RACK_ENV=production bundle exec rake"
58
+ # append :shared_children, "data"
62
59
 
63
- # if you\'re still using the script/reaper helper you will need
64
- # these http://github.com/rails/irs_process_scripts
65
-
66
- # If you are using Passenger mod_rails uncomment this:
67
- # namespace :deploy do
68
- # task :start do ; end
69
- # task :stop do ; end
70
- # task :restart, :roles => :app, :except => { :no_release => true } do
71
- # run "#{try_sudo} touch #{File.join(current_path,\'tmp\',\'restart.txt\')}"
72
- # end
73
- # end'}
60
+ namespace :deploy do
61
+ task :restart do
62
+ # implement depending on the Ruby app server you use
63
+ # e.g. for Passenger:
64
+ # run "touch \#{current_path}/tmp/restart.txt"
65
+ end
66
+ end
67
+ FILE
68
+ }
74
69
 
75
70
  base = ARGV.shift
71
+
76
72
  files.each do |file, content|
77
73
  file = File.join(base, file)
74
+
78
75
  if File.exist?(file)
79
76
  warn "[skip] '#{file}' already exists"
80
77
  elsif File.exist?(file.downcase)
@@ -84,6 +81,7 @@ files.each do |file, content|
84
81
  puts "[add] making directory '#{File.dirname(file)}'"
85
82
  FileUtils.mkdir(File.dirname(file))
86
83
  end
84
+
87
85
  puts "[add] writing '#{file}'"
88
86
  File.open(file, "w") { |f| f.write(content) }
89
87
  end
@@ -23,7 +23,7 @@ Built-in recipes live under `lib/minestrone/recipes`. The deploy recipe composes
23
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
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
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` |
26
+ | `lib/minestrone/configuration/actions/file_transfer.rb` | `Minestrone::Configuration::Actions::FileTransfer` | Adds `put`, `get`, `upload`/`upload_file`, `download`, and `transfer` DSL actions. `upload_file` avoids ambiguity with the `deploy:upload` task. Delegates actual work to `Minestrone::Transfer`. | `transfer`, `Connections#execute_on_server`, `Connections#session`, `run` |
27
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
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
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` |
@@ -33,15 +33,16 @@ Built-in recipes live under `lib/minestrone/recipes`. The deploy recipe composes
33
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
34
  | `lib/minestrone/configuration/log_formatters.rb` | `Minestrone::Configuration::LogFormatters` | DSL for adding logger formatters and disabling formatting. | `logger` |
35
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 |
36
+ | `lib/minestrone/configuration/servers.rb` | `Minestrone::Configuration::Servers` | Adds the single-host `server` DSL and resolves the configured server, with `SERVER` as the preferred environment override and `HOSTS` as a compatibility fallback. | `ServerDefinition`, `errors` |
37
+ | `lib/minestrone/configuration/variables.rb` | `Minestrone::Configuration::Variables` | Configuration variables with lazy proc evaluation, conditional defaults through `set_if_empty`, array updates through `append`/`remove`, reset/unset, `fetch`, `[]`, and variable-backed `method_missing`. | Used by nearly every DSL and recipe file |
38
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
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
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
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
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 |
43
+ | `lib/minestrone/recipes/deploy.rb` | recipe methods and tasks only | Primary deployment recipe. Defines deploy defaults, helpers (`scm_default`, `depend`, `with_env`, `r_env`, `run_locally`, `try_sudo`, `try_runner`), and tasks for setup, update, update_code, symlinks, upload, restart hooks, rollback, migrations, cleanup, checks, and pending diff/log. Defaults to Git when `.git` exists and `none` otherwise. | `deploy/scm`, `deploy/strategy`, `dependencies`, `Command`/`Transfer` through configuration actions |
44
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/bundler.rb` | recipe methods and tasks only | Bundler integration. Configures bundle defaults, makes Rake run through Bundler, installs gems into the shared bundle path during deployment, and symlinks that path into each release. | Loads `deploy`; deploy variables, callbacks/tasks/actions |
45
46
  | `lib/minestrone/recipes/deploy/dependencies.rb` | `Minestrone::Deploy::Dependencies` | Aggregates local and remote dependency checks and reports pass/fail. | `local_dependency`, `remote_dependency` |
46
47
  | `lib/minestrone/recipes/deploy/local_dependency.rb` | `Minestrone::Deploy::LocalDependency` | Checks local command availability in `PATH`. | Used by `Dependencies`, `Strategy::Copy#check!` |
47
48
  | `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` |
@@ -54,12 +55,11 @@ Built-in recipes live under `lib/minestrone/recipes`. The deploy recipe composes
54
55
  | `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
56
  | `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
57
  | `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
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
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
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
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` |
62
+ | `lib/minestrone/version.rb` | `Minestrone::Version`, `Minestrone::VERSION` | Version constants and string rendering for Minestrone 0.0.2. | Used by CLI `--version` |
63
63
 
64
64
  ## Dependency Graph
65
65
 
@@ -105,6 +105,7 @@ flowchart TD
105
105
  deploy_recipe --> strategy_factory["Deploy::Strategy factory"]
106
106
  deploy_recipe --> config
107
107
  assets_recipe["recipes/deploy/assets.rb"] --> deploy_recipe
108
+ bundler_recipe["recipes/deploy/bundler.rb"] --> deploy_recipe
108
109
 
109
110
  scm_factory --> scm_base["SCM::Base"]
110
111
  scm_base --> scm_adapters["Git, None"]
@@ -137,7 +138,8 @@ These are the code-level edges visible from `require` and `load`, excluding Ruby
137
138
  | `lib/minestrone/configuration/namespaces.rb` | `minestrone/configuration/alias_task`, `minestrone/task_definition` |
138
139
  | `lib/minestrone/configuration/servers.rb` | `minestrone/server_definition`, `minestrone/errors` |
139
140
  | `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/assets.rb` | `load 'deploy'` unless the `try_sudo` deploy helper already exists |
142
+ | `lib/minestrone/recipes/deploy/bundler.rb` | `load 'deploy'` unless the `try_sudo` deploy helper already exists |
141
143
  | `lib/minestrone/recipes/deploy/dependencies.rb` | `minestrone/recipes/deploy/local_dependency`, `minestrone/recipes/deploy/remote_dependency` |
142
144
  | `lib/minestrone/recipes/deploy/remote_dependency.rb` | `minestrone/errors` |
143
145
  | `lib/minestrone/recipes/deploy/scm.rb` | dynamically `minestrone/recipes/deploy/scm/<name>` |
@@ -154,9 +156,9 @@ These are the code-level edges visible from `require` and `load`, excluding Ruby
154
156
 
155
157
  - `Configuration` is the central dependency hub. Most recipe and strategy code calls into it through DSL methods mixed in from its modules.
156
158
  - `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.
159
+ - `ServerDefinition` is the single configured server identity object. It carries host/user/port/options into the `SERVER`/`HOSTS` override path, SSH connection setup, command placeholders, transfer logging, and error reporting.
158
160
  - `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
161
  - `Deploy::SCM` and `Deploy::Strategy` are factories. They load adapter files by name and instantiate classes from generated constant names.
160
162
  - 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
163
  - `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.
164
+ - `recipes/deploy/assets.rb` and `recipes/deploy/bundler.rb` are not class extensions. They are recipes that mutate the current configuration by setting defaults, registering callbacks, adding helper methods, and defining deployment tasks.
@@ -36,6 +36,9 @@ module Minestrone
36
36
 
37
37
  alias :[]= :set
38
38
 
39
+ # Sets a variable only when it has not already been defined. Existing
40
+ # values, including nil and false, are preserved. Accepts either a value
41
+ # or a block, following the same rules as #set.
39
42
  def set_if_empty(variable, *args, &block)
40
43
  set(variable, *args, &block) unless exists?(variable)
41
44
  end
@@ -47,10 +50,16 @@ module Minestrone
47
50
  @variables.delete(sym)
48
51
  end
49
52
 
53
+ # Appends one or more values to an array variable. Missing variables are
54
+ # treated as empty arrays, and existing scalar values are wrapped in an
55
+ # array before the new values are appended.
50
56
  def append(variable, *values)
51
57
  set(variable, Array(fetch(variable, [])).concat(values))
52
58
  end
53
59
 
60
+ # Removes all occurrences of the given values from an array variable.
61
+ # Missing variables are treated as empty arrays, and existing scalar
62
+ # values are wrapped in an array before removal.
54
63
  def remove(variable, *values)
55
64
  set(variable, Array(fetch(variable, [])) - values)
56
65
  end
@@ -3,7 +3,7 @@
3
3
  module Minestrone
4
4
  class Version
5
5
  def self.to_s
6
- "0.0.2"
6
+ "0.0.3"
7
7
  end
8
8
  end
9
9
 
data/minestrone.gemspec CHANGED
@@ -1,32 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- $LOAD_PATH.push File.expand_path("lib", __dir__)
4
- require "minestrone/version"
3
+ require_relative 'lib/minestrone/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = "minestrone"
8
7
  spec.version = Minestrone::Version.to_s
9
8
  spec.platform = Gem::Platform::RUBY
10
9
  spec.authors = ["Jamis Buck", "Lee Hambley", "Kuba Suder"]
11
- spec.homepage = "http://github.com/mackuba/minestrone"
12
- spec.summary = "Minestrone - Welcome to easy deployment with Ruby over SSH"
13
- spec.description = "Minestrone is a utility and framework for executing commands on a remote machine, via SSH."
10
+
11
+ spec.summary = "Simple deployment tool for Ruby apps (based on Capistrano)"
12
+ spec.description = %(
13
+ Minestrone is a simplified fork of old Capistrano from before the 3.0 rewrite. It retains most of the old, simpler API,
14
+ while also removing some more advanced features, and focusing on the relatively simplest but common scenario of a single
15
+ production server. It also removes a lot of old cruft, support for less commonly used or less recommended things,
16
+ and modernizes some of the code.
17
+ )
18
+
19
+ spec.homepage = "https://github.com/mackuba/minestrone"
20
+ spec.license = "MIT"
21
+
22
+ spec.metadata = {
23
+ "bug_tracker_uri" => "https://github.com/mackuba/minestrone/issues",
24
+ "changelog_uri" => "https://github.com/mackuba/minestrone/blob/master/CHANGELOG.md",
25
+ "source_code_uri" => "https://github.com/mackuba/minestrone",
26
+ "rubygems_mfa_required" => "true"
27
+ }
28
+
14
29
  spec.files = `git ls-files`.split("\n")
15
- spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
- spec.executables = `git ls-files -- bin/*`.split("\n").map { |file| File.basename(file) }
30
+ spec.executables = ['min', 'capify']
17
31
  spec.require_paths = ["lib"]
18
32
  spec.extra_rdoc_files = [
19
33
  "README.md"
20
34
  ]
21
35
 
22
- spec.required_ruby_version = ">= 3.0.0"
36
+ spec.required_ruby_version = ">= 3.3.0"
23
37
 
24
38
  spec.add_dependency 'benchmark', '~> 0.5'
25
- spec.add_dependency 'highline', '>= 0'
26
- spec.add_dependency 'net-ssh', '>= 7.2'
27
- spec.add_dependency 'net-sftp', '>= 3.0'
28
- spec.add_dependency 'net-scp', '>= 3.0'
29
-
30
- # used silently by net-ssh but undeclared
31
- spec.add_dependency 'logger'
39
+ spec.add_dependency 'highline', '~> 3.0'
40
+ spec.add_dependency 'net-ssh', '~> 8.0'
41
+ spec.add_dependency 'net-sftp', '~> 4.0'
42
+ spec.add_dependency 'net-scp', '~> 4.0'
43
+ spec.add_dependency 'bcrypt_pbkdf', '~> 1.1'
32
44
  end
@@ -47,6 +47,12 @@ class ConfigurationActionsFileTransferTest < Test::Unit::TestCase
47
47
  @config.upload("testl.txt", "testr.txt", :mode => "g+w", :foo => "bar")
48
48
  end
49
49
 
50
+ def test_upload_file_should_alias_upload
51
+ @config.expects(:transfer).with(:up, "testl.txt", "testr.txt", { :foo => "bar" })
52
+ @config.expects(:run).with("chmod 775 testr.txt", { :foo => "bar" })
53
+ @config.upload_file("testl.txt", "testr.txt", :mode => 0775, :foo => "bar")
54
+ end
55
+
50
56
  def test_download_should_delegate_to_transfer
51
57
  @config.expects(:transfer).with(:down, "testr.txt", "testl.txt", { :foo => "bar" })
52
58
  @config.download("testr.txt", "testl.txt", :foo => "bar")
@@ -96,6 +96,60 @@ class ConfigurationVariablesTest < Test::Unit::TestCase
96
96
  end
97
97
  end
98
98
 
99
+ def test_set_if_empty_should_set_missing_variable
100
+ @config.set_if_empty :sample, :value
101
+ assert_equal :value, @config.fetch(:sample)
102
+ end
103
+
104
+ def test_set_if_empty_should_accept_lazy_block
105
+ @config.set_if_empty(:sample) { :value }
106
+ assert_instance_of Proc, @config.variables[:sample]
107
+ assert_equal :value, @config.fetch(:sample)
108
+ end
109
+
110
+ def test_set_if_empty_should_not_replace_existing_false_or_nil
111
+ @config.set :false_value, false
112
+ @config.set :nil_value, nil
113
+
114
+ @config.set_if_empty :false_value, :replacement
115
+ replacement_called = false
116
+ @config.set_if_empty(:nil_value) { replacement_called = true }
117
+
118
+ assert_equal false, @config.fetch(:false_value)
119
+ assert_nil @config.fetch(:nil_value)
120
+ assert_equal false, replacement_called
121
+ end
122
+
123
+ def test_append_should_add_values_to_missing_or_existing_array
124
+ @config.append :missing, :one, :two
125
+ @config.set :existing, [:one]
126
+ @config.append :existing, :two, :three
127
+
128
+ assert_equal [:one, :two], @config.fetch(:missing)
129
+ assert_equal [:one, :two, :three], @config.fetch(:existing)
130
+ end
131
+
132
+ def test_append_should_wrap_existing_scalar_var_in_array
133
+ @config.set :sample, :one
134
+ @config.append :sample, :two
135
+ assert_equal [:one, :two], @config.fetch(:sample)
136
+ end
137
+
138
+ def test_remove_should_remove_values_from_missing_or_existing_array
139
+ @config.remove :missing, :one
140
+ @config.set :existing, [:one, :two, :one, :three]
141
+ @config.remove :existing, :one, :three
142
+
143
+ assert_equal [], @config.fetch(:missing)
144
+ assert_equal [:two], @config.fetch(:existing)
145
+ end
146
+
147
+ def test_remove_should_wrap_existing_scalar
148
+ @config.set :sample, :one
149
+ @config.remove :sample, :two
150
+ assert_equal [:one], @config.fetch(:sample)
151
+ end
152
+
99
153
  def test_unset_should_remove_variable_from_hash
100
154
  @config.set :sample, :value
101
155
  assert @config.variables.key?(:sample)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minestrone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamis Buck
@@ -29,74 +29,78 @@ dependencies:
29
29
  name: highline
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ">="
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '0'
34
+ version: '3.0'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '0'
41
+ version: '3.0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: net-ssh
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ">="
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '7.2'
48
+ version: '8.0'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ">="
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '7.2'
55
+ version: '8.0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: net-sftp
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - ">="
60
+ - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: '3.0'
62
+ version: '4.0'
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - ">="
67
+ - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: '3.0'
69
+ version: '4.0'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: net-scp
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ">="
74
+ - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: '3.0'
76
+ version: '4.0'
77
77
  type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ">="
81
+ - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: '3.0'
83
+ version: '4.0'
84
84
  - !ruby/object:Gem::Dependency
85
- name: logger
85
+ name: bcrypt_pbkdf
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - ">="
88
+ - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: '0'
90
+ version: '1.1'
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - ">="
95
+ - - "~>"
96
96
  - !ruby/object:Gem::Version
97
- version: '0'
98
- description: Minestrone is a utility and framework for executing commands on a remote
99
- machine, via SSH.
97
+ version: '1.1'
98
+ description: "\n Minestrone is a simplified fork of old Capistrano from before
99
+ the 3.0 rewrite. It retains most of the old, simpler API,\n while also removing
100
+ some more advanced features, and focusing on the relatively simplest but common
101
+ scenario of a single\n production server. It also removes a lot of old cruft,
102
+ support for less commonly used or less recommended things,\n and modernizes some
103
+ of the code.\n "
100
104
  executables:
101
105
  - capify
102
106
  - min
@@ -111,6 +115,7 @@ files:
111
115
  - LICENSE.txt
112
116
  - README.md
113
117
  - Rakefile
118
+ - SECURITY.md
114
119
  - bin/capify
115
120
  - bin/min
116
121
  - docs/lib-codebase-map.md
@@ -198,9 +203,14 @@ files:
198
203
  - test/transfer_test.rb
199
204
  - test/utils.rb
200
205
  - test/version_test.rb
201
- homepage: http://github.com/mackuba/minestrone
202
- licenses: []
203
- metadata: {}
206
+ homepage: https://github.com/mackuba/minestrone
207
+ licenses:
208
+ - MIT
209
+ metadata:
210
+ bug_tracker_uri: https://github.com/mackuba/minestrone/issues
211
+ changelog_uri: https://github.com/mackuba/minestrone/blob/master/CHANGELOG.md
212
+ source_code_uri: https://github.com/mackuba/minestrone
213
+ rubygems_mfa_required: 'true'
204
214
  rdoc_options: []
205
215
  require_paths:
206
216
  - lib
@@ -208,51 +218,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
218
  requirements:
209
219
  - - ">="
210
220
  - !ruby/object:Gem::Version
211
- version: 3.0.0
221
+ version: 3.3.0
212
222
  required_rubygems_version: !ruby/object:Gem::Requirement
213
223
  requirements:
214
224
  - - ">="
215
225
  - !ruby/object:Gem::Version
216
226
  version: '0'
217
227
  requirements: []
218
- rubygems_version: 4.0.15
228
+ rubygems_version: 4.0.23
219
229
  specification_version: 4
220
- summary: Minestrone - Welcome to easy deployment with Ruby over SSH
221
- test_files:
222
- - test/cli/execute_test.rb
223
- - test/cli/help_test.rb
224
- - test/cli/options_test.rb
225
- - test/cli/ui_test.rb
226
- - test/cli_test.rb
227
- - test/command_test.rb
228
- - test/configuration/actions/file_transfer_test.rb
229
- - test/configuration/actions/inspect_test.rb
230
- - test/configuration/actions/invocation_test.rb
231
- - test/configuration/alias_task_test.rb
232
- - test/configuration/callbacks_test.rb
233
- - test/configuration/connections_test.rb
234
- - test/configuration/execution_test.rb
235
- - test/configuration/loading_test.rb
236
- - test/configuration/namespace_dsl_test.rb
237
- - test/configuration/servers_test.rb
238
- - test/configuration/variables_test.rb
239
- - test/configuration_test.rb
240
- - test/deploy/local_dependency_test.rb
241
- - test/deploy/remote_dependency_test.rb
242
- - test/deploy/scm/base_test.rb
243
- - test/deploy/scm/git_test.rb
244
- - test/deploy/scm/none_test.rb
245
- - test/deploy/strategy/copy_test.rb
246
- - test/extensions_test.rb
247
- - test/fixtures/cli_integration.rb
248
- - test/fixtures/config.rb
249
- - test/fixtures/custom.rb
250
- - test/logger_formatting_test.rb
251
- - test/logger_test.rb
252
- - test/recipes_test.rb
253
- - test/server_definition_test.rb
254
- - test/ssh_test.rb
255
- - test/task_definition_test.rb
256
- - test/transfer_test.rb
257
- - test/utils.rb
258
- - test/version_test.rb
230
+ summary: Simple deployment tool for Ruby apps (based on Capistrano)
231
+ test_files: []