From 206c94ae66a066f8fbdf6a9ee6b80eb46de8908f Mon Sep 17 00:00:00 2001 From: Alex Kubacki Date: Mon, 10 Nov 2025 12:05:41 -0700 Subject: [PATCH 1/7] Support deployment without overloaded environment variables. --- lib/aptible/cli/subcommands/deploy.rb | 65 ++++++++++++++------- spec/aptible/cli/subcommands/deploy_spec.rb | 21 +++---- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/lib/aptible/cli/subcommands/deploy.rb b/lib/aptible/cli/subcommands/deploy.rb index 96f24730..1c13b521 100644 --- a/lib/aptible/cli/subcommands/deploy.rb +++ b/lib/aptible/cli/subcommands/deploy.rb @@ -2,15 +2,11 @@ module Aptible module CLI module Subcommands module Deploy - DOCKER_IMAGE_DEPLOY_ARGS = Hash[%w( + DEPRECATED_ENV = %w( APTIBLE_DOCKER_IMAGE - APTIBLE_PRIVATE_REGISTRY_EMAIL APTIBLE_PRIVATE_REGISTRY_USERNAME APTIBLE_PRIVATE_REGISTRY_PASSWORD - ).map do |var| - opt = var.gsub(/^APTIBLE_/, '').downcase.to_sym - [opt, var] - end] + ).freeze NULL_SHA1 = '0000000000000000000000000000000000000000'.freeze @@ -40,11 +36,23 @@ def self.included(thor) desc: 'This option only affects new ' \ 'services, not existing ones. ' \ 'Examples: m c r' - DOCKER_IMAGE_DEPLOY_ARGS.each_pair do |opt, var| - option opt, - type: :string, banner: var, - desc: "Shorthand for #{var}=..." - end + + option :docker_image, + type: :string, + desc: 'The docker image to deploy. If none specified, ' \ + 'the currently deployed image will be pulled again' + option :private_registry_username, + type: :string, + desc: 'Username for Docker images located in a private ' \ + 'repository' + option :private_registry_password, + type: :string, + desc: 'Password for Docker images located in a private ' \ + 'repository' + option :private_registry_email, + type: :string, + desc: 'This parameter is deprectated' + app_options def deploy(*args) telemetry(__method__, options) @@ -62,20 +70,37 @@ def deploy(*args) env = extract_env(args) - DOCKER_IMAGE_DEPLOY_ARGS.each_pair do |opt, var| - val = options[opt] - next unless val - if env[var] && env[var] != val - dasherized = "--#{opt.to_s.tr('_', '-')}" - raise Thor::Error, "The options #{dasherized} and #{var} " \ - 'cannot be set to different values' - end - env[var] = val + if (DEPRECATED_ENV & env.keys).any? + option_names = DEPRECATED_ENV.map do |var| + var.gsub('APTIBLE_', '--').to_s.downcase.tr('_', '-') + end.join(', ') + m = 'ERROR: The environment variables ' \ + "#{DEPRECATED_ENV.join(', ')} are deprecated. " \ + "Use the options #{option_names}, instead" + raise Thor::Error, m + end + + settings = {} + sensitive_settings = {} + + if options[:docker_image] + settings['APTIBLE_DOCKER_IMAGE'] = options[:docker_image] + end + + if options[:private_registry_username] + sensitive_settings['APTIBLE_PRIVATE_REGISTRY_USERNAME'] = + options[:private_registry_username] + end + if options[:private_registry_password] + sensitive_settings['APTIBLE_PRIVATE_REGISTRY_PASSWORD'] = + options[:private_registry_password] end opts = { type: 'deploy', env: env, + settings: settings, + sensitive_settings: sensitive_settings, git_ref: git_ref, container_count: options[:container_count], container_size: options[:container_size], diff --git a/spec/aptible/cli/subcommands/deploy_spec.rb b/spec/aptible/cli/subcommands/deploy_spec.rb index 3d77285a..6abaf6fa 100644 --- a/spec/aptible/cli/subcommands/deploy_spec.rb +++ b/spec/aptible/cli/subcommands/deploy_spec.rb @@ -45,7 +45,10 @@ def stub_options(**opts) stub_options(docker_image: 'foobar') expect(app).to receive(:create_operation!) - .with(type: 'deploy', env: { 'APTIBLE_DOCKER_IMAGE' => 'foobar' }) + .with( + type: 'deploy', + settings: { 'APTIBLE_DOCKER_IMAGE' => 'foobar' } + ) .and_return(operation) expect(subject).to receive(:attach_to_operation_logs) .with(operation) @@ -60,14 +63,13 @@ def stub_options(**opts) private_registry_password: 'qux' ) - env = { - 'APTIBLE_PRIVATE_REGISTRY_EMAIL' => 'foo', + sensitive_settings = { 'APTIBLE_PRIVATE_REGISTRY_USERNAME' => 'bar', 'APTIBLE_PRIVATE_REGISTRY_PASSWORD' => 'qux' } expect(app).to receive(:create_operation!) - .with(type: 'deploy', env: env) + .with(type: 'deploy', sensitive_settings: sensitive_settings) .and_return(operation) expect(subject).to receive(:attach_to_operation_logs) .with(operation) @@ -136,20 +138,15 @@ def stub_options(**opts) it 'allows redundant command line arguments' do stub_options(docker_image: 'foobar') - expect(app).to receive(:create_operation!) - .with(type: 'deploy', env: { 'APTIBLE_DOCKER_IMAGE' => 'foobar' }) - .and_return(operation) - expect(subject).to receive(:attach_to_operation_logs) - .with(operation) - - subject.deploy('APTIBLE_DOCKER_IMAGE=foobar') + expect { subject.deploy('APTIBLE_DOCKER_IMAGE=foobar') } + .to raise_error(/deprecated/im) end it 'reject contradictory command line argumnts' do stub_options(docker_image: 'foobar') expect { subject.deploy('APTIBLE_DOCKER_IMAGE=qux') } - .to raise_error(/different values/im) + .to raise_error(/deprecated/im) end it 'does not allow deploying nothing on an unprovisioned app' do From 1eeb806c77a3f9601d9c5d9f4f96db9b6d3900cf Mon Sep 17 00:00:00 2001 From: Alex Kubacki Date: Thu, 13 Nov 2025 16:48:41 -0700 Subject: [PATCH 2/7] Bump version --- Gemfile.lock | 2 +- lib/aptible/cli/subcommands/deploy.rb | 2 +- lib/aptible/cli/version.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9a176935..3c715703 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - aptible-cli (0.25.1) + aptible-cli (0.25.2) activesupport (>= 4.0, < 6.0) aptible-api (~> 1.10.0) aptible-auth (~> 1.2.5) diff --git a/lib/aptible/cli/subcommands/deploy.rb b/lib/aptible/cli/subcommands/deploy.rb index 1c13b521..ad4a5838 100644 --- a/lib/aptible/cli/subcommands/deploy.rb +++ b/lib/aptible/cli/subcommands/deploy.rb @@ -109,7 +109,7 @@ def deploy(*args) allow_it = [ opts[:git_ref], - opts[:env].try(:[], 'APTIBLE_DOCKER_IMAGE'), + opts[:settings].try(:[], 'APTIBLE_DOCKER_IMAGE'), app.status == 'provisioned' ].any? { |x| x } diff --git a/lib/aptible/cli/version.rb b/lib/aptible/cli/version.rb index ba1f1213..4a1b2166 100644 --- a/lib/aptible/cli/version.rb +++ b/lib/aptible/cli/version.rb @@ -1,5 +1,5 @@ module Aptible module CLI - VERSION = '0.25.1'.freeze + VERSION = '0.25.2'.freeze end end From 841f7d52255903c2d4949480ae8bfff7a3bfe9b4 Mon Sep 17 00:00:00 2001 From: Alex Kubacki Date: Wed, 19 Nov 2025 10:59:50 -0700 Subject: [PATCH 3/7] Update lib/aptible/cli/subcommands/deploy.rb Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/aptible/cli/subcommands/deploy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aptible/cli/subcommands/deploy.rb b/lib/aptible/cli/subcommands/deploy.rb index ad4a5838..4913afab 100644 --- a/lib/aptible/cli/subcommands/deploy.rb +++ b/lib/aptible/cli/subcommands/deploy.rb @@ -51,7 +51,7 @@ def self.included(thor) 'repository' option :private_registry_email, type: :string, - desc: 'This parameter is deprectated' + desc: 'This parameter is deprecated' app_options def deploy(*args) From b6646774893a176aa7552582e04e187178fd46e3 Mon Sep 17 00:00:00 2001 From: Alex Kubacki Date: Wed, 19 Nov 2025 10:59:57 -0700 Subject: [PATCH 4/7] Update spec/aptible/cli/subcommands/deploy_spec.rb Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- spec/aptible/cli/subcommands/deploy_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/aptible/cli/subcommands/deploy_spec.rb b/spec/aptible/cli/subcommands/deploy_spec.rb index 6abaf6fa..3bdecff2 100644 --- a/spec/aptible/cli/subcommands/deploy_spec.rb +++ b/spec/aptible/cli/subcommands/deploy_spec.rb @@ -142,7 +142,7 @@ def stub_options(**opts) .to raise_error(/deprecated/im) end - it 'reject contradictory command line argumnts' do + it 'reject contradictory command line arguments' do stub_options(docker_image: 'foobar') expect { subject.deploy('APTIBLE_DOCKER_IMAGE=qux') } From 42b215faedb5c8d228fcf444fff2a95c28d47b4d Mon Sep 17 00:00:00 2001 From: Alex Kubacki Date: Thu, 18 Dec 2025 16:13:27 -0700 Subject: [PATCH 5/7] Continue to allow (but warn) when using env for iamge/auth settings. --- Gemfile.lock | 4 +-- lib/aptible/cli/subcommands/deploy.rb | 29 ++++++++++++++------- spec/aptible/cli/subcommands/deploy_spec.rb | 15 ++++++++--- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8dcd57d3..8494a4e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,6 +20,7 @@ PATH httpclient (~> 2.8.0) json (~> 2.5.0) jwt (~> 2.3.0) + pry rack (~> 1.0) stripe (< 5.0) term-ansicolor (~> 1.8.0) @@ -120,7 +121,7 @@ GEM parser (2.7.2.0) ast (~> 2.4.1) powerpack (0.1.3) - pry (0.14.2) + pry (0.15.2) coderay (~> 1.1) method_source (~> 1.0) public_suffix (3.1.1) @@ -185,7 +186,6 @@ DEPENDENCIES climate_control (= 0.0.3) fabrication (~> 2.15.2) httplog (< 1.6) - pry rack (~> 1.0) rake rspec (~> 3.2) diff --git a/lib/aptible/cli/subcommands/deploy.rb b/lib/aptible/cli/subcommands/deploy.rb index 4913afab..d42393b1 100644 --- a/lib/aptible/cli/subcommands/deploy.rb +++ b/lib/aptible/cli/subcommands/deploy.rb @@ -2,11 +2,14 @@ module Aptible module CLI module Subcommands module Deploy - DEPRECATED_ENV = %w( + DEPRECATED_ENV = Hash[%w( APTIBLE_DOCKER_IMAGE APTIBLE_PRIVATE_REGISTRY_USERNAME APTIBLE_PRIVATE_REGISTRY_PASSWORD - ).freeze + ).map do |var| + opt = var.gsub(/^APTIBLE_/, '').downcase.to_sym + [opt, var] + end] NULL_SHA1 = '0000000000000000000000000000000000000000'.freeze @@ -70,14 +73,20 @@ def deploy(*args) env = extract_env(args) - if (DEPRECATED_ENV & env.keys).any? - option_names = DEPRECATED_ENV.map do |var| - var.gsub('APTIBLE_', '--').to_s.downcase.tr('_', '-') - end.join(', ') - m = 'ERROR: The environment variables ' \ - "#{DEPRECATED_ENV.join(', ')} are deprecated. " \ - "Use the options #{option_names}, instead" - raise Thor::Error, m + DEPRECATED_ENV.each_pair do |opt, var| + val = options[opt] + dasherized = "--#{opt.to_s.tr('_', '-')}" + if env[var] + m = "WARNING: The environment variable #{var} " \ + 'will be deprecated. Use the option ' \ + "#{dasherized}, instead." + CLI.logger.warn m + end + next unless val + if env[var] && env[var] != val + raise Thor::Error, "The options #{dasherized} and #{var} " \ + 'cannot be set to different values' + end end settings = {} diff --git a/spec/aptible/cli/subcommands/deploy_spec.rb b/spec/aptible/cli/subcommands/deploy_spec.rb index 3bdecff2..01814fc5 100644 --- a/spec/aptible/cli/subcommands/deploy_spec.rb +++ b/spec/aptible/cli/subcommands/deploy_spec.rb @@ -138,15 +138,22 @@ def stub_options(**opts) it 'allows redundant command line arguments' do stub_options(docker_image: 'foobar') - expect { subject.deploy('APTIBLE_DOCKER_IMAGE=foobar') } - .to raise_error(/deprecated/im) + expect(app).to receive(:create_operation!) + .with(type: 'deploy', + env: { 'APTIBLE_DOCKER_IMAGE' => 'foobar' }, + settings: { 'APTIBLE_DOCKER_IMAGE' => 'foobar' }) + .and_return(operation) + expect(subject).to receive(:attach_to_operation_logs) + .with(operation) + + subject.deploy('APTIBLE_DOCKER_IMAGE=foobar') end - it 'reject contradictory command line arguments' do + it 'reject contradictory command line argumnts' do stub_options(docker_image: 'foobar') expect { subject.deploy('APTIBLE_DOCKER_IMAGE=qux') } - .to raise_error(/deprecated/im) + .to raise_error(/different values/im) end it 'does not allow deploying nothing on an unprovisioned app' do From dc907afe34b1ff6dc1cc74f8b0a12202be6662cf Mon Sep 17 00:00:00 2001 From: Alex Kubacki Date: Thu, 18 Dec 2025 19:19:59 -0700 Subject: [PATCH 6/7] back it up, terry --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8494a4e7..ea7cc29e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,7 +20,6 @@ PATH httpclient (~> 2.8.0) json (~> 2.5.0) jwt (~> 2.3.0) - pry rack (~> 1.0) stripe (< 5.0) term-ansicolor (~> 1.8.0) @@ -186,6 +185,7 @@ DEPENDENCIES climate_control (= 0.0.3) fabrication (~> 2.15.2) httplog (< 1.6) + pry rack (~> 1.0) rake rspec (~> 3.2) From 03b9967834b1d769eafd5713f55a11d80e7fe219 Mon Sep 17 00:00:00 2001 From: Alex Kubacki Date: Wed, 7 Jan 2026 10:26:16 -0700 Subject: [PATCH 7/7] Add more tests --- spec/aptible/cli/subcommands/deploy_spec.rb | 35 +++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/spec/aptible/cli/subcommands/deploy_spec.rb b/spec/aptible/cli/subcommands/deploy_spec.rb index 01814fc5..447a720d 100644 --- a/spec/aptible/cli/subcommands/deploy_spec.rb +++ b/spec/aptible/cli/subcommands/deploy_spec.rb @@ -98,10 +98,12 @@ def stub_options(**opts) end it 'allows setting configuration variables' do - stub_options + stub_options(docker_image: 'foobar') expect(app).to receive(:create_operation!) - .with(type: 'deploy', env: { 'FOO' => 'bar', 'BAR' => 'qux' }) + .with(type: 'deploy', + env: { 'FOO' => 'bar', 'BAR' => 'qux' }, + settings: { 'APTIBLE_DOCKER_IMAGE' => 'foobar' }) .and_return(operation) expect(subject).to receive(:attach_to_operation_logs) .with(operation) @@ -149,6 +151,35 @@ def stub_options(**opts) subject.deploy('APTIBLE_DOCKER_IMAGE=foobar') end + context 'dasherized option for image' do + it 'deploys via operation.settings' do + stub_options(docker_image: 'foobar') + + expect(app).to receive(:create_operation!) + .with(type: 'deploy', + settings: { 'APTIBLE_DOCKER_IMAGE' => 'foobar' }) + .and_return(operation) + expect(subject).to receive(:attach_to_operation_logs) + .with(operation) + + subject.deploy + end + end + + context '(deprecated) environment variable style for image' do + it 'deploys via operation.env' do + stub_options + + expect(app).to receive(:create_operation!) + .with(type: 'deploy', env: { 'APTIBLE_DOCKER_IMAGE' => 'foobar' }) + .and_return(operation) + expect(subject).to receive(:attach_to_operation_logs) + .with(operation) + + subject.deploy('APTIBLE_DOCKER_IMAGE=foobar') + end + end + it 'reject contradictory command line argumnts' do stub_options(docker_image: 'foobar')