ndr_dev_support 6.1.5 → 6.1.8

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: f9b372449b95e60ead7c4da7289b8d98de92a18c894fb79c14391fcf3d6370fe
4
- data.tar.gz: 8847e9f85ba14c6268c49a1ee031411833674bcd506966b3a54aae03f283d95f
3
+ metadata.gz: 5895d92318201f2232d8f232f6d7a3ae590c02f67992a6615ec9e27f024d097b
4
+ data.tar.gz: bf60948987bbe9d71d418ba460082d04bb88190bc62fbb51f2f2681e88642d54
5
5
  SHA512:
6
- metadata.gz: a5217032e0347fd837e0cf31f3dce1c173bf701a6c1f1b8f2c28762b37239c75bf01884e6c0de629c1668198aa978a278d4dc629fb8efdd070b60d84e0a6e230
7
- data.tar.gz: 9b6f2ef06634b6fbe67cef8b196c55167456c8ab4cc513ab38c09ab0261c5ba13922da46bae3d3e4875c52ffa8396dcd1cbe204700ae63e0df49e38336eccca2
6
+ metadata.gz: 2a26d059ad0840e7290cb6c2f130944af19433c447e7a871c6b396243e7a9070e89594945bef3e7f85813488439e41ba0415c068810f59dca32288a78dee44f2
7
+ data.tar.gz: 3a549e3cfd26b724463a46998f737fdc1360c88de7646551ecfa3cecc4863338ed63bc13f140b92681dce22f83930cf88b881ccf5b57ada6d41fcffe50d3f496
data/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  ## [Unreleased]
2
2
  * No unreleased changes
3
3
 
4
+ ## 6.1.8 / 2022-08-09
5
+ ### Fixed
6
+ * Fixed ActiveSupport 7 deprecation messages
7
+
8
+ ## 6.1.7 / 2022-07-15
9
+ ### Added
10
+ * Add `cd:credentials` rake task for continuous deployment of credentials
11
+
12
+ ## 6.1.6 / 2022-07-01
13
+ ### Added
14
+ * capistrano: use DEPLOYER environment variable for non-interactive deployments
15
+
4
16
  ## 6.1.5 / 2022-06-24
5
17
  ### Fixed
6
18
  * audit:code should allow special characters in filenames
@@ -30,6 +30,8 @@ require_relative 'sysadmin_scripts'
30
30
  # and SVN branches. To use the latter, be sure to set the `:repository_branches` variable
31
31
  # to point at the root of the branches. Otherwise, just set `:repository` directly as normal.
32
32
  #
33
+ # Set environment variable DEPLOYER to deploy as a particular user instead of prompting.
34
+ #
33
35
  Capistrano::Configuration.instance(:must_exist).load do
34
36
  # Paths that are symlinked for each release to the "shared" directory:
35
37
  set :shared_paths, %w[config/database.yml config/secrets.yml log tmp]
@@ -94,9 +96,14 @@ Capistrano::Configuration.instance(:must_exist).load do
94
96
 
95
97
  # Gather SSH credentials: (password is asked for by Net::SSH, if needed)
96
98
  set :use_sudo, false
97
- set :user, Capistrano::CLI.ui.ask('Deploy as: ')
99
+ if ENV['DEPLOYER']
100
+ set :user, ENV['DEPLOYER']
101
+ Capistrano::CLI.ui.say "Deploy as: #{fetch(:user)}"
102
+ else
103
+ set :user, Capistrano::CLI.ui.ask('Deploy as: ')
104
+ end
98
105
 
99
- # If no alternate user is specified, deploy to the crediental-holding user.
106
+ # If no alternate user is specified, deploy to the credential-holding user.
100
107
  set :application_user, fetch(:user) unless fetch(:application_user)
101
108
 
102
109
  # The home folder of the application user:
