dlss-capistrano-docker 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +56 -0
- data/.rubocop.yml +178 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +67 -0
- data/README.md +98 -0
- data/Rakefile +15 -0
- data/dlss-capistrano-docker.gemspec +33 -0
- data/lib/dlss/docker/capistrano/tasks/docker.rake +50 -0
- data/lib/dlss/docker/capistrano/tasks/docker_compose.rake +198 -0
- data/lib/dlss/docker/capistrano/tasks/honeybadger.rake +58 -0
- data/lib/dlss/docker/capistrano/tasks/shared_configs.rake +21 -0
- data/lib/dlss/docker/capistrano/tasks/ssh.rake +10 -0
- data/lib/dlss/docker/capistrano.rb +6 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7b180b31a5354ceec3029befccbdeac4ba5c86321eb75a1beb369d0c24a5ebbd
|
4
|
+
data.tar.gz: 30865848d3ef1b7c5e86565641aed355c011cf85e5219999c112a1d234d353eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f90641ba2d8b8c60c7f22e45dfc477f163732e9aeb3b89244b5b1563e09f10913c51cdb59464dc8d015c7b5f558655d01d7b9729fbe11b541603ab0504828a53
|
7
|
+
data.tar.gz: dddb973eaecac7511a4a6128cdf6a0e2b065226e0e8c40547204b191ae101cb5eb3010669551831ce1a8685fb10b8e86f5854ada8044815f3d548c59c71524c8
|
data/.gitignore
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
# Ignore Byebug command history file.
|
17
|
+
.byebug_history
|
18
|
+
|
19
|
+
## Specific to RubyMotion:
|
20
|
+
.dat*
|
21
|
+
.repl_history
|
22
|
+
build/
|
23
|
+
*.bridgesupport
|
24
|
+
build-iPhoneOS/
|
25
|
+
build-iPhoneSimulator/
|
26
|
+
|
27
|
+
## Specific to RubyMotion (use of CocoaPods):
|
28
|
+
#
|
29
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
30
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
31
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
32
|
+
#
|
33
|
+
# vendor/Pods/
|
34
|
+
|
35
|
+
## Documentation cache and generated files:
|
36
|
+
/.yardoc/
|
37
|
+
/_yardoc/
|
38
|
+
/doc/
|
39
|
+
/rdoc/
|
40
|
+
|
41
|
+
## Environment normalization:
|
42
|
+
/.bundle/
|
43
|
+
/vendor/bundle
|
44
|
+
/lib/bundler/man/
|
45
|
+
|
46
|
+
# for a library or gem, you might want to ignore these files since the code is
|
47
|
+
# intended to run in multiple environments; otherwise, check them in:
|
48
|
+
# Gemfile.lock
|
49
|
+
# .ruby-version
|
50
|
+
# .ruby-gemset
|
51
|
+
|
52
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
53
|
+
.rvmrc
|
54
|
+
|
55
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
56
|
+
# .rubocop-https?--*
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 3.1
|
3
|
+
SuggestExtensions: false
|
4
|
+
DisplayCopNames: true
|
5
|
+
Include:
|
6
|
+
- './Rakefile' # rake only
|
7
|
+
- '**/*.rb'
|
8
|
+
- '**/*.rake' # rake only
|
9
|
+
|
10
|
+
Bundler/GemComment:
|
11
|
+
OnlyFor:
|
12
|
+
- restrictive_version_specifiers
|
13
|
+
- branch
|
14
|
+
|
15
|
+
# Configuration parameters: AllowURI, URISchemes.
|
16
|
+
Layout/LineLength:
|
17
|
+
Max: 120
|
18
|
+
|
19
|
+
# consider if refactoring will improve adherence to SOLID and/or improve readability
|
20
|
+
# Sometimes splitting the class up won't improve readablity, it just makes reader jump around in the code.
|
21
|
+
Metrics/ClassLength:
|
22
|
+
Max: 150 # default 100
|
23
|
+
|
24
|
+
# consider if refactoring will improve adherence to SOLID and/or improve readability
|
25
|
+
# Sometimes splitting the method up won't improve readablity, it just makes reader jump around in the code.
|
26
|
+
# Good method names help.
|
27
|
+
Metrics/MethodLength:
|
28
|
+
Max: 15 # default 10
|
29
|
+
|
30
|
+
# capistrano tasks tend to be long.
|
31
|
+
Metrics/BlockLength:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
# "> 0", "== 0", "< 0" are not less readable than ".positive?", ".zero?" or ".negative?"
|
35
|
+
Style/NumericPredicate:
|
36
|
+
Enabled: false
|
37
|
+
|
38
|
+
Style/RegexpLiteral:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
Style/SymbolArray:
|
42
|
+
MinSize: 4 # default 2
|
43
|
+
|
44
|
+
Style/WordArray:
|
45
|
+
MinSize: 4 # default 2
|
46
|
+
|
47
|
+
Gemspec/DeprecatedAttributeAssignment: # new in 1.30
|
48
|
+
Enabled: true
|
49
|
+
Gemspec/RequireMFA: # new in 1.23
|
50
|
+
Enabled: true
|
51
|
+
Layout/LineContinuationLeadingSpace: # new in 1.31
|
52
|
+
Enabled: true
|
53
|
+
Layout/LineContinuationSpacing: # new in 1.31
|
54
|
+
Enabled: true
|
55
|
+
Layout/LineEndStringConcatenationIndentation: # new in 1.18
|
56
|
+
Enabled: true
|
57
|
+
Layout/SpaceBeforeBrackets: # new in 1.7
|
58
|
+
Enabled: true
|
59
|
+
Lint/AmbiguousAssignment: # new in 1.7
|
60
|
+
Enabled: true
|
61
|
+
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
62
|
+
Enabled: true
|
63
|
+
Lint/AmbiguousRange: # new in 1.19
|
64
|
+
Enabled: true
|
65
|
+
Lint/ConstantOverwrittenInRescue: # new in 1.31
|
66
|
+
Enabled: true
|
67
|
+
Lint/DeprecatedConstants: # new in 1.8
|
68
|
+
Enabled: true
|
69
|
+
Lint/DuplicateBranch: # new in 1.3
|
70
|
+
Enabled: true
|
71
|
+
Lint/DuplicateRegexpCharacterClassElement: # new in 1.1
|
72
|
+
Enabled: true
|
73
|
+
Lint/EmptyBlock: # new in 1.1
|
74
|
+
Enabled: true
|
75
|
+
Lint/EmptyClass: # new in 1.3
|
76
|
+
Enabled: true
|
77
|
+
Lint/EmptyInPattern: # new in 1.16
|
78
|
+
Enabled: true
|
79
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
80
|
+
Enabled: true
|
81
|
+
Lint/LambdaWithoutLiteralBlock: # new in 1.8
|
82
|
+
Enabled: true
|
83
|
+
Lint/NoReturnInBeginEndBlocks: # new in 1.2
|
84
|
+
Enabled: true
|
85
|
+
Lint/NonAtomicFileOperation: # new in 1.31
|
86
|
+
Enabled: true
|
87
|
+
Lint/NumberedParameterAssignment: # new in 1.9
|
88
|
+
Enabled: true
|
89
|
+
Lint/OrAssignmentToConstant: # new in 1.9
|
90
|
+
Enabled: true
|
91
|
+
Lint/RedundantDirGlobSort: # new in 1.8
|
92
|
+
Enabled: true
|
93
|
+
Lint/RefinementImportMethods: # new in 1.27
|
94
|
+
Enabled: true
|
95
|
+
Lint/RequireRangeParentheses: # new in 1.32
|
96
|
+
Enabled: true
|
97
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
98
|
+
Enabled: true
|
99
|
+
Lint/SymbolConversion: # new in 1.9
|
100
|
+
Enabled: true
|
101
|
+
Lint/ToEnumArguments: # new in 1.1
|
102
|
+
Enabled: true
|
103
|
+
Lint/TripleQuotes: # new in 1.9
|
104
|
+
Enabled: true
|
105
|
+
Lint/UnexpectedBlockArity: # new in 1.5
|
106
|
+
Enabled: true
|
107
|
+
Lint/UnmodifiedReduceAccumulator: # new in 1.1
|
108
|
+
Enabled: true
|
109
|
+
Lint/UselessRuby2Keywords: # new in 1.23
|
110
|
+
Enabled: true
|
111
|
+
Naming/BlockForwarding: # new in 1.24
|
112
|
+
Enabled: true
|
113
|
+
Security/CompoundHash: # new in 1.28
|
114
|
+
Enabled: true
|
115
|
+
Security/IoMethods: # new in 1.22
|
116
|
+
Enabled: true
|
117
|
+
Style/ArgumentsForwarding: # new in 1.1
|
118
|
+
Enabled: true
|
119
|
+
Style/CollectionCompact: # new in 1.2
|
120
|
+
Enabled: true
|
121
|
+
Style/DocumentDynamicEvalDefinition: # new in 1.1
|
122
|
+
Enabled: true
|
123
|
+
Style/EmptyHeredoc: # new in 1.32
|
124
|
+
Enabled: true
|
125
|
+
Style/EndlessMethod: # new in 1.8
|
126
|
+
Enabled: true
|
127
|
+
Style/EnvHome: # new in 1.29
|
128
|
+
Enabled: true
|
129
|
+
Style/FetchEnvVar: # new in 1.28
|
130
|
+
Enabled: true
|
131
|
+
Style/FileRead: # new in 1.24
|
132
|
+
Enabled: true
|
133
|
+
Style/FileWrite: # new in 1.24
|
134
|
+
Enabled: true
|
135
|
+
Style/HashConversion: # new in 1.10
|
136
|
+
Enabled: true
|
137
|
+
Style/HashExcept: # new in 1.7
|
138
|
+
Enabled: true
|
139
|
+
Style/IfWithBooleanLiteralBranches: # new in 1.9
|
140
|
+
Enabled: true
|
141
|
+
Style/InPatternThen: # new in 1.16
|
142
|
+
Enabled: true
|
143
|
+
Style/MagicCommentFormat: # new in 1.35
|
144
|
+
Enabled: true
|
145
|
+
Style/MapCompactWithConditionalBlock: # new in 1.30
|
146
|
+
Enabled: true
|
147
|
+
Style/MapToHash: # new in 1.24
|
148
|
+
Enabled: true
|
149
|
+
Style/MultilineInPatternThen: # new in 1.16
|
150
|
+
Enabled: true
|
151
|
+
Style/NegatedIfElseCondition: # new in 1.2
|
152
|
+
Enabled: true
|
153
|
+
Style/NestedFileDirname: # new in 1.26
|
154
|
+
Enabled: true
|
155
|
+
Style/NilLambda: # new in 1.3
|
156
|
+
Enabled: true
|
157
|
+
Style/NumberedParameters: # new in 1.22
|
158
|
+
Enabled: true
|
159
|
+
Style/NumberedParametersLimit: # new in 1.22
|
160
|
+
Enabled: true
|
161
|
+
Style/ObjectThen: # new in 1.28
|
162
|
+
Enabled: true
|
163
|
+
Style/OpenStructUse: # new in 1.23
|
164
|
+
Enabled: true
|
165
|
+
Style/QuotedSymbols: # new in 1.16
|
166
|
+
Enabled: true
|
167
|
+
Style/RedundantArgument: # new in 1.4
|
168
|
+
Enabled: true
|
169
|
+
Style/RedundantInitialize: # new in 1.27
|
170
|
+
Enabled: true
|
171
|
+
Style/RedundantSelfAssignmentBranch: # new in 1.19
|
172
|
+
Enabled: true
|
173
|
+
Style/SelectByRegexp: # new in 1.22
|
174
|
+
Enabled: true
|
175
|
+
Style/StringChars: # new in 1.12
|
176
|
+
Enabled: true
|
177
|
+
Style/SwapValues: # new in 1.1
|
178
|
+
Enabled: true
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
dlss-capistrano-docker (1.0.0)
|
5
|
+
capistrano (~> 3.0)
|
6
|
+
capistrano-one_time_key
|
7
|
+
capistrano-shared_configs
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
airbrussh (1.4.1)
|
13
|
+
sshkit (>= 1.6.1, != 1.7.0)
|
14
|
+
ast (2.4.2)
|
15
|
+
byebug (11.1.3)
|
16
|
+
capistrano (3.17.1)
|
17
|
+
airbrussh (>= 1.0.0)
|
18
|
+
i18n
|
19
|
+
rake (>= 10.0.0)
|
20
|
+
sshkit (>= 1.9.0)
|
21
|
+
capistrano-one_time_key (0.1.0)
|
22
|
+
capistrano (~> 3.0)
|
23
|
+
capistrano-shared_configs (0.2.2)
|
24
|
+
concurrent-ruby (1.1.10)
|
25
|
+
i18n (1.12.0)
|
26
|
+
concurrent-ruby (~> 1.0)
|
27
|
+
json (2.6.2)
|
28
|
+
net-scp (1.2.1)
|
29
|
+
net-ssh (>= 2.6.5)
|
30
|
+
net-ssh (7.0.1)
|
31
|
+
parallel (1.22.1)
|
32
|
+
parser (3.1.2.1)
|
33
|
+
ast (~> 2.4.1)
|
34
|
+
rainbow (3.1.1)
|
35
|
+
rake (13.0.6)
|
36
|
+
regexp_parser (2.5.0)
|
37
|
+
rexml (3.2.5)
|
38
|
+
rubocop (1.36.0)
|
39
|
+
json (~> 2.3)
|
40
|
+
parallel (~> 1.10)
|
41
|
+
parser (>= 3.1.2.1)
|
42
|
+
rainbow (>= 2.2.2, < 4.0)
|
43
|
+
regexp_parser (>= 1.8, < 3.0)
|
44
|
+
rexml (>= 3.2.5, < 4.0)
|
45
|
+
rubocop-ast (>= 1.20.1, < 2.0)
|
46
|
+
ruby-progressbar (~> 1.7)
|
47
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
48
|
+
rubocop-ast (1.21.0)
|
49
|
+
parser (>= 3.1.1.0)
|
50
|
+
ruby-progressbar (1.11.0)
|
51
|
+
sshkit (1.21.3)
|
52
|
+
net-scp (>= 1.1.2)
|
53
|
+
net-ssh (>= 2.8.0)
|
54
|
+
unicode-display_width (2.3.0)
|
55
|
+
|
56
|
+
PLATFORMS
|
57
|
+
x86_64-darwin-21
|
58
|
+
|
59
|
+
DEPENDENCIES
|
60
|
+
bundler
|
61
|
+
byebug
|
62
|
+
dlss-capistrano-docker!
|
63
|
+
rake (>= 12.3.3)
|
64
|
+
rubocop (~> 1.0)
|
65
|
+
|
66
|
+
BUNDLED WITH
|
67
|
+
2.3.22
|
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# dlss-capistrano-docker
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/dlss-capistrano-docker.svg)](https://badge.fury.io/rb/dlss-capistrano-docker)
|
4
|
+
|
5
|
+
This gem provides Capistrano Docker deployment tasks used by Stanford Libraries' Digital Library Systems and Services group.
|
6
|
+
|
7
|
+
It requires that the services to be run on a server be specified by a docker compose configuration file.
|
8
|
+
|
9
|
+
## Included Tasks
|
10
|
+
* `ssh`: establishes an SSH connection to the host running in environment, and changes into the current deployment directory.
|
11
|
+
* `honeybadger:notify`: notifies Honeybadger of deploy using curl (thus, ruby is not required on host).
|
12
|
+
* `docker:login`: log into Docker Hub. Logging in is required to avoid strict image download limits.
|
13
|
+
* `docker:logout`: log out of Docker Hub.
|
14
|
+
* `docker:prune`: prune docker artifacts to avoid filling disk space.
|
15
|
+
* `docker_compose:migrate`: migrate the database.
|
16
|
+
* `docker_compose:seed`: seed the database.
|
17
|
+
* `docker_compose:build`: build images for the services.
|
18
|
+
* `docker_compose:setup_rabbit`: create channel, queues, etc for RabbitMQ.
|
19
|
+
* `docker_compose:restart`: down then up services.
|
20
|
+
* `docker_compose:up`: stop services.
|
21
|
+
* `docker_compose:down`: tear down services.
|
22
|
+
* `docker_compose:copy_assets`: copy assets from a container to the server so they can be served by Apache.
|
23
|
+
* `docker_compose:dereference_linked_files`: turn linked files into actual files.
|
24
|
+
* `docker_compose:dereference_linked_dirs`: turn linked directories into actual directories containing actual files.
|
25
|
+
|
26
|
+
## Hooks
|
27
|
+
Hooks into the Capistrano lifecycle are provided for most of these tasks. These hooks can be controlled with variables, e.g., `docker_hub_use_hooks` to control the hooks for `docker:login` and `docker:logout`.
|
28
|
+
|
29
|
+
In addition to tasks included in this gem, a hook is provided for `shared_configs:update`.
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
For an example of any of the following, see https://github.com/sul-dlss/happy-heron
|
33
|
+
|
34
|
+
### `Gemfile`
|
35
|
+
* Add `gem 'dlss-capistrano-docker', require: false` to the deployment group.
|
36
|
+
* Remove any gems that are removed from `Capfile` below.
|
37
|
+
* Move puma gem from development/test dependencies to the application dependencies. (Puma will be used as the application server instead of Passenger.)
|
38
|
+
|
39
|
+
### `Capfile`
|
40
|
+
* Remove any of the following:
|
41
|
+
```
|
42
|
+
require 'capistrano/bundler'
|
43
|
+
require 'capistrano/rails'
|
44
|
+
require 'capistrano/honeybadger'
|
45
|
+
require 'capistrano/passenger'
|
46
|
+
require 'whenever/capistrano'
|
47
|
+
require 'dlss/capistrano'
|
48
|
+
```
|
49
|
+
* Add `require 'dlss/docker/capistrano`
|
50
|
+
|
51
|
+
### `config/deploy.rb`
|
52
|
+
* For `:linked_files` remove `config/database.yml` and `config/secrets.yml` if present. Both of these will be provided by environment variables.
|
53
|
+
* For `:linked_dirs` remove `tmp/pids`, `tmp/cache`, `tmp/sockets`, `public/system` if present. `log` and `config/settings` should remain.
|
54
|
+
* Remove any sidekiq, sneakers, passenger, whenever, or shared_configs related settings.
|
55
|
+
* Add `set :docker_compose_file, 'docker-compose.prod.yml'` to reference the production docker-compose file.
|
56
|
+
* Optionally, add `set :docker_compose_seed_use_hooks, true` to perform seeding.
|
57
|
+
* Optionally, add `set :docker_compose_rabbitmq_use_hooks, true` to perform Rabbitmq setup.
|
58
|
+
* Note that there are other settings supported by this gem for additional configuration.
|
59
|
+
|
60
|
+
### `config/deploy/<environment>.rb`
|
61
|
+
* Each server should have the `app` role and any roles that correspond with profiles in the docker-compose file. This is what controls what services are run on the server.
|
62
|
+
|
63
|
+
### `config/puma.rb`
|
64
|
+
* Change `RAILS_MAX_THREAD` to `PUMA_MAX_THREAD` and `RAILS_MIN_THREAD` to `PUMA_MIN_THREAD`.
|
65
|
+
* Enable workers with `workers ENV.fetch('PUMA_WORKERS', 2)`
|
66
|
+
* Enable preload with `preload_app!`.
|
67
|
+
|
68
|
+
### `config/schedule.rb`
|
69
|
+
* Add `set :job_template, nil` to execute with sh instead of bash.
|
70
|
+
|
71
|
+
### `Dockerfile`
|
72
|
+
* When possible, base the image on Alpine (e.g., `FROM ruby:3.1-alpine`).
|
73
|
+
* Processes should run as the application user (e.g., `h2`) not root, with user id and group id set to match the server.
|
74
|
+
* If using Whenever, install Supercronic (which does not have to run as root) and write the crontab file during the build with `RUN sh -c 'bundle exec whenever . | tee -a config/crontab'`.
|
75
|
+
* When possible, write to both a log file and stdout.
|
76
|
+
* Precompile assets (`RUN bin/rails assets:precompile`) as part of the build. `SECRET_KEY_BASE` will need to be available for precompiling.
|
77
|
+
|
78
|
+
### `docker-compose.prod.yml`
|
79
|
+
* Duplicate configuration can be shared with fragments (e.g., `&environment` / `*environment`).
|
80
|
+
* The command for a container can be overridden with `command:`, e.g., `command: bin/bundle exec rake sneakers:run 2>&1 | tee -a log/sneakers.log`.
|
81
|
+
* Each service should be assigned to one or more profiles. These correspond to capistrano roles. For example:
|
82
|
+
```
|
83
|
+
profiles:
|
84
|
+
- cron
|
85
|
+
```
|
86
|
+
* Containers should link in the shared logs directory. For example:
|
87
|
+
```
|
88
|
+
volumes:
|
89
|
+
- /opt/app/h2/happy-heron/shared/log:/app/log
|
90
|
+
```
|
91
|
+
* Environment variables provided by the server should be passed through to the container. For example:
|
92
|
+
```
|
93
|
+
environment:
|
94
|
+
- HONEYBADGER_API_KEY
|
95
|
+
```
|
96
|
+
|
97
|
+
### `.dockerignore`
|
98
|
+
Ignore `public.assets`
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
Dir.glob('lib/tasks/*.rake').each { |r| import r }
|
6
|
+
|
7
|
+
begin
|
8
|
+
Bundler.setup(:default, :development)
|
9
|
+
rescue Bundler::BundlerError => e
|
10
|
+
$stderr.puts e.message
|
11
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
12
|
+
exit e.status_code
|
13
|
+
end
|
14
|
+
|
15
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dlss-capistrano-docker"
|
7
|
+
s.version = '1.0.0'
|
8
|
+
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ['Justin Littman']
|
11
|
+
s.email = ['justinlittman@stanford.edu']
|
12
|
+
s.summary = "Capistrano recipes for use in SUL/DLSS projects for docker deployment"
|
13
|
+
s.homepage = 'https://github.com/sul-dlss/dlss-capistrano-docker'
|
14
|
+
s.license = "Apache-2.0"
|
15
|
+
|
16
|
+
s.required_ruby_version = '>= 3.0', '< 4'
|
17
|
+
|
18
|
+
# All dependencies are runtime dependencies, since this gem's "runtime" is
|
19
|
+
# the dependent gem's development-time.
|
20
|
+
s.add_dependency "capistrano", "~> 3.0"
|
21
|
+
s.add_dependency "capistrano-one_time_key"
|
22
|
+
s.add_dependency "capistrano-shared_configs"
|
23
|
+
|
24
|
+
s.add_development_dependency 'bundler'
|
25
|
+
s.add_development_dependency 'byebug'
|
26
|
+
s.add_development_dependency 'rake', '>= 12.3.3'
|
27
|
+
s.add_development_dependency 'rubocop', '~> 1.0'
|
28
|
+
|
29
|
+
s.files = `git ls-files`.split($/)
|
30
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
31
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
32
|
+
s.metadata['rubygems_mfa_required'] = 'true'
|
33
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Capistrano plugin hook to set default values
|
4
|
+
namespace :load do
|
5
|
+
task :defaults do
|
6
|
+
set :docker_prune_use_hooks, fetch(:docker_prune_use_hooks, true)
|
7
|
+
set :docker_hub_use_hooks, fetch(:docker_hub_use_hooks, true)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Integrate hooks into Capistrano
|
12
|
+
namespace :deploy do
|
13
|
+
before :starting, :add_docker_hooks do
|
14
|
+
invoke 'docker:add_prune_hooks' if fetch(:docker_prune_use_hooks)
|
15
|
+
invoke 'docker:add_hub_hooks' if fetch(:docker_hub_use_hooks)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
namespace :docker do
|
20
|
+
task :add_prune_hooks do
|
21
|
+
# Cleaning up docker on start so that images/logs are available for troubleshooting.
|
22
|
+
after 'deploy:starting', 'docker:prune'
|
23
|
+
end
|
24
|
+
|
25
|
+
task :add_hub_hooks do
|
26
|
+
after 'deploy:starting', 'docker:login'
|
27
|
+
after 'deploy:finishing', 'docker:logout'
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Log in to Docker Hub'
|
31
|
+
task :login do
|
32
|
+
on roles(:app) do
|
33
|
+
execute(:docker, 'login', '-u', '$DOCKER_USERNAME', '-p', '$DOCKER_PASSWORD')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Log out of Docker Hub'
|
38
|
+
task :logout do
|
39
|
+
on roles(:app) do
|
40
|
+
execute(:docker, 'logout')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
desc 'Prune unused images/containers'
|
45
|
+
task :prune do
|
46
|
+
on roles(:app) do
|
47
|
+
execute(:docker, 'system', 'prune', '-af')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Capistrano plugin hook to set default values
|
4
|
+
namespace :load do
|
5
|
+
task :defaults do
|
6
|
+
set :docker_compose_file, fetch(:docker_compose_file, 'docker-compose.yml')
|
7
|
+
|
8
|
+
set :docker_compose_migrate_use_hooks, fetch(:docker_compose_migrate_use_hooks, true)
|
9
|
+
set :migration_role, fetch(:migration_role, :db)
|
10
|
+
set :migration_servers, -> { primary(fetch(:migration_role)) }
|
11
|
+
set :migration_command, fetch(:migration_command, 'db:migrate')
|
12
|
+
|
13
|
+
set :docker_compose_seed_use_hooks, fetch(:docker_compose_seed_use_hooks, false)
|
14
|
+
set :seed_command, fetch(:migration_command, 'db:seed')
|
15
|
+
|
16
|
+
set :docker_compose_build_use_hooks, fetch(:docker_compose_build_use_hooks, true)
|
17
|
+
set :build_roles, fetch(:build_roles, [:app])
|
18
|
+
set :dereference_files, fetch(:dereference_files)
|
19
|
+
set :dereference_dirs, fetch(:dereference_dirs, [])
|
20
|
+
|
21
|
+
set :docker_compose_rabbitmq_use_hooks, fetch(:docker_compose_rabbit_use_hooks, false)
|
22
|
+
set :rabbitmq_role, fetch(:rabbitmq_role, :app)
|
23
|
+
set :rabbitmq_servers, -> { primary(fetch(:rabbitmq_role)) }
|
24
|
+
set :rabbitmq_command, fetch(:rabbitmq_command, 'rabbitmq:setup')
|
25
|
+
|
26
|
+
set :docker_compose_restart_use_hooks, fetch(:docker_compose_restart_use_hooks, true)
|
27
|
+
|
28
|
+
set :copy_assets_role, fetch(:copy_assets_role, :app)
|
29
|
+
set :assets_path, fetch(:assets_path, 'public/assets')
|
30
|
+
set :docker_compose_copy_assets_use_hooks, fetch(:docker_compose_copy_assets_use_hooks, true)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Integrate hooks into Capistrano
|
35
|
+
namespace :deploy do
|
36
|
+
before :starting, :add_docker_hooks do
|
37
|
+
invoke 'docker_compose:add_migrate_hooks' if fetch(:docker_compose_migrate_use_hooks)
|
38
|
+
invoke 'docker_compose:add_seed_hooks' if fetch(:docker_compose_seed_use_hooks)
|
39
|
+
invoke 'docker_compose:add_build_hooks' if fetch(:docker_compose_build_use_hooks)
|
40
|
+
invoke 'docker_compose:add_rabbitmq_hooks' if fetch(:docker_compose_rabbitmq_use_hooks)
|
41
|
+
invoke 'docker_compose:add_restart_hooks' if fetch(:docker_compose_restart_use_hooks)
|
42
|
+
invoke 'docker_compose:add_copy_assets_hooks' if fetch(:docker_compose_copy_assets_use_hooks)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
namespace :docker_compose do
|
47
|
+
task :add_migrate_hooks do
|
48
|
+
after 'deploy:publishing', 'docker_compose:migrate'
|
49
|
+
end
|
50
|
+
|
51
|
+
task :add_seed_hooks do
|
52
|
+
after 'deploy:publishing', 'docker_compose:seed'
|
53
|
+
end
|
54
|
+
|
55
|
+
task :add_build_hooks do
|
56
|
+
after 'deploy:updating', 'docker_compose:build'
|
57
|
+
end
|
58
|
+
|
59
|
+
task :add_rabbitmq_hooks do
|
60
|
+
after 'deploy:publishing', 'docker_compose:setup_rabbitmq'
|
61
|
+
end
|
62
|
+
|
63
|
+
task :add_restart_hooks do
|
64
|
+
after 'deploy:publishing', 'docker_compose:restart'
|
65
|
+
end
|
66
|
+
|
67
|
+
task :add_copy_assets_hooks do
|
68
|
+
after 'deploy:publishing', 'docker_compose:copy_assets'
|
69
|
+
end
|
70
|
+
|
71
|
+
desc 'Migrate database'
|
72
|
+
task :migrate do
|
73
|
+
on fetch(:migration_servers) do
|
74
|
+
within current_path do
|
75
|
+
execute(:docker, 'compose', '-f', fetch(:docker_compose_file), 'run', 'app', 'bin/rails',
|
76
|
+
fetch(:migration_command))
|
77
|
+
end
|
78
|
+
info 'Db migrated'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
desc 'Seed database'
|
83
|
+
task :seed do
|
84
|
+
on fetch(:migration_servers) do
|
85
|
+
within current_path do
|
86
|
+
execute(:docker, 'compose', '-f', fetch(:docker_compose_file), 'run', 'app', 'bin/rails',
|
87
|
+
fetch(:seed_command))
|
88
|
+
end
|
89
|
+
info 'Db migrated'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'Build images'
|
94
|
+
# Docker build does not dereference symlinks.
|
95
|
+
task build: [:dereference_linked_files, :dereference_linked_dirs] do
|
96
|
+
on roles(fetch(:build_roles)) do
|
97
|
+
info 'Building images'
|
98
|
+
within release_path do
|
99
|
+
execute(:docker, 'compose', '-f', fetch(:docker_compose_file), 'build')
|
100
|
+
end
|
101
|
+
info 'Docker images built'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
desc 'Setup RabbitMQ'
|
106
|
+
task :setup_rabbitmq do
|
107
|
+
on fetch(:rabbitmq_servers) do
|
108
|
+
within current_path do
|
109
|
+
execute(:docker, 'compose', '-f', fetch(:docker_compose_file), 'run', 'app', 'bin/rake',
|
110
|
+
fetch(:rabbitmq_command))
|
111
|
+
end
|
112
|
+
info 'RabbitMQ setup'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
desc 'Restart containers (down then up)'
|
117
|
+
task restart: [:down, :up]
|
118
|
+
|
119
|
+
desc 'Start containers'
|
120
|
+
task :up do
|
121
|
+
on roles(:app) do |server|
|
122
|
+
cmd = cmd_with_profiles(server)
|
123
|
+
cmd.concat(['up', '-d'])
|
124
|
+
within current_path do
|
125
|
+
execute(*cmd)
|
126
|
+
info 'Containers started'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
desc 'Tear down containers'
|
132
|
+
task :down do
|
133
|
+
on roles(:app) do |server|
|
134
|
+
cmd = cmd_with_profiles(server)
|
135
|
+
cmd.concat(['down'])
|
136
|
+
within current_path do
|
137
|
+
execute(*cmd)
|
138
|
+
info 'Containers down'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
desc 'Copy assets'
|
144
|
+
task :copy_assets do
|
145
|
+
assets_path = fetch(:assets_path)
|
146
|
+
on roles(fetch(:copy_assets_role)) do
|
147
|
+
within current_path do
|
148
|
+
# Can't do a direct copy to public/assets because it is a symlink.
|
149
|
+
execute(:docker, 'compose', '-f', fetch(:docker_compose_file), 'cp',
|
150
|
+
'app:/app/public/assets', '.')
|
151
|
+
execute(:rm, '-fr', "#{assets_path}/*")
|
152
|
+
execute(:mkdir, assets_path)
|
153
|
+
execute(:cp, 'assets/*', "#{assets_path}/")
|
154
|
+
end
|
155
|
+
info 'Assets copied'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
desc 'Dereference linked files'
|
160
|
+
task :dereference_linked_files do
|
161
|
+
dereference_files = fetch(:dereference_files) || fetch(:linked_files, [])
|
162
|
+
next if dereference_files.empty?
|
163
|
+
|
164
|
+
on roles(fetch(:build_roles)) do
|
165
|
+
dereference_files.each do |file|
|
166
|
+
target = release_path.join(file)
|
167
|
+
source = shared_path.join(file)
|
168
|
+
execute :rm, target if test "[ -L #{target} ]"
|
169
|
+
execute :cp, source, target
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
desc 'Dereference linked directories'
|
175
|
+
task :dereference_linked_dirs do
|
176
|
+
dereference_dirs = fetch(:dereference_dirs)
|
177
|
+
next if dereference_dirs.empty?
|
178
|
+
|
179
|
+
on roles(fetch(:build_roles)) do
|
180
|
+
dereference_dirs.each do |dir|
|
181
|
+
target = release_path.join(dir)
|
182
|
+
source = shared_path.join(dir)
|
183
|
+
next unless test "[ -L #{target} ]"
|
184
|
+
|
185
|
+
execute :rm, target
|
186
|
+
execute :cp, '-r', source, target
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def cmd_with_profiles(server)
|
192
|
+
cmd = [:docker, 'compose', '-f', fetch(:docker_compose_file)]
|
193
|
+
server.roles.each do |role|
|
194
|
+
cmd.concat(['--profile', role.to_s])
|
195
|
+
end
|
196
|
+
cmd
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Capistrano plugin hook to set default values
|
4
|
+
namespace :load do
|
5
|
+
task :defaults do
|
6
|
+
set :honeybadger_use_hooks, fetch(:honeybadger_use_hooks, true)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Integrate hooks into Capistrano
|
11
|
+
namespace :deploy do
|
12
|
+
before :starting, :add_honeybadger_hooks do
|
13
|
+
invoke 'honeybadger:add_hooks' if fetch(:honeybadger_use_hooks)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :honeybadger do
|
18
|
+
task :add_hooks do
|
19
|
+
after 'deploy:finishing', 'honeybadger:notify'
|
20
|
+
end
|
21
|
+
|
22
|
+
# Replaces honeybadger:deploy to use curl instead of invoking ruby.
|
23
|
+
# Adapted from https://github.com/honeybadger-io/honeybadger-ruby/blob/master/vendor/capistrano-honeybadger/lib/capistrano/tasks/deploy.cap
|
24
|
+
desc 'Notify Honeybadger of a deploy (using the API via curl)'
|
25
|
+
task notify: %i[deploy:set_current_revision] do
|
26
|
+
fetch(:honeybadger_server) do
|
27
|
+
if (s = primary(:app))
|
28
|
+
set(:honeybadger_server, s.select?({ exclude: :no_release }) ? s : nil)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if (server = fetch(:honeybadger_server))
|
33
|
+
revision = fetch(:current_revision)
|
34
|
+
|
35
|
+
on server do |_host|
|
36
|
+
info 'Notifying Honeybadger of deploy.'
|
37
|
+
|
38
|
+
honeybadger_config = nil
|
39
|
+
within release_path do
|
40
|
+
honeybadger_config = capture(:cat, 'config/honeybadger.yml')
|
41
|
+
end
|
42
|
+
remote_api_key = YAML.safe_load(honeybadger_config)['api_key']
|
43
|
+
remote_api_key = capture(:echo, '$HONEYBADGER_API_KEY') if remote_api_key.nil?
|
44
|
+
|
45
|
+
options = {
|
46
|
+
'deploy[environment]' => fetch(:honeybadger_env, fetch(:rails_env, 'production')),
|
47
|
+
'deploy[local_username]' => fetch(:honeybadger_user, ENV['USER'] || ENV.fetch('USERNAME', nil)),
|
48
|
+
'deploy[revision]' => revision,
|
49
|
+
'deploy[repository]' => fetch(:repo_url),
|
50
|
+
'api_key' => fetch(:honeybadger_api_key, ENV.fetch('HONEYBADGER_API_KEY', nil)) || remote_api_key
|
51
|
+
}
|
52
|
+
data = options.to_a.map { |pair| pair.join('=') }.join('&')
|
53
|
+
execute(:curl, '--no-progress-meter', '--data', "\"#{data}\"", 'https://api.honeybadger.io/v1/deploys')
|
54
|
+
info 'Honeybadger notification complete.'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Capistrano plugin hook to set default values
|
4
|
+
namespace :load do
|
5
|
+
task :defaults do
|
6
|
+
set :shared_configs_use_hooks, fetch(:shared_configs_use_hooks, true)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Integrate hooks into Capistrano
|
11
|
+
namespace :deploy do
|
12
|
+
before :starting, :add_shared_configs_hooks do
|
13
|
+
invoke 'shared_configs:add_hooks' if fetch(:shared_configs_use_hooks)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :shared_configs do
|
18
|
+
task :add_hooks do
|
19
|
+
before 'deploy:updating', 'shared_configs:update'
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
desc 'ssh to the current directory on the server'
|
4
|
+
task :ssh do
|
5
|
+
on roles(:app), primary: true do |host|
|
6
|
+
command = "cd #{fetch(:deploy_to)}/current && exec $SHELL -l"
|
7
|
+
puts command if fetch(:log_level) == :debug
|
8
|
+
exec "ssh -l #{host.user} #{host.hostname} -p #{host.port || 22} -t '#{command}'"
|
9
|
+
end
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dlss-capistrano-docker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Littman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-09-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: capistrano
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: capistrano-one_time_key
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: capistrano-shared_configs
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 12.3.3
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 12.3.3
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- justinlittman@stanford.edu
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".rubocop.yml"
|
120
|
+
- Gemfile
|
121
|
+
- Gemfile.lock
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- dlss-capistrano-docker.gemspec
|
125
|
+
- lib/dlss/docker/capistrano.rb
|
126
|
+
- lib/dlss/docker/capistrano/tasks/docker.rake
|
127
|
+
- lib/dlss/docker/capistrano/tasks/docker_compose.rake
|
128
|
+
- lib/dlss/docker/capistrano/tasks/honeybadger.rake
|
129
|
+
- lib/dlss/docker/capistrano/tasks/shared_configs.rake
|
130
|
+
- lib/dlss/docker/capistrano/tasks/ssh.rake
|
131
|
+
homepage: https://github.com/sul-dlss/dlss-capistrano-docker
|
132
|
+
licenses:
|
133
|
+
- Apache-2.0
|
134
|
+
metadata:
|
135
|
+
rubygems_mfa_required: 'true'
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '3.0'
|
145
|
+
- - "<"
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '4'
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
requirements: []
|
154
|
+
rubygems_version: 3.3.7
|
155
|
+
signing_key:
|
156
|
+
specification_version: 4
|
157
|
+
summary: Capistrano recipes for use in SUL/DLSS projects for docker deployment
|
158
|
+
test_files: []
|