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 +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/ndr_dev_support/capistrano/ndr_model.rb +9 -2
- data/lib/ndr_dev_support/daemon/cd_credentials.rb +157 -0
- data/lib/ndr_dev_support/daemon/stoppable.rb +2 -1
- data/lib/ndr_dev_support/slack_message_publisher.rb +2 -0
- data/lib/ndr_dev_support/tasks.rb +1 -0
- data/lib/ndr_dev_support/version.rb +1 -1
- data/lib/tasks/cd/credentials.rake +9 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5895d92318201f2232d8f232f6d7a3ae590c02f67992a6615ec9e27f024d097b
|
4
|
+
data.tar.gz: bf60948987bbe9d71d418ba460082d04bb88190bc62fbb51f2f2681e88642d54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
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.
|
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)
|
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
|
+
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-
|
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
|