@@ -0,0 +1,157 @@
1
+ require 'English'
2
+ require_relative 'stoppable'
3
+ require 'ndr_dev_support/slack_message_publisher'
4
+ require 'shellwords'
5
+ require 'with_clean_rbenv'
6
+
7
+ module NdrDevSupport
8
+ module Daemon
9
+ # Wrapper around Capistrano based Continuous Deployment of application credentials
10
+ #
11
+ # Assumes there is a capistrano task "app:update_secrets" which can be used together
12
+ # with a target name, e.g. cap target app:update_secrets
13
+ # to update a capistrano target with secrets / credentials from one or more repositories.
14
+ # To use this daemon, a number of environment variables need to be set
15
+ # including CD_TARGETS and CD_URLS.
16
+ class CDCredentials
17
+ include Stoppable
18
+
19
+ def self.from_args(env)
20
+ name = env['WORKER_NAME'].to_s
21
+ cd_targets = env['CD_TARGETS'].to_s.split
22
+ cd_urls = env['CD_URLS'].to_s.split
23
+
24
+ new(name: name, cd_targets: cd_targets, cd_urls: cd_urls)
25
+ end
26
+
27
+ def initialize(name:, cd_targets:, cd_urls:)
28
+ super
29
+
30
+ # Worker name can be used for clear logging:
31
+ @name = name
32
+ raise ArgumentError, 'No WORKER_NAME specified!' if name.blank?
33
+
34
+ # Capistrano targets to use for deployments
35
+ @cd_targets = cd_targets
36
+ raise ArgumentError, 'No CD_TARGETS specified!' unless cd_targets&.present?
37
+
38
+ # URLs to watch for continuous deployment
39
+ @cd_urls = cd_urls
40
+ raise ArgumentError, 'No CD_URLS specified!' unless cd_urls&.present?
41
+ end
42
+
43
+ private
44
+
45
+ def run_once
46
+ log('running once...')
47
+
48
+ # Keep state, watch repositories for changes, maybe save state to disk?
49
+ if (revisions = check_for_new_revisions)
50
+ log("deploying with revisions #{revisions}...")
51
+ deploy_credentials # should also notify slack if any changes deployed, but not
52
+ else
53
+ log('nothing new to deploy')
54
+ end
55
+ log('completed single run.')
56
+ rescue => e
57
+ log(<<~MSG)
58
+ Unhandled exception! #{e.class}: #{e.message}
59
+ #{(e.backtrace || []).join("\n")}
60
+ MSG
61
+
62
+ raise e
63
+ end
64
+
65
+ # Check for new revisions, and cache the latest one.
66
+ # If there are new revisions in the repositories available since the last check,
67
+ # return a hash of repo -> latest revision
68
+ # If no revisions have changed, returns nil
69
+ def check_for_new_revisions
70
+ # TODO: implement this, by checking for updates to @cd_urls
71
+ # Stub implementation, pretends things always changed
72
+ { 'dummy_repo' => '0' }
73
+ end
74
+
75
+ # Deploy credentials to all targets. Should also notify slack if any changes deployed
76
+ def deploy_credentials
77
+ log("Deploying to #{@cd_targets.join(', ')}...")
78
+ @changed_targets = []
79
+ @unchanged_targets = []
80
+ @failed_targets = []
81
+ @cd_targets.each do |target|
82
+ deploy_to_target(target)
83
+ end
84
+ publish_results
85
+ end
86
+
87
+ # Deploy credentials to a single target.
88
+ def deploy_to_target(target)
89
+ WithCleanRbenv.with_clean_rbenv do
90
+ results = `rbenv exec bundle exec cap #{Shellwords.escape(target)} \
91
+ app:update_secrets < /dev/null`.split("\n")
92
+ puts results
93
+ if $CHILD_STATUS.exitstatus.zero?
94
+ if results.include?('No changed secret files to upload')
95
+ @unchanged_targets << target
96
+ log("Unchanged target #{target}")
97
+ elsif results.grep(/^Uploaded [0-9]+ changed secret files: /).any?
98
+ @changed_targets << target
99
+ log("Changed target #{target}")
100
+ else
101
+ @failed_targets << target
102
+ log("Unparseable result deploying to target #{target}")
103
+ end
104
+ else
105
+ @failed_targets << target
106
+ log("Failed to deploy to target #{target}")
107
+ end
108
+ end
109
+ end
110
+
111
+ def publish_results
112
+ slack_publisher = NdrDevSupport::SlackMessagePublisher.new(ENV['SLACK_WEBHOOK_URL'],
113
+ username: 'Rake CI',
114
+ icon_emoji: ':robot_face:',
115
+ channel: ENV['SLACK_CHANNEL'])
116
+ slack_publisher.post(attachments: attachments)
117
+ end
118
+
119
+ # Status / warning messages for slack notifications
120
+ def attachments
121
+ attachments = []
122
+
123
+ if @failed_targets.any?
124
+ attachment = {
125
+ color: 'danger',
126
+ title: "#{@failed_targets.count} failed credential updates :rotating_light:",
127
+ text: "Failed targets: `#{@failed_targets.join(', ')}`",
128
+ footer: 'bundle exec cap target app:update_secrets',
129
+ mrkdwn_in: ['text']
130
+ }
131
+ attachments << attachment
132
+ puts attachment.inspect
133
+ end
134
+
135
+ if @changed_targets.any?
136
+ text = "Changed targets: `#{@changed_targets.join(', ')}`\n"
137
+ text << (if @unchanged_targets.any?
138
+ "Unchanged targets: `#{@unchanged_targets.join(', ')}`"
139
+ else
140
+ 'No unchanged targets'
141
+ end)
142
+ attachment = {
143
+ color: 'good',
144
+ title: "#{@changed_targets.size} successful credential updates",
145
+ text: text,
146
+ footer: 'bundle exec cap target app:update_secrets',
147
+ mrkdwn_in: ['text']
148
+ }
149
+ attachments << attachment
150
+ puts attachment.inspect
151
+ end
152
+
153
+ attachments
154
+ end
155
+ end
156
+ end
157
+ end
@@ -68,7 +68,8 @@ module NdrDevSupport
68
68
  end
