ndr_dev_support 6.1.5 → 6.1.8

Sign up to get free protection for your applications and to get access to all the features.
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