ndr_dev_support 6.1.4 → 6.1.7

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: 665f148ac622b9f75c0150d8b1d6770aaeaaf5c9d1bb561c5a1d34a3f9b8bf2d
4
- data.tar.gz: af2bd48cfef10426450978b40071f134d40af2524edec37cf380b5ffa820a409
3
+ metadata.gz: 5fe8e3400612fc7c12992a9ed37a1896cc2345ef9d060638776ad5f3f5f2c2e1
4
+ data.tar.gz: 229b4288c7f789407821bea03feaf6bf0512b5628d51d1a69fd8f8febdcacb6d
5
5
  SHA512:
6
- metadata.gz: 706873fa19d231e950bec7f26a74946a5c19d9d594930b5fe6b64e0b4be12545254b2371c82067a7ed0b420153ac050f449980c84c3eb15b8a2a58940e6a64ab
7
- data.tar.gz: a20045257bbd629bca137e8b8724549836c2c484e05d1074b245dbdf56c607608cfd572141619c4bfe18786ae8645581ebe6777ed0068bd849e1bb8d97d95306
6
+ metadata.gz: 1edfdb2328f91d2fb3707b1f6e1b8b70f48cf4bae5037a1bea01398192a079912d063842bd45a88b748fb6522e6c6b5593336584e7bad3a0e2c91e0ff539fcb5
7
+ data.tar.gz: 687c9637cc0c9d1dae203b242393f91c44fc7817719fb9e0fbe43bb8ea9b545918ee45850f0f2f2d8186858a72ef807416ef2006fd8cf7f8b2533b5987596c74
data/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  ## [Unreleased]
2
2
  * No unreleased changes
3
3
 
4
+ ## 6.1.7 / 2022-07-15
5
+ ### Added
6
+ * Add `cd:credentials` rake task for continuous deployment of credentials
7
+
8
+ ## 6.1.6 / 2022-07-01
9
+ ### Added
10
+ * capistrano: use DEPLOYER environment variable for non-interactive deployments
11
+
12
+ ## 6.1.5 / 2022-06-24
13
+ ### Fixed
14
+ * audit:code should allow special characters in filenames
15
+
4
16
  ## 6.1.4 / 2022-06-16
5
17
  ### Added
6
18
  * Add warning when upgrading webpacker
@@ -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
@@ -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.4'
5
+ VERSION = '6.1.7'
6
6
  end
@@ -1,6 +1,7 @@
1
1
  require 'csv'
2
2
  require 'pathname'
3
3
  require 'yaml'
4
+ require 'shellwords'
4
5
 
5
6
  SAFETY_FILE =
6
7
  if File.exist?('code_safety.yml')
@@ -338,7 +339,8 @@ def get_last_changed_revision(repo, fname)
338
339
  %x[git log -n 1 -- "#{fname}"].split("\n").first[7..-1]
339
340
  when 'git-svn', 'svn'
340
341
  begin
341
- svn_info = %x[svn info -r head "#{repo}/#{fname}"]
342
+ dest = "#{repo}/#{fname}@"
343
+ svn_info = %x[svn info -r head #{Shellwords.escape(dest)}]
342
344
  rescue
343
345
  puts 'we have an error in the svn info line'
344
346
  end
@@ -376,9 +378,10 @@ def capture_file_diffs(repo, fname, safe_revision, repolatest)
376
378
  cmd =
377
379
  case repository_type
378
380
  when 'git'
379
- cmd = ['git', '--no-pager', 'diff', '--color', '-b', "#{safe_revision}..#{repolatest}", fname]
381
+ ['git', '--no-pager', 'diff', '--color', '-b', "#{safe_revision}..#{repolatest}", fname]
380
382
  when 'git-svn', 'svn'
381
- cmd = ['svn', 'diff', '-r', "#{safe_revision.to_i}:#{repolatest.to_i}", '-x', '-b', "#{repo}/#{fname}"]
383
+ ['svn', 'diff', '-r', "#{safe_revision.to_i}:#{repolatest.to_i}", '-x', '-b',
384
+ "#{repo}/#{fname}@"]
382
385
  end
383
386
 
384
387
  stdout_and_err_str, _status = Open3.capture2e(*cmd)
@@ -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.4
4
+ version: 6.1.7
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-16 00:00:00.000000000 Z
11
+ date: 2022-07-15 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