sombrero 0.0.1 → 0.0.2

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Rakefile +1 -2
  4. data/app/.gitignore +6 -0
  5. data/app/.pryrc +1 -0
  6. data/app/Gemfile +6 -0
  7. data/app/Rakefile +1 -0
  8. data/app/base/base_controller.rb +3 -0
  9. data/app/base/boot.rb +2 -0
  10. data/app/base/helpers/application_helpers.rb +1 -0
  11. data/app/base/load_controllers.rb +2 -0
  12. data/app/base/rtcp_controller.rb +22 -0
  13. data/app/config/config.rb +11 -0
  14. data/app/config/config.yml +11 -0
  15. data/app/config/env/development.yml +0 -0
  16. data/app/config/env/production.yml +0 -0
  17. data/app/config/env/stage.yml +0 -0
  18. data/app/config/env/test.yml +0 -0
  19. data/app/config.ru +3 -0
  20. data/app/core/Gemfile +5 -0
  21. data/app/core/boot.rb +17 -0
  22. data/app/core/client/activity_observer.coffee +37 -0
  23. data/app/core/client/api.coffee +248 -0
  24. data/app/core/client/channels.coffee +37 -0
  25. data/app/core/client/load.coffee +20 -0
  26. data/app/core/client/page.coffee +68 -0
  27. data/app/core/client/polyfills/array.compact.coffee +4 -0
  28. data/app/core/client/polyfills/array.compact_join.coffee +4 -0
  29. data/app/core/client/polyfills/number.to_money.coffee +3 -0
  30. data/app/core/client/polyfills/string.capitalize.coffee +4 -0
  31. data/app/core/client/polyfills/string.strip.coffee +5 -0
  32. data/app/core/client/polyfills.coffee +6 -0
  33. data/app/core/client/render.coffee +57 -0
  34. data/app/core/client/util/alert.coffee +50 -0
  35. data/app/core/client/util/datetime.coffee +47 -0
  36. data/app/core/client/util.coffee +38 -0
  37. data/app/core/generate_controllers_map.rb +4 -0
  38. data/app/core/generate_webpack_setup.rb +4 -0
  39. data/app/core/load.rb +5 -0
  40. data/app/core/load_controllers.rb +16 -0
  41. data/app/package.json +5 -0
  42. data/app/webpack.config.js +51 -0
  43. data/bin/sombrero +5 -0
  44. data/docker/Dockerfile +5 -0
  45. data/docker/base/Dockerfile +3 -0
  46. data/docker/base/build +10 -0
  47. data/docker/base/build.sh +25 -0
  48. data/docker/cleanup +7 -0
  49. data/docker/run +68 -0
  50. data/docker/skel/build.sh +1 -0
  51. data/docker/skel/config.yml +24 -0
  52. data/docker/skel/prepare_build.sh +5 -0
  53. data/docker/skel/start.sh +1 -0
  54. data/docker/start +7 -0
  55. data/lib/sombrero/{version.rb → app.rb} +3 -1
  56. data/lib/sombrero/base_controller.rb +5 -0
  57. data/lib/sombrero/cli/app/install.rb +38 -0
  58. data/lib/sombrero/cli/app/update.rb +20 -0
  59. data/lib/sombrero/cli/app.rb +10 -0
  60. data/lib/sombrero/cli/docker/build.rb +170 -0
  61. data/lib/sombrero/cli/docker/install.rb +23 -0
  62. data/lib/sombrero/cli/docker.rb +14 -0
  63. data/lib/sombrero/cli.rb +128 -0
  64. data/lib/sombrero/rtcp_controller.rb +93 -0
  65. data/lib/sombrero.rb +110 -2
  66. data/sombrero.gemspec +6 -1
  67. metadata +91 -4
