capistrano-redmine-deployment 1.0.1 → 1.1.0

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: 5a1d4def15c15b92236d4cad5e63ab56a469b973763bcaeb0be17a59477efc5e
4
- data.tar.gz: 91f5982de00664a05f986f714acd782464c60901d6af1ff051dd7691ecf61032
3
+ metadata.gz: d6bcb935ad7aaa01c101fa9380a958b0dc57a3d6b1b39797fafb3eff6ae03a05
4
+ data.tar.gz: adaff749719d3b3178b3f6f23e71d9605c8785ff37c773d2422eb2a76f568956
5
5
  SHA512:
6
- metadata.gz: af10737c30d398ab457265538ea359850403e53ec28771ba020cef4a07d178c712aeaafc0a4cbce4d760d9bf81d21938c8b5aa85ef1a95c6e8116aded924a950
7
- data.tar.gz: 9d1282a7b24f607c94603b1604138e5d30a18173bbd468be524e39eb8af6c69bf10c47a36703d1868a047a85f9ebc51c65860b0ded0599c3b46f0655db26b1ac
6
+ metadata.gz: c552022bdeac49a92283af11c3e99869efb1509be175ee68179759300c6c3fde2e502b1e096736157f20e4382e77bdd1a934ceb93c6a82a2d736bd544a3ba9c1
7
+ data.tar.gz: b3d6ae5239ac13d3042f5228ba2a6175a3a0d1b115e186196bf26418d50db3518cb3ea4da397d7c5893f4203db3047ffa3b727ead08e30cddf69f5c25227ac2d
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require spec_helper
2
+ --format documentation
data/Gemfile CHANGED
@@ -6,3 +6,4 @@ source "https://rubygems.org"
6
6
  gemspec
7
7
 
8
8
  gem "rake"
9
+ gem "rspec"
data/README.md CHANGED
@@ -49,13 +49,43 @@ set(:redmine_repository, "target-redmine-repository-identifier")
49
49
 
50
50
  # in case of `SSL` issues that are caused by *CRL* (i.e. by LetsEncrypt certificates)
51
51
  set(:redmine_host_verification, false)