69
69
 
70
70
  def log(message, level = :info)
71
- tags = "[#{Time.current.to_s(:db)}] [#{level.upcase}] [daemon: #{name} (#{Process.pid})]"
71
+ tags = "[#{Time.current.to_formatted_s(:db)}] [#{level.upcase}] " \
72
+ "[daemon: #{name} (#{Process.pid})]"
72
73
  message = "#{tags} #{message}"
73
74
 
74
75
  logger.send(level, message)
@@ -1,3 +1,5 @@
1
+ require 'net/http'
2
+
1
3
  module NdrDevSupport
2
4
  # This Class publishes messages to Slack
3
5
  class SlackMessagePublisher
@@ -1,5 +1,6 @@
1
1
  load 'tasks/audit_code.rake'
2
2
  load 'tasks/audit_bundle.rake'
3
+ load 'tasks/cd/credentials.rake'
3
4
  load 'tasks/ci/brakeman.rake'
4
5
  load 'tasks/ci/bundle_audit.rake'
5
6
  load 'tasks/ci/commit_cop.rake'
@@ -2,5 +2,5 @@
2
2
  # This defines the NdrDevSupport version. If you change it, rebuild and commit the gem.
3
3
  # Use "rake build" to build the gem, see rake -T for all bundler rake tasks (and our own).
4
4
  module NdrDevSupport
5
- VERSION = '6.1.5'
5
+ VERSION = '6.1.8'
6
6
  end
@@ -0,0 +1,9 @@
1
+ namespace :cd do
2
+ desc 'Run Capistrano Continuous Deployment credentials server'
3
+ task :credentials do
4
+ require 'ndr_dev_support/daemon/cd_credentials'
5
+
6
+ worker = NdrDevSupport::Daemon::CDCredentials.from_args(ENV)
7
+ worker.run
8
+ end
9
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ndr_dev_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.5
4
+ version: 6.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - NCRS Development Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-24 00:00:00.000000000 Z
11
+ date: 2022-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -422,6 +422,7 @@ files:
422
422
  - lib/ndr_dev_support/capistrano/standalone_gems.rb
423
423
  - lib/ndr_dev_support/capistrano/svn_cache.rb
424
424
  - lib/ndr_dev_support/capistrano/sysadmin_scripts.rb
425
+ - lib/ndr_dev_support/daemon/cd_credentials.rb
425
426
  - lib/ndr_dev_support/daemon/ci_server.rb
426
427
  - lib/ndr_dev_support/daemon/stoppable.rb
427
428
  - lib/ndr_dev_support/integration_testing.rb
@@ -452,6 +453,7 @@ files:
452
453
  - lib/ndr_dev_support/version.rb
453
454
  - lib/tasks/audit_bundle.rake
454
455
  - lib/tasks/audit_code.rake
456
+ - lib/tasks/cd/credentials.rake
455
457
  - lib/tasks/ci/brakeman.rake
456
458
  - lib/tasks/ci/bundle_audit.rake
457
459
  - lib/tasks/ci/commit_cop.rake