@@ -0,0 +1,50 @@
1
+ _ =
2
+ isObject: require('lodash/isObject')
3
+ isFunction: require('lodash/isFunction')
4
+ merge: require('lodash/merge')
5
+ #end
6
+
7
+ require 'sweetalert/dist/sweetalert.css'
8
+ Alert = require('sweetalert')
9
+
10
+
11
+ Alert.setDefaults
12
+ allowEscapeKey: false
13
+ allowOutsideClick: false
14
+ #end
15
+
16
+
17
+ module.exports =
18
+ alert: Alert
19
+
20
+ error: (text, opts = {}) ->
21
+ if _.isObject(text)
22
+ [text, opts] = [null, text]
23
+ Alert(_.merge({type: 'error', title: 'Error', text: text}, opts))
24
+ #end
25
+
26
+
27
+ warning: (title, opts = {}) ->
28
+ if _.isObject(title)
29
+ [title, opts] = [null, title]
30
+ Alert(_.merge({type: 'warning', title: title, text: null}, opts))
31
+ #end
32
+
33
+
34
+ success: (title = 'Done!', opts = {}) ->
35
+ if _.isObject(title)
36
+ [title, opts] = [null, title]
37
+ Alert(_.merge({title: title, text: null, showConfirmButton: false, timer: 1000, type: 'success'}, opts))
38
+ #end
39
+
40
+
41
+ confirm: (title, opts, cb) ->
42
+ if _.isFunction(title)
43
+ [title, opts, cb] = [null, {}, title]
44
+ else if _.isFunction(opts)
45
+ [opts, cb] = [null, opts]
46
+ title ||= 'This action is irreversible! Continue?'
47
+ Alert(_.merge({title: title, type: 'warning', showCancelButton: true}, opts), cb)
48
+ #end
49
+
50
+ #end
@@ -0,0 +1,47 @@
1
+ Moment = require('moment')
2
+
3
+ current_year = ->
4
+ new Date().getFullYear()
5
+ #end
6
+
7
+ Api =
8
+
9
+ date_format: (x, skip_current_year = false) ->
10
+ date = Moment(x)
11
+ if skip_current_year && time.year() == current_year()
12
+ date.format('MMM Do')
13
+ else
14
+ date.format('MMM Do YYYY')
15
+ #end
16
+
17
+
18
+ datetime_format: (x, skip_current_year = false) ->
19
+ time = Moment(x)
20
+ if skip_current_year && time.year() == current_year()
21
+ time.format('MMMM D, h:mmA')
22
+ else
23
+ time.format('MMMM D YYYY, h:mmA')
24
+ #end
25
+
26
+
27
+ time_format: (x) ->
28
+ Moment(x).format('HH:mm')
29
+ #end
30
+
31
+
32
+ relative_time_format: (x) ->
33
+ return '' unless x
34
+ now = Moment()
35
+ _then = Moment(x)
36
+ diff = now.diff(_then, 'seconds')
37
+
38
+ if diff < 86400
39
+ _then.fromNow()
40
+ else if diff < 172800
41
+ _then.calendar(now)
42
+ else
43
+ Api.datetime_format(x)
44
+ #end
45
+ #end
46
+
47
+ module.exports = Api
@@ -0,0 +1,38 @@
1
+ module.exports =
2
+
3
+ generate_uuid: ->
4
+ 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace /[xy]/g, (c) ->
5
+ v = r = Math.random() * 16|0
6
+ v = (r&0x3|0x8) if c == 'x'
7
+ v.toString(16)
8
+ #end
9
+
10
+
11
+ shorten: (text, max_length = 50) ->
12
+ return unless text
13
+ text[0 .. max_length] + (if text.length > max_length then '...' else '')
14
+ #end
15
+
16
+
17
+ scroll_top: ->
18
+ window.scrollTo(0, 0)
19
+ #end
20
+
21
+
22
+ reload: ->
23
+ window.location.reload()
24
+ #end
25
+
26
+
27
+ popup: (url, width, height) ->
28
+ width ||= 800
29
+ height ||= 600
30
+ left = (screen.width / 2) - (width / 2)
31
+ top = (screen.height / 2) - (height / 2)
32
+ window.open url, '_blank', 'menubar=no' +
33
+ ',width=' + width +
34
+ ',height=' + height +
35
+ ',left=' + left +
36
+ ',top=' + top
37
+ #end
38
+ #end
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../load', __FILE__)
3
+
4
+ Sombrero.generate_controllers_map(File.expand_path('../..', __FILE__))
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../load', __FILE__)
3
+
4
+ Sombrero.generate_webpack_setup(File.expand_path('../..', __FILE__))
data/app/core/load.rb ADDED
@@ -0,0 +1,5 @@
1
+ # DO NOT EDIT THIS FILE, all updates will be lost on next update.
2
+ # edit base/load.rb instead.
3
+
4
+ require File.expand_path('../boot', __FILE__)
5
+ require File.expand_path('../load_controllers', __FILE__)
@@ -0,0 +1,16 @@
1
+ # DO NOT EDIT THIS FILE, all updates will be lost on next update.
2
+ # edit base/load_controllers.rb instead.
3
+
4
+ Dir.chdir File.expand_path('../..', __FILE__) do
5
+
6
+ require './base/base_controller'
7
+ require './base/rtcp_controller'
8
+
9
+ %w[
10
+ **/server.rb
11
+ ].each_with_object([]) {|f,o| o.concat(Dir["./base/api/#{f}"])}.sort {|a,b|
12
+ a.split(/\/+/).size <=> b.split(/\/+/).size
13
+ }.each {|f| require(f)}
14
+
15
+ require './base/load_controllers'
16
+ end
data/app/package.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {
3
+
4
+ }
5
+ }
@@ -0,0 +1,51 @@
1
+ var webpack = require('webpack'),
2
+ fs = require('fs'),
3
+ child_process = require('child_process')
4
+ ;
5
+
6
+ if (process.env.APP_ENV == 'development') {
7
+ console.log('Generating controllers map...');
8
+ child_process.execSync('./core/generate_controllers_map.rb');
9
+ console.log('Generating webpack setup...');
10
+ child_process.execSync('./core/generate_webpack_setup.rb');
11
+ }
12
+
13
+ var setup = JSON.parse(fs.readFileSync('./webpack_setup.json'));
14
+ console.log(JSON.stringify(setup, null, 2))
15
+
16
+ module.exports = {
17
+ entry: setup.entries,
18
+ output: {
19
+ path: [setup.path, setup.url].join('/'),
20
+ filename: '[name].js',
21
+ publicPath: setup.url + '/', // trailing slash required
22
+ libraryTarget: 'commonjs2'
23
+ },
24
+ module: {
25
+ loaders: [
26
+ // { test: /\.coffee$/, loader: 'coffee-loader' },
27
+ // { test: /\.css$/, loader: 'style-loader!css-loader' },
28
+ // { test: /\.json$/, loader: 'json-loader' },
29
+ // { test: /\.otf($|\?)/, loader: require.resolve('file-loader') },
30
+ // { test: /\.ttf($|\?)/, loader: require.resolve('file-loader') },
31
+ // { test: /\.eot($|\?)/, loader: require.resolve('file-loader') },
32
+ // { test: /\.svg($|\?)/, loader: require.resolve('file-loader') },
33
+ // { test: /\.png($|\?)/, loader: require.resolve('url-loader') + '?limit=10000&mimetype=image/png' },
34
+ // { test: /\.jpg($|\?)/, loader: require.resolve('file-loader') },
35
+ // { test: /\.gif($|\?)/, loader: require.resolve('file-loader') },
36
+ // { test: /\.woff[2]?($|\?)/, loader: require.resolve('url-loader') + '?limit=10000&mimetype=application/font-woff' },
37
+ ]
38
+ },
39
+ resolve: {
40
+ extensions: ['', '.js', '.css', '.json', '.coffee', '.html'],
41
+ alias: {
42
+ core: __dirname + '/core/client',
43
+ base: __dirname + '/base',
44
+ api: __dirname + '/base/api',
45
+ }
46
+ },
47
+ plugins: [
48
+ new webpack.optimize.DedupePlugin(),
49
+ new webpack.optimize.CommonsChunkPlugin('core', 'core.js'),
50
+ ]
51
+ }
data/bin/sombrero CHANGED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.expand_path('../../lib', __FILE__))
3
+ require 'sombrero'
4
+ require 'sombrero/cli'
5
+ Sombrero::CLI.new($*)
data/docker/Dockerfile ADDED
@@ -0,0 +1,5 @@
1
+ FROM sombrero/base
2
+ COPY start /
3
+ COPY build /build
4
+ RUN sh /build/build && sh /build/cleanup && mkdir /app
5
+ CMD sh /start
@@ -0,0 +1,3 @@
1
+ FROM alpine
2
+ COPY build.sh /
3
+ RUN sh /build.sh && rm -f /build.sh
data/docker/base/build ADDED
@@ -0,0 +1,10 @@
1
+ set -e
2
+
3
+ image="sombrero/base"
4
+
5
+ cd "$(cd $(dirname $0); pwd)"
6
+ docker build -t $image --force-rm --no-cache .
7
+
8
+ if [ "$1" = "-p" ]; then
9
+ docker push $image
10
+ fi
@@ -0,0 +1,25 @@
1
+ #/usr/bin/env sh
2
+
3
+ set -e
4
+
5
+ for e in $(getent passwd | cut -d: -f1); do
6
+ [[ "$e" = "root" || "$e" = "nobody" ]] || ! deluser "$e"
7
+ done
8
+
9
+ for e in $(getent group | cut -d: -f1); do
10
+ [[ "$e" = "root" || "$e" = "nobody" ]] || ! delgroup "$e"
11
+ done
12
+
13
+ echo "http://dl-4.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
14
+
15
+ apk update
16
+ apk upgrade
17
+
18
+ apk add build-base runit nmap-ncat libxml2 libxml2-dev libxslt libxslt-dev \
19
+ ruby ruby-dev ruby-irb ruby-io-console ruby-bigdecimal \
20
+ nodejs nodejs-dev python git \
21
+ redis libpq postgresql-dev \
22
+ imagemagick imagemagick-dev
23
+
24
+ curl -fsSL curl.haxx.se/ca/cacert.pem -o "$(ruby -ropenssl -e 'puts OpenSSL::X509::DEFAULT_CERT_FILE')"
25
+ echo 'gem: --no-ri --no-rdoc' > /root/.gemrc
data/docker/cleanup ADDED
@@ -0,0 +1,7 @@
1
+ set -e
2
+
3
+ apk del build-base libxml2-dev libxslt-dev \
4
+ ruby-dev postgresql-dev imagemagick-dev \
5
+ nodejs-dev python git
6
+
7
+ rm -rf /var/cache/apk/*
data/docker/run ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bash
2
+
3
+ run() {
4
+ echo -e "\n$ $@"
5
+ "$@"
6
+ }
7
+
8
+ container_is_built() {
9
+ [[ -n $(docker ps -a | grep -E "\s$CONTAINER_NAME\s") ]]
10
+ }
11
+
12
+ container_is_running() {
13
+ [[ -n $(docker ps | grep -E "\s$CONTAINER_NAME\s") ]]
14
+ }
15
+
16
+ stop_container() {
17
+ run docker stop $CONTAINER_NAME
18
+ }
19
+
20
+ remove_container() {
21
+ run docker rm $CONTAINER_NAME
22
+ }
23
+
24
+ env_prompt() {
25
+ read APP_ENV
26
+ [ "$(echo " {environments} " | grep -E "\s$APP_ENV\s")" = "" ] && env_prompt
27
+ }
28
+
29
+ if [ "$APP_ENV" = "" ]; then
30
+ echo "APP_ENV not set, please use one of"
31
+ echo "{environments}"
32
+ echo -n "> "
33
+ env_prompt
34
+ fi
35
+
36
+ set -e
37
+
38
+ {container_definitions}
39
+
40
+ if [ "$CONTAINER_NAME" = "" ]; then
41
+ echo -e "\n\t::: $APP_ENV environment not supported. Use one of: {environments} :::\n"
42
+ exit 1
43
+ fi
44
+
45
+ APP_UID="$(id -u)"
46
+ APP_GID="$(id -g)"
47
+ APP_DIR="$(cd "$(dirname ${BASH_SOURCE[0]})/{script_path_traversal}"; pwd)"
48
+
49
+ if [ "$APP_UID" = "0" ]; then
50
+ echo -e "\n\t::: No superpowers accepted here! Run this as a regular user :::\n"
51
+ exit 1
52
+ fi
53
+
54
+ run docker pull {image}
55
+ container_is_running && stop_container
56
+ container_is_built && remove_container
57
+
58
+ run docker run \
59
+ --name "$CONTAINER_NAME" \
60
+ -e APP_ENV="$APP_ENV" \
61
+ -e APP_UID="$APP_UID" \
62
+ -e APP_GID="$APP_GID" \
63
+ -e LANG="en_US.UTF-8" \
64
+ -e LC_ALL="en_US.UTF-8" \
65
+ -e LC_TYPE="en_US.UTF-8" \
66
+ -v "$APP_DIR":/app \
67
+ {run_opts} {image}
68
+ echo
@@ -0,0 +1 @@
1
+ # running inside container.
@@ -0,0 +1,24 @@
1
+ # a image with this name will be built (see prepare_build.sh and build.sh)
2
+ IMAGE_NAME:
3
+
4
+ # the name of container to be run on your server(s).
5
+ # name depends on APP_ENV variable.
6
+ # you can add/remove environments but at least one is required.
7
+ CONTAINER_NAME:
8
+ development:
9
+ test:
10
+ stage:
11
+ production:
12
+
13
+ # path to app.
14
+ # should be absolute or relative to this file.
15
+ APP_DIR:
16
+
17
+ # a file with this name will be generated and installed inside APP_DIR.
18
+ RUN_SCRIPT: docker/run
19
+
20
+ # options passed to `docker build`
21
+ BUILD_OPTS: --force-rm --no-cache
22
+
23
+ # options passed to `docker run`
24
+ RUN_OPTS: -d --restart always
@@ -0,0 +1,5 @@
1
+ # running before image building started.
2
+ # will run inside building dir so copy into ./ any files you need for building.
3
+ # APP_DIR variable points to your app directory
4
+ # so use it to copy any files from your app into building dir.
5
+ # running outside container, e.g. on your dev machine.
@@ -0,0 +1 @@
1
+ # start your app
data/docker/start ADDED
@@ -0,0 +1,7 @@
1
+ set -e
2
+
3
+ [ "$(getent group $APP_GID)" = "" ] && addgroup -g $APP_GID app
4
+
5
+ [ "$(getent passwd $APP_UID)" = "" ] && adduser -D -u $APP_UID -G app app
6
+
7
+ {start}
@@ -1,3 +1,5 @@
1
1
  module Sombrero
2
- VERSION = "0.1.0"
2
+ class App
3
+
4
+ end
3
5
  end
@@ -0,0 +1,5 @@
1
+ module Sombrero
2
+ class BaseController < RocketIO::Controller
3
+
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ module Sombrero
2
+ class CLI
3
+ class App
4
+ class Install
5
+ include InstallHelpers
6
+
7
+ def initialize dir, namespace
8
+ ensure_dirname_exists(dir)
9
+ assert_installable_dir(dir)
10
+ install(dir, namespace)
11
+ end
12
+
13
+ def install dir, namespace
14
+ src = dir.to_path == '.' ? BASE_DIR.to_path + '/.' : BASE_DIR
15
+ FileUtils.cp_r(src, dir)
16
+ FileUtils.chmod('+x', dir / 'core/generate_webpack_setup.rb')
17
+ FileUtils.chmod('+x', dir / 'core/generate_controllers_map.rb')
18
+ if namespace
19
+ %w[
20
+ base/base_controller.rb
21
+ base/rtcp_controller.rb
22
+ config/config.rb
23
+ ].each do |file|
24
+ code = File.read(dir / file)
25
+ File.open dir / file, 'w' do |f|
26
+ f.puts "module #{namespace}"
27
+ code.split("\n").each {|l| f.puts " #{l}"}
28
+ f.puts "end"
29
+ end
30
+ end
31
+ end
32
+ puts "Done. All files installed into #{dir}"
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ module Sombrero
2
+ class CLI
3
+ class App
4
+ class Update
5
+
6
+ def initialize dir
7
+ assert_is_a_sombrero_dir(dir)
8
+ end
9
+
10
+ def assert_is_a_sombrero_dir dir
11
+
12
+ end
13
+
14
+ def update
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ module Sombrero
2
+ class CLI
3
+ class App
4
+ BASE_DIR = (Sombrero::BASE_DIR / 'app').freeze
5
+ end
6
+ end
7
+ end
8
+
9
+ require 'sombrero/cli/app/install'
10
+ require 'sombrero/cli/app/update'
@@ -0,0 +1,170 @@
1
+ module Sombrero
2
+ class CLI
3
+ module Docker
4
+ class Build
5
+
6
+ def initialize dir, args
7
+ check_working_dir(dir)
8
+
9
+ Dir.chdir dir do
10
+ check_config_file
11
+
12
+ config = load_config
13
+ validate_config(config)
14
+
15
+ build_dir = Pathname.new(File.expand_path('__tmpbuildir__'))
16
+
17
+ prepare_build_dir(build_dir)
18
+
19
+ install_files(build_dir)
20
+
21
+ app_dir = Pathname.new(File.expand_path(config['APP_DIR']))
22
+
23
+ unless skip_build?(args)
24
+ prepare_build(build_dir, app_dir)
25
+
26
+ image_built = build_image(build_dir, config['IMAGE_NAME'], config['BUILD_OPTS'])
27
+
28
+ if image_built && push_opted?(args)
29
+ push_image(config['IMAGE_NAME'])
30
+ end
31
+ end
32
+
33
+ install_run_script(app_dir, *config.values_at('IMAGE_NAME', 'CONTAINER_NAME', 'RUN_SCRIPT', 'RUN_OPTS'))
34
+
35
+ FileUtils.rm_rf(build_dir)
36
+ end
37
+ end
38
+
39
+ def push_opted? args
40
+ args.find {|a| a == '-p'}
41
+ end
42
+
43
+ def skip_build? args
44
+ args.find {|a| a == '-u'}
45
+ end
46
+
47
+ def check_working_dir dir
48
+ return if File.directory?(dir)
49
+ puts "#{dir} should be a directory"
50
+ exit 1
51
+ end
52
+
53
+ def check_config_file
54
+ return if File.file?(CONFIG_FILE)
55
+ puts "#{dir}/config.yml file is missing"
56
+ exit 1
57
+ end
58
+
59
+ def load_config
60
+ YAML.load(File.read(CONFIG_FILE))
61
+ end
62
+
63
+ def validate_config config
64
+ {
65
+ 'IMAGE_NAME' => :validate_config__image_name,
66
+ 'CONTAINER_NAME' => :validate_config__container_name,
67
+ 'APP_DIR' => :validate_config__app_dir,
68
+ 'RUN_SCRIPT' => :validate_config__run_script,
69
+ }.each_pair do |key,validator|
70
+ next if send(validator, config[key])
71
+ puts "", "\t::: Please set #{key} in config.yml :::", ""
72
+ exit 1
73
+ end
74
+ end
75
+
76
+ def validate_config__image_name value
77
+ !value.nil? && !value.empty?
78
+ end
79
+
80
+ def validate_config__container_name value
81
+ !value.nil? && !value.empty? && value.values.any?
82
+ end
83
+
84
+ def validate_config__app_dir value
85
+ !value.nil? && !value.empty?
86
+ end
87
+
88
+ def validate_config__run_script value
89
+ !value.nil? && !value.empty?
90
+ end
91
+
92
+ def prepare_build_dir dir
93
+ FileUtils.rm_rf(dir)
94
+ FileUtils.mkdir_p(dir / 'build')
95
+ end
96
+
97
+ def install_files dir
98
+ install_dockerfile(dir)
99
+ install_start_file(dir)
100
+ install_build_files(dir)
101
+ install_cleanup_file(dir)
102
+ end
103
+
104
+ def install_dockerfile dir
105
+ FileUtils.cp(BASE_DIR / 'Dockerfile', dir)
106
+ end
107
+
108
+ def install_start_file dir
109
+ File.open dir / 'start', 'w' do |f|
110
+ f << File.read(BASE_DIR / 'start').sub('{start}', File.read(START_FILE))
111
+ end
112
+ end
113
+
114
+ def install_build_files dir
115
+ FileUtils.cp(PREPARE_BUILD_FILE, dir / 'build')
116
+ FileUtils.cp(BUILD_FILE, dir / 'build/build')
117
+ end
118
+
119
+ def install_cleanup_file dir
120
+ FileUtils.cp(BASE_DIR / 'cleanup', dir / 'build')
121
+ end
122
+
123
+ def prepare_build dir, app_dir
124
+ Dir.chdir dir / 'build' do
125
+ CLI.run "APP_DIR=#{app_dir} #{PREPARE_BUILD_FILE}"
126
+ exit 1 unless $? && $?.success?
127
+ end
128
+ end
129
+
130
+ def build_image dir, image_name, build_opts
131
+ CLI.run "docker build -t #{image_name} #{build_opts} '#{dir}'"
132
+ $? && $?.success?
133
+ end
134
+
135
+ def push_image image_name
136
+ CLI.run "docker push #{image_name}"
137
+ $? && $?.success?
138
+ end
139
+
140
+ def install_run_script app_dir, image_name, container_name, run_script, run_opts
141
+ FileUtils.mkdir_p(app_dir / File.dirname(run_script))
142
+
143
+ script_path = app_dir / run_script
144
+
145
+ File.open script_path, 'w' do |f|
146
+ f << File.read(BASE_DIR / 'run').
147
+ gsub('{image}', image_name).
148
+ gsub('{script_path_traversal}', script_path_traversal(run_script)).
149
+ gsub('{run_opts}', run_opts).
150
+ gsub('{environments}', container_name.keys.join(' ')).
151
+ gsub('{container_definitions}', container_definitions(container_name))
152
+ end
153
+
154
+ FileUtils.chmod('+x', script_path)
155
+ end
156
+
157
+ def container_definitions container_name
158
+ container_name.map do |kv|
159
+ '[ "$APP_ENV" = "%s" ] && CONTAINER_NAME="%s"' % kv
160
+ end.join("\n")
161
+ end
162
+
163
+ def script_path_traversal run_script
164
+ run_script.gsub(/\A\/+|\/+\Z/, '').scan(/\/+/).map {'..'}*'/'
165
+ end
166
+
167
+ end
168
+ end
169
+ end
170
+ end