52
+
53
+ # alternatively, for instances with a custom CA, point to a CA bundle instead of
54
+ # disabling verification entirely (preferred over :redmine_host_verification)
55
+ set(:redmine_ca_file, "/path/to/ca-bundle.pem")
52
56
  ```
53
57
 
54
58
  ### User-specific credentials
55
59
 
60
+ The `api_key` is resolved from the following sources, **later ones win**:
61
+
62
+ 1. capistrano variables: `:redmine_api_key`, or `:redmine_api_key_command` (its stdout is used as the key) as fallback
63
+ 2. `.redmine` file in the current directory (`$PWD`) or `$HOME`
64
+ 3. the `REDMINE_API_KEY` ENV variable
65
+
66
+ #### Option A: macOS Keychain (recommended)
67
+
68
+ Store the key once per developer in the keychain (use a dedicated entry):
69
+
70
+ $ security add-generic-password -s ri-redmine-deploy -a "$USER" -w 'YOUR_KEY'
71
+
72
+ Then point capistrano at a command that reads it, in your `config/deploy.rb`:
73
+
74
+ ```ruby
75
+ set :redmine_api_key_command, 'security find-generic-password -s ri-redmine-deploy -w'
76
+ ```
77
+
78
+ No secret ends up in `deploy.rb` or your SCM — only the command. Once every developer
79
+ has switched over, the `.redmine` file can be removed entirely (it stays supported as a
80
+ fallback).
81
+
82
+ > Use a **dedicated** keychain entry (e.g. `ri-redmine-deploy`).
83
+
84
+ #### Option B: `.redmine` file via rake-task
85
+
56
86
  Setup redmine `API-KEY` through rake-task:
57
87
 
58
- $ rake capistrano:redmine:deploy:setup
88
+ $ rake capistrano:redmine:deployment:setup
59
89
 
60
90
 
61
91
  ## Redmine requirements
data/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Capistrano::Redmine::Deployment - CHANGELOG
2
2
 
3
+ ## [1.1.0] - 2026-07-10
4
+ * **[add]** ENV layer for config (`REDMINE_API_KEY`, `REDMINE_HOST`, `REDMINE_PROJECT`, `REDMINE_REPOSITORY`, `REDMINE_CA_FILE`)
5
+ * **[add]** `:redmine_api_key` capistrano variable, with `:redmine_api_key_command` (command stdout, e.g. macOS keychain) as fallback
6
+ * **[add]** `:redmine_ca_file` config (and `REDMINE_CA_FILE` ENV) as a safe alternative to disabling host verification
7
+ * **[add]** rspec test suite for `Config.resolve` layer precedence
8
+ * **[ref]** config resolution order: capistrano is the base, then `.redmine` files, then ENV win over it
9
+ * **[fix]** enable SSL by URI scheme (`https`) instead of only port 443, so HTTPS on non-standard ports works
10
+
3
11
  ## [1.0.1] - 2025-10-24
4
12
  * **[add]** config for `host_verification` to skip issues with OpenSSL / CRL issues
5
13
  * **[add]** warning message during deployment while host verification is disabled
@@ -60,8 +60,13 @@ module Capistrano
60
60
  uri = URI("#{config.host}/projects/#{config.project}/deploy/#{config.repository}.json")
61
61
 
62
62
  http = Net::HTTP.new(uri.host, uri.port)
63
- http.use_ssl = true if uri.port == 443
64
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE if config.host_verification == false
63
+ http.use_ssl = true if uri.scheme == 'https'
64
+
65
+ if config.ca_file
66
+ http.ca_file = config.ca_file
67
+ elsif config.host_verification == false
68
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
69
+ end
65
70
 
66
71
  request = Net::HTTP::Post.new(uri.request_uri)
67
72
  request["Content-Type"] = "application/json"
@@ -79,7 +84,8 @@ module Capistrano
79
84
 
80
85
  def log_deploy(deployment)
81
86
  puts "Sending deployment information to #{config.host} (project: '#{config.project}' | repo: '#{config.repository}')"
82
- puts "\e[33m WARNING: Host verification disabled!\e[0m" if config.host_verification == false
87
+ puts "\e[33m Using custom CA file: #{config.ca_file}\e[0m" if config.ca_file
88
+ puts "\e[33m WARNING: Host verification disabled!\e[0m" if config.ca_file.nil? && config.host_verification == false
83
89
  puts ""
84
90
  puts " Commits......: #{deployment[:from_revision]} ... #{deployment[:to_revision]}"
85
91
  puts " Environment..: #{deployment[:environment] || '-'}"
@@ -14,7 +14,7 @@ module Capistrano
14
14
  # build new empty config
15
15
  config = new
16
16
 
17
- # try to resolve from capistrano
17
+ # capistrano is the base - files and ENV win over it
18
18
  config.assign!(config_from_capistrano(capistrano)) if capistrano
19
19
 
20
20
  # try to resolve from current PWD
@@ -22,23 +22,58 @@ module Capistrano
22
22
  config.assign!(config_from_file(File.join(ENV['HOME'], '.redmine')))
23
23
  config.assign!(config_from_file(file)) if file
24
24
 
25
+ # ENV wins over files and capistrano
26
+ config.assign!(config_from_env)
27
+
25
28
  config
26
29
  end
27
30
 
28
31
  def config_from_capistrano(capistrano)
29
32
  config = {
33
+ api_key: capistrano.fetch(:redmine_api_key) || api_key_from_command(capistrano),
30
34
  host: capistrano.fetch(:redmine_host),
31
35
  project: capistrano.fetch(:redmine_project) || capistrano.fetch(:redmine_project_id),
32
36
  repository: capistrano.fetch(:redmine_repository),
33
- host_verification: capistrano.fetch(:redmine_host_verification)
37
+ host_verification: capistrano.fetch(:redmine_host_verification),
38
+ ca_file: capistrano.fetch(:redmine_ca_file)
34
39
  }
35
40
 
36
41
  new(config)
37
42
  end
38
43
 
44
+ # Resolves config from ENV variables. Values are filtered by `assign!`,
45
+ # so unset (nil/empty) variables never overwrite an existing value.
46
+ def config_from_env
47
+ new({
48
+ api_key: ENV['REDMINE_API_KEY'],
49
+ host: ENV['REDMINE_HOST'],
50
+ project: ENV['REDMINE_PROJECT'],
51
+ repository: ENV['REDMINE_REPOSITORY'],
52
+ ca_file: ENV['REDMINE_CA_FILE']
53
+ })
54
+ end
55
+
39
56
  def config_from_file(file)
40
57
  new(file: file)
41
58
  end
59
+
60
+ private
61
+
62
+ # Resolves the api_key by running the `:redmine_api_key_command` capistrano
63
+ # variable (if set) and taking its stdout. This keeps the secret out of
64
+ # `deploy.rb` - only the command (e.g. a keychain lookup) lives there.
65
+ #
66
+ # On any failure (non-zero exit or empty stdout) nil is returned so the
67
+ # file/ENV fallback still applies.
68
+ def api_key_from_command(capistrano)
69
+ cmd = capistrano.fetch(:redmine_api_key_command)
70
+ return nil unless cmd && cmd != ''
71
+
72
+ key = `#{cmd}`.strip
73
+ return nil unless $?.success? && !key.empty?
74
+
75
+ key
76
+ end
42
77
  end
43
78
 
44
79
  def initialize(config = {}, file: nil)
@@ -10,8 +10,8 @@ module Capistrano
10
10
 
11
11
  module VERSION
12
12
  MAJOR = 1
13
- MINOR = 0
14
- TINY = 1
13
+ MINOR = 1
14
+ TINY = 0
15
15
  PRE = nil
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -24,6 +24,11 @@ Configure the redmine credentials for deployment.
24
24
  puts ""
25
25
  puts " > HINT: Keep configs empty to prevent to overwrite existing configs."
26
26
  puts ""
27
+ puts " > ALTERNATIVE (recommended): the api_key can also be provided without this file"
28
+ puts " via the ENV variable 'REDMINE_API_KEY' or the capistrano variable"
29
+ puts " ':redmine_api_key_command' (e.g. a macOS keychain lookup). Both win over"
30
+ puts " the '.redmine' file. See the README for details."
31
+ puts ""
27
32
  puts "******************************************************************************************************"
28
33
  puts ""
29
34
  puts ""
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-redmine-deployment
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Gonsior
@@ -19,6 +19,7 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - ".gitignore"
22
+ - ".rspec"
22
23
  - Gemfile
23
24
  - LICENSE.txt
24
25
  - README.md