fiver 0.0alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.browserslistrc +1 -0
- data/.gitignore +57 -0
- data/.orchestration.yml +4 -0
- data/.rspec +3 -0
- data/.rspec_status +18 -0
- data/.rubocop.yml +10 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +36 -0
- data/Gemfile.lock +292 -0
- data/LICENSE +7 -0
- data/LICENSE.txt +21 -0
- data/Makefile +27 -0
- data/README.md +11 -0
- data/Rakefile +8 -0
- data/app/assets/config/manifest.js +2 -0
- data/app/assets/images/.keep +0 -0
- data/app/assets/stylesheets/application.css +15 -0
- data/app/channels/application_cable/channel.rb +6 -0
- data/app/channels/application_cable/connection.rb +6 -0
- data/app/controllers/application_controller.rb +4 -0
- data/app/controllers/concerns/.keep +0 -0
- data/app/helpers/application_helper.rb +5 -0
- data/app/javascript/channels/consumer.js +6 -0
- data/app/javascript/channels/index.js +5 -0
- data/app/javascript/packs/application.js +17 -0
- data/app/javascript/packs/hello_react.jsx +26 -0
- data/app/jobs/application_job.rb +9 -0
- data/app/mailers/application_mailer.rb +6 -0
- data/app/models/application_record.rb +6 -0
- data/app/models/concerns/.keep +0 -0
- data/app/views/layouts/application.html.erb +15 -0
- data/app/views/layouts/mailer.html.erb +13 -0
- data/app/views/layouts/mailer.text.erb +1 -0
- data/babel.config.js +87 -0
- data/bin/bundle +114 -0
- data/bin/console +14 -0
- data/bin/rails +9 -0
- data/bin/rake +9 -0
- data/bin/setup +8 -0
- data/bin/spring +17 -0
- data/bin/webpack +18 -0
- data/bin/webpack-dev-server +18 -0
- data/bin/yarn +11 -0
- data/config.ru +7 -0
- data/config/application.rb +18 -0
- data/config/boot.rb +6 -0
- data/config/cable.yml +10 -0
- data/config/credentials.yml.enc +1 -0
- data/config/database.yml +25 -0
- data/config/environment.rb +7 -0
- data/config/environments/development.rb +64 -0
- data/config/environments/production.rb +114 -0
- data/config/environments/test.rb +52 -0
- data/config/initializers/application_controller_renderer.rb +9 -0
- data/config/initializers/assets.rb +16 -0
- data/config/initializers/backtrace_silencers.rb +8 -0
- data/config/initializers/content_security_policy.rb +31 -0
- data/config/initializers/cookies_serializer.rb +7 -0
- data/config/initializers/filter_parameter_logging.rb +6 -0
- data/config/initializers/inflections.rb +17 -0
- data/config/initializers/mime_types.rb +5 -0
- data/config/initializers/wrap_parameters.rb +16 -0
- data/config/locales/en.yml +33 -0
- data/config/puma.rb +40 -0
- data/config/rabbitmq.yml +8 -0
- data/config/routes.rb +5 -0
- data/config/spring.rb +8 -0
- data/config/storage.yml +34 -0
- data/config/unicorn.rb +19 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +3 -0
- data/config/webpack/production.js +5 -0
- data/config/webpack/test.js +5 -0
- data/config/webpacker.yml +97 -0
- data/db/schema.rb +15 -0
- data/db/seeds.rb +8 -0
- data/fiver.gemspec +26 -0
- data/lib/assets/.keep +0 -0
- data/lib/fiver.rb +12 -0
- data/lib/fiver/version.rb +5 -0
- data/lib/tasks/.keep +0 -0
- data/log/.keep +0 -0
- data/orchestration/Dockerfile +34 -0
- data/orchestration/Makefile +511 -0
- data/orchestration/docker-compose.development.yml +14 -0
- data/orchestration/docker-compose.production.yml +33 -0
- data/orchestration/docker-compose.test.yml +14 -0
- data/orchestration/entrypoint.sh +17 -0
- data/package.json +20 -0
- data/postcss.config.js +12 -0
- data/public/404.html +67 -0
- data/public/422.html +67 -0
- data/public/500.html +66 -0
- data/public/apple-touch-icon-precomposed.png +0 -0
- data/public/apple-touch-icon.png +0 -0
- data/public/favicon.ico +0 -0
- data/public/robots.txt +1 -0
- data/storage/.keep +0 -0
- data/tmp/.keep +0 -0
- data/tmp/pids/.keep +0 -0
- data/vendor/.keep +0 -0
- data/yarn.lock +7696 -0
- metadata +148 -0
data/lib/assets/.keep
ADDED
File without changes
|
data/lib/fiver.rb
ADDED
data/lib/tasks/.keep
ADDED
File without changes
|
data/log/.keep
ADDED
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
FROM ruby:2.7.1
|
2
|
+
ARG BUNDLE_BITBUCKET__ORG
|
3
|
+
ARG BUNDLE_GITHUB__COM
|
4
|
+
ARG GIT_COMMIT
|
5
|
+
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
|
6
|
+
&& apt-get update \
|
7
|
+
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
8
|
+
nodejs \
|
9
|
+
gosu \
|
10
|
+
sendmail \
|
11
|
+
&& rm -rf /var/lib/apt/lists/* \
|
12
|
+
&& gem install bundler \
|
13
|
+
&& mkdir /app \
|
14
|
+
&& curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash \
|
15
|
+
&& . /root/.bashrc \
|
16
|
+
&& nvm install 10.13.0 \
|
17
|
+
&& npm config set user 0 \
|
18
|
+
&& npm config set unsafe-perm true \
|
19
|
+
&& npm install -g yarn
|
20
|
+
WORKDIR /app
|
21
|
+
COPY .build/Gemfile .build/Gemfile.lock ./
|
22
|
+
RUN bundle install --without development test --deployment
|
23
|
+
COPY .build/package.json .build/yarn.lock ./
|
24
|
+
RUN . /root/.bashrc ; yarn install
|
25
|
+
ADD .build/context.tar .
|
26
|
+
RUN . /root/.bashrc ; NODE_ENV=production RAILS_ENV=production yarn install && NODE_ENV=production RAILS_ENV=production SECRET_KEY_BASE=abc123 bundle exec rake assets:precompile
|
27
|
+
RUN echo "${GIT_COMMIT}" > /app/GIT_COMMIT
|
28
|
+
HEALTHCHECK --interval=30s \
|
29
|
+
--timeout=30s \
|
30
|
+
--start-period=5s \
|
31
|
+
--retries=3 \
|
32
|
+
CMD ["bundle","exec","rake","orchestration:healthcheck"]
|
33
|
+
ENTRYPOINT ["/app/orchestration/entrypoint.sh"]
|
34
|
+
CMD ["bundle","exec","unicorn","-c","config/unicorn.rb"]
|
@@ -0,0 +1,511 @@
|
|
1
|
+
### Environment setup ###
|
2
|
+
SHELL:=/bin/bash
|
3
|
+
|
4
|
+
TERM ?= 'dumb'
|
5
|
+
pwd:=$(shell pwd)
|
6
|
+
ifdef mounted_orchestration
|
7
|
+
orchestration_dir=$(mounted_orchestration)
|
8
|
+
else
|
9
|
+
orchestration_dir=${pwd}/orchestration
|
10
|
+
endif
|
11
|
+
|
12
|
+
ifdef env_file
|
13
|
+
custom_env_file ?= 1
|
14
|
+
else
|
15
|
+
custom_env_file ?= 0
|
16
|
+
endif
|
17
|
+
|
18
|
+
ifneq (,$(wildcard ${pwd}/config/database.yml))
|
19
|
+
database_enabled = 1
|
20
|
+
else
|
21
|
+
database_enabled = 0
|
22
|
+
endif
|
23
|
+
|
24
|
+
make=$(MAKE) $1
|
25
|
+
orchestration_config_filename:=.orchestration.yml
|
26
|
+
orchestration_config:=${pwd}/${orchestration_config_filename}
|
27
|
+
print_error=printf '${red}\#${reset} '$1 | tee '${stderr}'
|
28
|
+
println_error=$(call print_error,$1'\n')
|
29
|
+
print=printf '${blue}\#${reset} '$1
|
30
|
+
println=$(call print,$1'\n')
|
31
|
+
printraw=printf $1
|
32
|
+
printrawln=$(call printraw,$1'\n')
|
33
|
+
stdout=${pwd}/log/orchestration.stdout.log
|
34
|
+
stderr=${pwd}/log/orchestration.stderr.log
|
35
|
+
log_path_length=$(shell echo "${stdout}" | wc -c)
|
36
|
+
ifndef verbose
|
37
|
+
log_tee:= 2>&1 | tee -a ${stdout}
|
38
|
+
log:= >>${stdout} 2>>${stderr}
|
39
|
+
progress_point:=perl -e 'while( my $$line = <STDIN> ) { printf("."); select()->flush(); }'
|
40
|
+
log_progress:= > >(tee -ai ${stdout} >&1 | ${progress_point}) 2> >(tee -ai ${stderr} 2>&1 | ${progress_point})
|
41
|
+
endif
|
42
|
+
red:=$(shell tput setaf 1)
|
43
|
+
green:=$(shell tput setaf 2)
|
44
|
+
yellow:=$(shell tput setaf 3)
|
45
|
+
blue:=$(shell tput setaf 4)
|
46
|
+
magenta:=$(shell tput setaf 5)
|
47
|
+
cyan:=$(shell tput setaf 6)
|
48
|
+
gray:=$(shell tput setaf 7)
|
49
|
+
reset:=$(shell tput sgr0)
|
50
|
+
tick=[${green}✓${reset}]
|
51
|
+
cross=[${red}✘${reset}]
|
52
|
+
warn=[${yellow}!${reset}]
|
53
|
+
hr=$(call println,"$1$(shell head -c ${log_path_length} < /dev/zero | tr '\0' '=')${reset}")
|
54
|
+
managed_env_tag:=\# -|- ORCHESTRATION
|
55
|
+
standard_env_path:=${pwd}/.env
|
56
|
+
backup_env_path:=${pwd}/.env.orchestration.backup
|
57
|
+
is_managed_env:=$$(test -f '${standard_env_path}' && tail -n 1 '${standard_env_path}') == "${managed_env_tag}"*
|
58
|
+
token:=$(shell cat /dev/urandom | LC_CTYPE=C tr -dc 'a-z0-9' | fold -w8 | head -n1)
|
59
|
+
back_up_env:=( \
|
60
|
+
[ ! -f '${standard_env_path}' ] \
|
61
|
+
|| \
|
62
|
+
( \
|
63
|
+
[ -f '${standard_env_path}' ] \
|
64
|
+
&& cp '${standard_env_path}' '${backup_env_path}' \
|
65
|
+
) \
|
66
|
+
)
|
67
|
+
|
68
|
+
replace_env:=( \
|
69
|
+
( [ "${custom_env_file}" == "0" ] ) \
|
70
|
+
|| \
|
71
|
+
( \
|
72
|
+
[ "${custom_env_file}" == "1" ] \
|
73
|
+
&& ${back_up_env} \
|
74
|
+
&& cp ${env_file} '${standard_env_path}' \
|
75
|
+
&& $(call printraw,'\n${managed_env_tag}') >> '${standard_env_path}' \
|
76
|
+
) \
|
77
|
+
)
|
78
|
+
|
79
|
+
restore_env:=( \
|
80
|
+
( \
|
81
|
+
[[ ! ${is_managed_env} ]] \
|
82
|
+
|| [ ! -f '${backup_env_path}' ] \
|
83
|
+
) \
|
84
|
+
|| \
|
85
|
+
( \
|
86
|
+
[ -f '${backup_env_path}' ] \
|
87
|
+
&& [[ ${is_managed_env} ]] \
|
88
|
+
&& mv '${backup_env_path}' '${standard_env_path}' \
|
89
|
+
) \
|
90
|
+
)
|
91
|
+
|
92
|
+
key_chars:=[a-zA-Z0-9_]
|
93
|
+
censored:=**********
|
94
|
+
censor=s/\(^${key_chars}*$(1)${key_chars}*\)=\(.*\)$$/\1=${censored}/
|
95
|
+
censor_urls:=s|\([a-zA-Z0-9_+]\+://.*:\).*\(@.*\)$$|\1${censored}\2|
|
96
|
+
format_env:=sed '$(call censor,SECRET); \
|
97
|
+
$(call censor,TOKEN); \
|
98
|
+
$(call censor,PRIVATE); \
|
99
|
+
$(call censor,KEY); \
|
100
|
+
$(censor_urls); \
|
101
|
+
/^\s*$$/d; \
|
102
|
+
/^\s*\#/d; \
|
103
|
+
s/\(^[a-zA-Z0-9_]\+\)=/${blue}\1${reset}=/; \
|
104
|
+
s/^/ /; \
|
105
|
+
s/=\(.*\)$$/=${yellow}\1${reset}/' | \
|
106
|
+
sort
|
107
|
+
|
108
|
+
fail=( \
|
109
|
+
$(call printraw,' ${cross}') ; \
|
110
|
+
${restore_env} ; \
|
111
|
+
$(call make,dump) ; \
|
112
|
+
echo ; \
|
113
|
+
$(call println,'Failed. ${cross}') ; \
|
114
|
+
exit 1 \
|
115
|
+
)
|
116
|
+
|
117
|
+
|
118
|
+
ifdef env_file
|
119
|
+
-include ${env_file}
|
120
|
+
else
|
121
|
+
ifneq (${env},test)
|
122
|
+
ifeq (,$(findstring test,$(MAKECMDGOALS)))
|
123
|
+
-include .env
|
124
|
+
endif
|
125
|
+
endif
|
126
|
+
endif
|
127
|
+
|
128
|
+
export
|
129
|
+
|
130
|
+
ifneq (,$(env))
|
131
|
+
# `env` set by current shell.
|
132
|
+
else ifneq (,$(RAILS_ENV))
|
133
|
+
env=$(RAILS_ENV)
|
134
|
+
else ifneq (,$(RACK_ENV))
|
135
|
+
env=$(RACK_ENV)
|
136
|
+
else
|
137
|
+
env=development
|
138
|
+
endif
|
139
|
+
|
140
|
+
DOCKER_TAG ?= latest
|
141
|
+
|
142
|
+
ifneq (,$(wildcard ./Gemfile))
|
143
|
+
rake=RACK_ENV=${env} RAILS_ENV=${env} bundle exec rake
|
144
|
+
else
|
145
|
+
rake=RACK_ENV=${env} RAILS_ENV=${env} rake
|
146
|
+
endif
|
147
|
+
|
148
|
+
ifneq (,$(wildcard ${env_file}))
|
149
|
+
rake_cmd:=${rake}
|
150
|
+
rake=. ${env_file} && ${rake_cmd}
|
151
|
+
endif
|
152
|
+
|
153
|
+
ifeq (,$(findstring serve,$(MAKECMDGOALS)))
|
154
|
+
ifeq (,$(findstring console,$(MAKECMDGOALS)))
|
155
|
+
ifeq (,$(findstring test,$(MAKECMDGOALS)))
|
156
|
+
docker_config:=$(shell RAILS_ENV=development bundle exec rake orchestration:config)
|
157
|
+
docker_organization=$(word 1,$(docker_config))
|
158
|
+
docker_repository=$(word 2,$(docker_config))
|
159
|
+
endif
|
160
|
+
endif
|
161
|
+
endif
|
162
|
+
|
163
|
+
ifeq (,$(project_name))
|
164
|
+
project_base = ${docker_repository}_${env}
|
165
|
+
else
|
166
|
+
project_base := $(project_name)
|
167
|
+
endif
|
168
|
+
|
169
|
+
ifeq (,$(findstring deploy,$(MAKECMDGOALS)))
|
170
|
+
sidecar_suffix := $(shell test -f ${orchestration_dir}/.sidecar && cat ${orchestration_dir}/.sidecar)
|
171
|
+
ifneq (,${sidecar_suffix})
|
172
|
+
sidecar := 1
|
173
|
+
endif
|
174
|
+
|
175
|
+
ifdef sidecar
|
176
|
+
# Set the variable to an empty string so that "#{sidecar-1234}" will
|
177
|
+
# evaluate to "1234" in port mappings.
|
178
|
+
sidecar_compose = sidecar=''
|
179
|
+
ifeq (,${sidecar_suffix})
|
180
|
+
sidecar_suffix := $(call token)
|
181
|
+
_ignore := $(shell echo ${sidecar_suffix} > ${orchestration_dir}/.sidecar)
|
182
|
+
endif
|
183
|
+
|
184
|
+
ifeq (,${sidecar_suffix})
|
185
|
+
$(warning Unable to generate project suffix; project name collisions may occur.)
|
186
|
+
endif
|
187
|
+
compose_project_name = ${project_base}_${sidecar_suffix}
|
188
|
+
else
|
189
|
+
compose_project_name = ${project_base}
|
190
|
+
endif
|
191
|
+
else
|
192
|
+
compose_project_name = ${project_base}
|
193
|
+
endif
|
194
|
+
|
195
|
+
compose_base=env -i \
|
196
|
+
PATH=$(PATH) \
|
197
|
+
HOST_UID=$(shell id -u) \
|
198
|
+
DOCKER_ORGANIZATION="${docker_organization}" \
|
199
|
+
DOCKER_REPOSITORY="${docker_repository}" \
|
200
|
+
COMPOSE_PROJECT_NAME="${compose_project_name}" \
|
201
|
+
${sidecar_compose} \
|
202
|
+
docker-compose \
|
203
|
+
-f ${orchestration_dir}/docker-compose.${env}.yml
|
204
|
+
|
205
|
+
git_branch ?= $(if $(branch),$(branch),$(shell git rev-parse --abbrev-ref HEAD))
|
206
|
+
ifndef dev
|
207
|
+
git_version ?= $(shell git rev-parse --short --verify ${git_branch})
|
208
|
+
else
|
209
|
+
git_version = dev
|
210
|
+
endif
|
211
|
+
|
212
|
+
docker_image=${docker_organization}/${docker_repository}:${git_version}
|
213
|
+
|
214
|
+
compose=${compose_base}
|
215
|
+
random_str=cat /dev/urandom | LC_ALL=C tr -dc 'a-z' | head -c $1
|
216
|
+
|
217
|
+
ifneq (,$(wildcard ${orchestration_dir}/docker-compose.local.yml))
|
218
|
+
compose:=${compose} -f ${orchestration_dir}/docker-compose.local.yml
|
219
|
+
endif
|
220
|
+
|
221
|
+
all: build
|
222
|
+
|
223
|
+
### Container management commands ###
|
224
|
+
|
225
|
+
.PHONY: start
|
226
|
+
ifndef network
|
227
|
+
start: network := ${compose_project_name}
|
228
|
+
endif
|
229
|
+
start: _create-log-directory _clean-logs
|
230
|
+
@$(call print,'${yellow}Starting ${cyan}${env}${yellow} containers${reset} ...')
|
231
|
+
ifeq (${env},$(filter ${env},test development))
|
232
|
+
@${compose} up --detach --force-recreate --renew-anon-volumes --remove-orphans ${services} ${log} || ${fail}
|
233
|
+
@[ -n '${sidecar}' ] && \
|
234
|
+
( \
|
235
|
+
$(call printraw,' ${yellow}(joining dependency network ${green}${network}${yellow})${reset} ... ') ; \
|
236
|
+
docker network connect '${network}' '$(shell hostname)' ${log} \
|
237
|
+
|| ( \
|
238
|
+
$(call println,'') ; \
|
239
|
+
$(call println,'${yellow}Warning${reset}: Unable to join network: "${yellow}${network}${reset}". Container will not be able to connect to dependency services.') ; \
|
240
|
+
$(call print,'You may need to delete "${yellow}orchestration/.sidecar${reset}" to disable sidecar mode if this file was added by mistake.\n...') ; \
|
241
|
+
) \
|
242
|
+
) \
|
243
|
+
|| ( [ -z '${sidecar}' ] || ${fail} )
|
244
|
+
else
|
245
|
+
@${compose} up --detach --scale app=$${instances:-1} ${log} || ${fail}
|
246
|
+
endif
|
247
|
+
@$(call printrawln,' ${green}started${reset} ${tick}')
|
248
|
+
@$(call println,'${yellow}Waiting for services to become available${reset} ...')
|
249
|
+
@$(call make,wait) 2>${stderr} || ${fail}
|
250
|
+
|
251
|
+
.PHONY: start-database
|
252
|
+
start-database:
|
253
|
+
@$(call make,start services='database')
|
254
|
+
|
255
|
+
.PHONY: start-rabbitmq
|
256
|
+
start-rabbitmq:
|
257
|
+
@$(call make,start services='rabbitmq')
|
258
|
+
|
259
|
+
.PHONY: start-app
|
260
|
+
start-app:
|
261
|
+
@$(call make,start services='app')
|
262
|
+
|
263
|
+
|
264
|
+
.PHONY: stop
|
265
|
+
stop: network := ${compose_project_name}
|
266
|
+
stop:
|
267
|
+
@$(call print,'${yellow}Stopping ${cyan}${env}${yellow} containers${reset} ...')
|
268
|
+
@if docker ps --format "{{.ID}}" | grep -q $(shell hostname) ; \
|
269
|
+
then \
|
270
|
+
( docker network disconnect ${network} $(shell hostname) ${log} || : ) \
|
271
|
+
&& \
|
272
|
+
( ${compose} down ${log} || ${fail} ) ; \
|
273
|
+
else \
|
274
|
+
${compose} down ${log} || ${fail} ; \
|
275
|
+
fi
|
276
|
+
@$(call printrawln,' ${green}stopped${reset}. ${tick}')
|
277
|
+
|
278
|
+
.PHONY: logs
|
279
|
+
logs:
|
280
|
+
@${compose} logs -f
|
281
|
+
|
282
|
+
.PHONY: config
|
283
|
+
config:
|
284
|
+
@${compose} config
|
285
|
+
|
286
|
+
.PHONY: compose
|
287
|
+
compose:
|
288
|
+
@echo ${compose}
|
289
|
+
|
290
|
+
### Development/Test Utility Commands
|
291
|
+
|
292
|
+
.PHONY: serve
|
293
|
+
serve: env_file ?= ./.env
|
294
|
+
serve: rails = RAILS_ENV='${env}' bundle exec rails server ${server}
|
295
|
+
serve:
|
296
|
+
@if [ -f "${env_file}" ] ; \
|
297
|
+
then ( \
|
298
|
+
$(call println,'${yellow}Environment${reset}: ${green}${env_file}${reset}') && \
|
299
|
+
cat '${env_file}' | ${format_env} && \
|
300
|
+
$(call printrawln,'') \
|
301
|
+
) ; \
|
302
|
+
fi
|
303
|
+
${rails}
|
304
|
+
|
305
|
+
.PHONY: console
|
306
|
+
console: env_file ?= ./.env
|
307
|
+
console: rails = RAILS_ENV='${env}' bundle exec rails
|
308
|
+
console:
|
309
|
+
@if [ -f "${env_file}" ] ; \
|
310
|
+
then ( \
|
311
|
+
$(call println,'${yellow}Environment${reset}: ${green}${env_file}${reset}') && \
|
312
|
+
cat '${env_file}' | ${format_env} && \
|
313
|
+
$(call printrawln,'') \
|
314
|
+
) ; \
|
315
|
+
fi
|
316
|
+
${rails} console
|
317
|
+
|
318
|
+
.PHONY: test-setup
|
319
|
+
test-setup: env := test
|
320
|
+
test-setup:
|
321
|
+
ifndef light
|
322
|
+
@$(call make,start env=test)
|
323
|
+
ifneq (,$(wildcard config/database.yml))
|
324
|
+
${rake} db:create || :
|
325
|
+
ifneq (,$(wildcard db/structure.sql))
|
326
|
+
${rake} db:structure:load
|
327
|
+
else ifneq (,$(wildcard db/schema.rb))
|
328
|
+
${rake} db:schema:load
|
329
|
+
endif
|
330
|
+
|
331
|
+
${rake} db:migrate
|
332
|
+
endif
|
333
|
+
endif
|
334
|
+
|
335
|
+
.PHONY: dump
|
336
|
+
dump:
|
337
|
+
ifndef verbose
|
338
|
+
@$(call println)
|
339
|
+
@$(call println,'${yellow}Captured${reset} ${green}stdout${reset} ${yellow}and${reset} ${red}stderr${reset} ${yellow}log data [${cyan}${env}${yellow}]${reset}:')
|
340
|
+
@$(call println)
|
341
|
+
@echo
|
342
|
+
@test -f '${stdout}' && ( \
|
343
|
+
$(call hr,${green}) ; \
|
344
|
+
$(call println,'${gray}${stdout}${reset}') ; \
|
345
|
+
$(call hr,${green}) ; \
|
346
|
+
echo ; cat '${stdout}' ; echo ; \
|
347
|
+
$(call hr,${green}) ; \
|
348
|
+
)
|
349
|
+
|
350
|
+
@test -f '${stdout}' && ( \
|
351
|
+
echo ; \
|
352
|
+
$(call hr,${red}) ; \
|
353
|
+
$(call println,'${gray}${stderr}${reset}') ; \
|
354
|
+
$(call hr,${red}) ; \
|
355
|
+
echo ; cat '${stderr}' ; echo ; \
|
356
|
+
$(call hr,${red}) ; \
|
357
|
+
)
|
358
|
+
endif
|
359
|
+
ifneq (,$(findstring deploy,$(MAKECMDGOALS)))
|
360
|
+
@echo ; \
|
361
|
+
$(call hr,${yellow}) ; \
|
362
|
+
$(call println,'${gray}docker-compose logs${reset}') ; \
|
363
|
+
$(call hr,${yellow}) ; \
|
364
|
+
echo
|
365
|
+
@${compose} logs
|
366
|
+
@echo ; \
|
367
|
+
$(call hr,${yellow})
|
368
|
+
endif
|
369
|
+
@$(NOOP)
|
370
|
+
|
371
|
+
.PHONY: image
|
372
|
+
image:
|
373
|
+
@echo ${docker_image}
|
374
|
+
|
375
|
+
### Deployment utility commands ###
|
376
|
+
|
377
|
+
.PHONY: deploy
|
378
|
+
ifdef env_file
|
379
|
+
deploy: env_file_option = --env-file ${env_file}
|
380
|
+
endif
|
381
|
+
deploy: RAILS_ENV := ${env}
|
382
|
+
deploy: RACK_ENV := ${env}
|
383
|
+
deploy: DOCKER_TAG = ${git_version}
|
384
|
+
deploy: base_vars = DOCKER_ORGANIZATION=${docker_organization} DOCKER_REPOSITORY=${docker_repository} DOCKER_TAG=${git_version}
|
385
|
+
deploy: compose_deploy := ${base_vars} COMPOSE_PROJECT_NAME=${project_base} HOST_UID=$(shell id -u) docker-compose ${env_file_option} --project-name ${project_base} -f orchestration/docker-compose.production.yml
|
386
|
+
deploy: compose_config := ${compose_deploy} config
|
387
|
+
deploy: deploy_cmd := echo "$${config}" | ssh "${manager}" "/bin/bash -lc 'cat | docker stack deploy --prune --with-registry-auth -c - ${project_base}'"
|
388
|
+
deploy: out_of_sequence_error := rpc error: code = Unknown desc = update out of sequence
|
389
|
+
deploy: retry_message := ${yellow}Detected Docker RPC error: ${red}${out_of_sequence_error}${yellow}. Retrying in
|
390
|
+
deploy:
|
391
|
+
ifndef manager
|
392
|
+
@$(call println_error,'Missing `manager` parameter: `make deploy manager=swarm-manager.example.com`') ; exit 1
|
393
|
+
endif
|
394
|
+
@$(call println,'${yellow}Deploying ${green}${env} ${yellow}stack via ${green}${manager} ${yellow}as ${green}${project_base}${reset} ...') && \
|
395
|
+
( \
|
396
|
+
$(call println,'${yellow}Deployment environment${reset}:') && \
|
397
|
+
( test -f '${env_file}' && cat '${env_file}' | ${format_env} || : ) && \
|
398
|
+
$(call println,'') && \
|
399
|
+
$(call println,'${yellow}Application image${reset}: ${cyan}${docker_image}${reset}') && \
|
400
|
+
export config="$$(${compose_config} 2>${stderr})" ; \
|
401
|
+
config_exit_code=$$? ; \
|
402
|
+
if [[ "$${config_exit_code}" != "0" ]]; then exit ${config_exit_code}; fi ; \
|
403
|
+
output="$$(${deploy_cmd} | tee)" ; \
|
404
|
+
deploy_exit_code=$$? ; \
|
405
|
+
if [[ "$${deploy_exit_code}" == 0 ]] ; then exit 0 ; fi ; \
|
406
|
+
if ! echo "$${output}" | grep -q '${out_of_sequence_error}' ; then exit ${deploy_exit_code} ; fi ; \
|
407
|
+
retry_in="$$(( 10 + RANDOM % 50 ))" ; \
|
408
|
+
echo "${retry_message} ${green}$${retry_in} ${yellow}seconds.${reset}" ; \
|
409
|
+
sleep "$${retry_in}" ; \
|
410
|
+
${deploy_cmd} \
|
411
|
+
) \
|
412
|
+
|| ${fail}
|
413
|
+
|
414
|
+
@$(call println,'${yellow}Deployment${reset} ${green}complete${reset}. ${tick}')
|
415
|
+
|
416
|
+
.PHONY: rollback
|
417
|
+
ifndef service
|
418
|
+
rollback: service = app
|
419
|
+
endif
|
420
|
+
rollback:
|
421
|
+
ifndef manager
|
422
|
+
@$(call println_error,'Missing `manager` parameter: `make deploy manager=swarm-manager.example.com`') ; exit 1
|
423
|
+
endif
|
424
|
+
@$(call println,'${yellow}Rolling back${reset} ${green}${compose_project_name}_${service}${reset} ${yellow}via${reset} ${green}${manager}${reset} ...')
|
425
|
+
@ssh "${manager}" 'docker service rollback --detach "${compose_project_name}_${service}"' ${log} || ${fail}
|
426
|
+
@$(call println,'${yellow}Rollback request${reset} ${green}complete${reset}. ${tick}')
|
427
|
+
|
428
|
+
### Service healthcheck commands ###
|
429
|
+
|
430
|
+
.PHONY: wait
|
431
|
+
wait:
|
432
|
+
@${rake} orchestration:wait
|
433
|
+
@$(call println,'${yellow}All services${reset} ${green}ready${reset}. ${tick}')
|
434
|
+
|
435
|
+
## Generic Listener healthcheck for TCP services ##
|
436
|
+
|
437
|
+
wait-listener:
|
438
|
+
@${rake} orchestration:listener:wait service=${service} sidecar=${sidecar}
|
439
|
+
|
440
|
+
### Docker build commands ###
|
441
|
+
|
442
|
+
.PHONY: build
|
443
|
+
build: build_dir = ${orchestration_dir}/.build
|
444
|
+
build: context = ${build_dir}/context.tar
|
445
|
+
build: _create-log-directory check-local-changes
|
446
|
+
@$(call print,'${yellow}Preparing build context from${reset} ${cyan}${git_branch}:${git_version}${reset} ... ')
|
447
|
+
@mkdir -p ${orchestration_dir}/.build ${log} || ${fail}
|
448
|
+
ifndef dev
|
449
|
+
@git show ${git_branch}:./Gemfile > ${orchestration_dir}/.build/Gemfile 2>${stderr} || ${fail}
|
450
|
+
@git show ${git_branch}:./Gemfile.lock > ${orchestration_dir}/.build/Gemfile.lock 2>${stderr} || ${fail}
|
451
|
+
@git show ${git_branch}:./package.json > ${orchestration_dir}/.build/package.json 2>${stderr} || ${fail}
|
452
|
+
@git show ${git_branch}:./yarn.lock > ${orchestration_dir}/.build/yarn.lock 2>${stderr} || ${fail}
|
453
|
+
@git archive --format 'tar' -o '${context}' '${git_branch}' ${log} || ${fail}
|
454
|
+
else
|
455
|
+
@tar -cvf '${context}' . ${log} || ${fail}
|
456
|
+
endif
|
457
|
+
@$(call printrawln,'${green}complete.${reset} ${tick}')
|
458
|
+
ifdef include
|
459
|
+
@$(call print,'${yellow}Including files from:${reset} ${cyan}${include}${reset} ...')
|
460
|
+
@(while read line; do \
|
461
|
+
export line; \
|
462
|
+
include_dir="${build_dir}/$$(dirname "$${line}")/" && \
|
463
|
+
mkdir -p "$${include_dir}" && cp "$${line}" "$${include_dir}" \
|
464
|
+
&& (cd '${orchestration_dir}/.build/' && tar rf 'context.tar' "$${line}"); \
|
465
|
+
done < '${include}') ${log} || ${fail}
|
466
|
+
@$(call printrawln,' ${green}complete.${reset} ${tick}')
|
467
|
+
endif
|
468
|
+
ifdef sidecar
|
469
|
+
# Assume we are in a line-buffered environment (e.g. Jenkins)
|
470
|
+
@$(call println,'${yellow}Building image${reset} ...')
|
471
|
+
else
|
472
|
+
@$(call print,'${yellow}Building image${reset} ...')
|
473
|
+
endif
|
474
|
+
@docker build \
|
475
|
+
--build-arg BUNDLE_GITHUB__COM \
|
476
|
+
--build-arg BUNDLE_BITBUCKET__ORG \
|
477
|
+
--build-arg GIT_COMMIT='${git_version}' \
|
478
|
+
-t ${docker_organization}/${docker_repository} \
|
479
|
+
-t ${docker_organization}/${docker_repository}:${git_version} \
|
480
|
+
${orchestration_dir}/ ${log_progress} || ${fail}
|
481
|
+
@$(call printrawln,' ${green}complete${reset}. ${tick}')
|
482
|
+
@$(call println,'[${green}tag${reset}] ${cyan}${docker_organization}/${docker_repository}${reset}')
|
483
|
+
@$(call println,'[${green}tag${reset}] ${cyan}${docker_organization}/${docker_repository}:${git_version}${reset}')
|
484
|
+
|
485
|
+
.PHONY: push
|
486
|
+
push: _create-log-directory
|
487
|
+
@$(call print,'${yellow}Pushing${reset} ${cyan}${docker_image}${reset} ...')
|
488
|
+
@docker push ${docker_image} ${log_progress} || ${fail}
|
489
|
+
@$(call printrawln,' ${green}complete${reset}. ${tick}')
|
490
|
+
|
491
|
+
.PHONY: check-local-changes
|
492
|
+
check-local-changes:
|
493
|
+
ifndef dev
|
494
|
+
@if [[ ! -z "$$(git status --porcelain)" ]] ; \
|
495
|
+
then \
|
496
|
+
$(call println,'${red}You have uncommitted changes which will not be included in your build:${reset}') ; \
|
497
|
+
git status --porcelain ; \
|
498
|
+
$(call println,'${yellow}Use ${cyan}make build dev=1${reset} ${yellow}to include these files.${reset}\n') ; \
|
499
|
+
fi
|
500
|
+
endif
|
501
|
+
|
502
|
+
### Internal Commands ###
|
503
|
+
#
|
504
|
+
.PHONY: _clean-logs
|
505
|
+
_clean-logs:
|
506
|
+
@rm -f '${stdout}' '${stderr}'
|
507
|
+
@touch '${stdout}' '${stderr}'
|
508
|
+
|
509
|
+
.PHONY: _create-log-directory
|
510
|
+
_create-log-directory:
|
511
|
+
@mkdir -p log
|