heighliner 0.9.0
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 +7 -0
- data/README.md +182 -0
- data/exe/heighliner +86 -0
- data/lib/heighliner/after_dotter.rb +23 -0
- data/lib/heighliner/cli.rb +714 -0
- data/lib/heighliner/cli_options.rb +14 -0
- data/lib/heighliner/cmds/attach.rb +23 -0
- data/lib/heighliner/cmds/db_load.rb +29 -0
- data/lib/heighliner/cmds/db_reset.rb +22 -0
- data/lib/heighliner/cmds/db_reset_hard.rb +21 -0
- data/lib/heighliner/cmds/db_save.rb +26 -0
- data/lib/heighliner/cmds/deinit.rb +22 -0
- data/lib/heighliner/cmds/down.rb +21 -0
- data/lib/heighliner/cmds/init.rb +40 -0
- data/lib/heighliner/cmds/login.rb +21 -0
- data/lib/heighliner/cmds/logs.rb +19 -0
- data/lib/heighliner/cmds/root.rb +21 -0
- data/lib/heighliner/cmds/set.rb +127 -0
- data/lib/heighliner/cmds/show.rb +40 -0
- data/lib/heighliner/cmds/shutdown.rb +36 -0
- data/lib/heighliner/cmds/up.rb +57 -0
- data/lib/heighliner/command_runner.rb +54 -0
- data/lib/heighliner/config.rb +95 -0
- data/lib/heighliner/databases/mysql.rb +45 -0
- data/lib/heighliner/databases/postgres.rb +46 -0
- data/lib/heighliner/docker_control.rb +10 -0
- data/lib/heighliner/dotter.rb +21 -0
- data/lib/heighliner/error.rb +14 -0
- data/lib/heighliner/plugin.rb +68 -0
- data/lib/heighliner/plugins/database.rb +30 -0
- data/lib/heighliner/plugins/git_submodule.rb +23 -0
- data/lib/heighliner/service.rb +60 -0
- data/lib/heighliner/steerfile.rb +120 -0
- data/lib/heighliner/version.rb +5 -0
- data/lib/heighliner.rb +52 -0
- metadata +233 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Attach < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Shuts down the application container and starts it up again with the current directory bind mounted inside. This way the application will run from the source code in the current directory and any edits you make will immediately show up inside the container. This is ideal for development.
|
|
9
|
+
|
|
10
|
+
Once the attached container exits (through the use of control+c for example) it will be replaced by a regular non-attached version of the app container.
|
|
11
|
+
|
|
12
|
+
USAGE: heighliner attach
|
|
13
|
+
EOS
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def execute(_opts)
|
|
17
|
+
ensure_setup
|
|
18
|
+
attach_app
|
|
19
|
+
start_app
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class DbLoad < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Shuts down the database docker container, *replaces* the database with the backup provided and brings the container up again.
|
|
9
|
+
|
|
10
|
+
The database will be restored from a tarball saved as \`~/.heighliner/<ENV_NAME>/<current_github_branch_name>/<DB_BACKUP_FILENAME>.tar.bz\`
|
|
11
|
+
|
|
12
|
+
Alternatively you can also load it from your current directory.
|
|
13
|
+
|
|
14
|
+
If no database name was provided, the default database stored at \`~/.heighliner/<ENV_NAME>/<current_github_branch_name>/default.tar.bz\` will be used.
|
|
15
|
+
|
|
16
|
+
USAGE: heighliner db_load
|
|
17
|
+
heighliner db_load DB_BACKUP_FILENAME
|
|
18
|
+
heighliner db_load ./my_database.tar.bz
|
|
19
|
+
EOS
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def execute(_opts)
|
|
23
|
+
ensure_setup
|
|
24
|
+
name = ARGV.shift || 'default'
|
|
25
|
+
load_db(name)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class DbReset < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Shuts down the database docker container, *replaces* the database with the default database image stored at \`~/.heighliner/<ENV_NAME>/<current_github_branch_name>/default.tar.bz\` and brings the container up again.
|
|
9
|
+
|
|
10
|
+
This is the same as running \`heighliner db_load\` with no arguments.
|
|
11
|
+
|
|
12
|
+
USAGE: heighliner db_reset
|
|
13
|
+
EOS
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def execute(_opts)
|
|
17
|
+
ensure_setup
|
|
18
|
+
load_db('default')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class DbResetHard < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Shuts down the database docker container, deletes the default database image stored at \`~/.heighliner/<ENV_NAME>/<current_github_branch_name>/default.tar.bz\`, rebuilds the docker volume if needed and the default database image from scratch and then brings the container up again.
|
|
9
|
+
|
|
10
|
+
USAGE: heighliner db_reset_hard
|
|
11
|
+
EOS
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute(_opts)
|
|
15
|
+
ensure_setup
|
|
16
|
+
FileUtils.rm db_image_path('default') if File.exist?(db_image_path('default'))
|
|
17
|
+
setup_db
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class DbSave < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Shuts down the database docker container, backs up the database and brings the container back up.
|
|
9
|
+
|
|
10
|
+
The database will be saved as a tarball to \`~/.heighliner/<ENV_NAME>/<current_github_branch_name>/<DB_BACKUP_FILENAME>.tar.bz\`
|
|
11
|
+
|
|
12
|
+
Alternatively you can also save it to your current directory.
|
|
13
|
+
|
|
14
|
+
USAGE: heighliner db_save DB_BACKUP_FILENAME
|
|
15
|
+
heighliner db_save ./my_database.tar.bz
|
|
16
|
+
EOS
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def execute(_opts)
|
|
20
|
+
ensure_setup
|
|
21
|
+
name = ARGV.shift || 'default'
|
|
22
|
+
save_db(name)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Deinit < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Removes the Heighliner environment from \`~/.heighliner/config.yml\`. This also runs \`heighliner down\` to stop and delete your app containers and database volume. It does not delete the \`~/.heighliner/databases/<ENV_NAME>\` directory.
|
|
9
|
+
|
|
10
|
+
USAGE: heighliner deinit
|
|
11
|
+
EOS
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute(_opts)
|
|
15
|
+
down
|
|
16
|
+
Config.config[:envs].delete(envname)
|
|
17
|
+
Config.config[:envnames].delete(Config.work_dir)
|
|
18
|
+
save_config
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Down < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Stops and removes your app and database containers, and deletes the database volume. This does **not** affect the shared infrastructure (nginx, DNS, Chrome) — use \`heighliner shutdown\` for that.
|
|
9
|
+
|
|
10
|
+
USAGE: heighliner down
|
|
11
|
+
EOS
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute(_opts)
|
|
15
|
+
stop_db
|
|
16
|
+
stop_app
|
|
17
|
+
delete_db_volume
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Init < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Initializes a Heighliner environment and assigns ports for it in \`~/.heighliner/config.yml\`. When running \`heighliner up\` later the directory \`~/.heighliner/databases/<ENV_NAME>\` will get created.
|
|
9
|
+
|
|
10
|
+
If the current directory is already initialized, you will get an error telling you the existing environment name.
|
|
11
|
+
|
|
12
|
+
USAGE: heighliner init ENV_NAME
|
|
13
|
+
EOS
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def execute(_opts)
|
|
17
|
+
return Optimist.die "Already initialized as #{envname}. Use 'heighliner deinit' to remove this environment first." if envname
|
|
18
|
+
|
|
19
|
+
name = ARGV.shift
|
|
20
|
+
return Optimist.die 'Needs environment name' if name.nil?
|
|
21
|
+
|
|
22
|
+
init_config_for_env(name)
|
|
23
|
+
save_config
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def init_config_for_env(name)
|
|
27
|
+
Config.config[:envnames][Config.work_dir] = name
|
|
28
|
+
Config.config[:envs][name] = {
|
|
29
|
+
app_port: (largest_port + 1).to_s,
|
|
30
|
+
db_port: (largest_port + 2).to_s
|
|
31
|
+
}
|
|
32
|
+
Config.config[:largest_port] = Config.config[:largest_port] + 2
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def largest_port
|
|
36
|
+
Config.config[:largest_port]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Login < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Executes a command on the application docker container. By executing the command \`sh\` you can get a login shell.
|
|
9
|
+
|
|
10
|
+
USAGE: heighliner login COMMAND
|
|
11
|
+
EOS
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute(_opts)
|
|
15
|
+
ensure_setup
|
|
16
|
+
cmd = (ARGV || []).join(' ')
|
|
17
|
+
exec "docker exec -ti #{app_container_name} #{cmd}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Logs < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Continuously monitors the application container's logs.
|
|
9
|
+
|
|
10
|
+
USAGE: heighliner logs
|
|
11
|
+
EOS
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute(_opts)
|
|
15
|
+
exec "docker logs -f #{app_container_name}"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Root < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~USAGE
|
|
8
|
+
Executes a command on the application docker container as a root user.
|
|
9
|
+
|
|
10
|
+
USAGE: heighliner root COMMAND
|
|
11
|
+
USAGE
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute(_opts)
|
|
15
|
+
ensure_setup
|
|
16
|
+
cmd = (ARGV || []).join(' ')
|
|
17
|
+
exec "docker exec -ti --user root #{app_container_name} #{cmd}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Heighliner
|
|
6
|
+
module Cmds
|
|
7
|
+
class Set < Cli
|
|
8
|
+
def usage
|
|
9
|
+
<<~EOS
|
|
10
|
+
This command lets you set up special variables that configure heighliner's behavior for you.
|
|
11
|
+
|
|
12
|
+
Available subcommands:
|
|
13
|
+
|
|
14
|
+
http-suffix - Sets the domain suffix for the reverse proxy to use (defaults to lvh.me)
|
|
15
|
+
cert-url - Sets up a URL from which HTTPS certificates can be downloaded.
|
|
16
|
+
cert-folder - Sets up a folder from which HTTPS certificates can be copied.
|
|
17
|
+
cert-1password - Sets up a 1Password item from which HTTPS certificates can be downloaded.
|
|
18
|
+
cert-1password-fields - Sets custom 1Password field names (JSON object)
|
|
19
|
+
help-https - Shows the HTTPS notes.
|
|
20
|
+
|
|
21
|
+
USAGE: heighliner set cert-url
|
|
22
|
+
heighliner set cert-folder
|
|
23
|
+
heighliner set cert-1password
|
|
24
|
+
heighliner set cert-1password-fields
|
|
25
|
+
heighliner set http-suffix
|
|
26
|
+
heighliner set help-https
|
|
27
|
+
EOS
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize
|
|
31
|
+
super
|
|
32
|
+
@use_steerfile = false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def execute(_opts)
|
|
36
|
+
cmd = ARGV.shift
|
|
37
|
+
|
|
38
|
+
case cmd
|
|
39
|
+
when 'cert-url'
|
|
40
|
+
Config.config[:cert_source] = { url: ARGV.shift }
|
|
41
|
+
when 'cert-folder'
|
|
42
|
+
Config.config[:cert_source] = { folder: ARGV.shift }
|
|
43
|
+
when 'cert-1password'
|
|
44
|
+
handle_cert_1password
|
|
45
|
+
when 'cert-1password-fields'
|
|
46
|
+
Config.config[:cert_source]['1password-fields'] = JSON.parse(ARGV.shift)
|
|
47
|
+
when 'http-suffix'
|
|
48
|
+
Config.config[:http_suffix] = ARGV.shift
|
|
49
|
+
when 'help-https'
|
|
50
|
+
puts help_https
|
|
51
|
+
else
|
|
52
|
+
Optimist.die "Unknown subcommand: '#{cmd}'"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
save_config
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def handle_cert_1password
|
|
61
|
+
if ARGV.empty?
|
|
62
|
+
puts help_1password
|
|
63
|
+
else
|
|
64
|
+
Config.config[:cert_source] = { '1password': ARGV.shift }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def help_https
|
|
69
|
+
<<~SET_HELP
|
|
70
|
+
Notes on HTTPS:
|
|
71
|
+
|
|
72
|
+
You need to set suffix and either cert-url or cert-folder to enable HTTPS.
|
|
73
|
+
|
|
74
|
+
cert-url and cert-folder are mutually exclusive. If you set one of them the other will be erased.
|
|
75
|
+
|
|
76
|
+
The cert-url and cert-folder must satisfy the following requirements to work:
|
|
77
|
+
|
|
78
|
+
The strings must be the root of certificates named after the suffix. For example,
|
|
79
|
+
|
|
80
|
+
if cert-url is https://mydomain.com/certs and your suffix is local.mydomain.com, the following
|
|
81
|
+
url need to be the certificate files:
|
|
82
|
+
|
|
83
|
+
https://mydomain.com/certs/local.mydomain.com.chain.pem
|
|
84
|
+
https://mydomain.com/certs/local.mydomain.com.crt
|
|
85
|
+
https://mydomain.com/certs/local.mydomain.com.key
|
|
86
|
+
|
|
87
|
+
Another example:
|
|
88
|
+
|
|
89
|
+
If you use suffix of localme.com and cert-folder is /home/me/https, The following files need to exist:
|
|
90
|
+
|
|
91
|
+
/home/me/https/localme.com.chain.pem
|
|
92
|
+
/home/me/https/localme.com.crt
|
|
93
|
+
/home/me/https/localme.com.key
|
|
94
|
+
SET_HELP
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def help_1password
|
|
98
|
+
<<~SET_HELP
|
|
99
|
+
Notes on 1Password certificates:
|
|
100
|
+
|
|
101
|
+
You need to set suffix and cert-1password to enable HTTPS with 1Password.
|
|
102
|
+
|
|
103
|
+
The cert-1password value should be in the format 'Vault/Item'.
|
|
104
|
+
|
|
105
|
+
By default, the field names in the 1Password item should match the file extensions:
|
|
106
|
+
- key → <suffix>.key
|
|
107
|
+
- crt → <suffix>.crt
|
|
108
|
+
- chain → <suffix>.chain.pem
|
|
109
|
+
|
|
110
|
+
You can customize field names with:
|
|
111
|
+
heighliner set cert-1password-fields '{"key":"private-key","crt":"certificate","chain":"ca-bundle"}'
|
|
112
|
+
|
|
113
|
+
Example:
|
|
114
|
+
heighliner set cert-1password Vault/Dev-Certs
|
|
115
|
+
heighliner set http-suffix local.mydomain.com
|
|
116
|
+
|
|
117
|
+
This will read:
|
|
118
|
+
op read "op://Vault/Dev-Certs/key" → local.mydomain.com.key
|
|
119
|
+
op read "op://Vault/Dev-Certs/crt" → local.mydomain.com.crt
|
|
120
|
+
op read "op://Vault/Dev-Certs/chain" → local.mydomain.com.chain.pem
|
|
121
|
+
|
|
122
|
+
Make sure the `op` CLI is installed and authenticated on your machine.
|
|
123
|
+
SET_HELP
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Show < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Subcommand that shows information about the environment such as the TCP ports or the certificate used for HTTPS.
|
|
9
|
+
|
|
10
|
+
USAGE: heighliner show ports
|
|
11
|
+
heighliner show cert-source
|
|
12
|
+
heighliner show http-suffix
|
|
13
|
+
EOS
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def execute(_opts)
|
|
17
|
+
ensure_setup
|
|
18
|
+
cmd = ARGV.shift
|
|
19
|
+
valid_cmds = 'ports cert-source http-suffix'
|
|
20
|
+
return Optimist.die "Available things to show: #{valid_cmds}" unless cmd
|
|
21
|
+
|
|
22
|
+
case cmd
|
|
23
|
+
when 'ports'
|
|
24
|
+
Config.info_out.puts "app: #{app_port}"
|
|
25
|
+
Config.info_out.puts "db: #{db_port}"
|
|
26
|
+
when 'cert-source'
|
|
27
|
+
unless Config.config[:cert_source]
|
|
28
|
+
Optimist.die 'No certificate source set.
|
|
29
|
+
see heighliner set help'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
source = Config.config[:cert_source][:url] || Config.config[:cert_source][:folder]
|
|
33
|
+
Config.info_out.puts source
|
|
34
|
+
when 'http-suffix'
|
|
35
|
+
Config.info_out.puts http_suffix
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Shutdown < Cli
|
|
6
|
+
def usage
|
|
7
|
+
<<~EOS
|
|
8
|
+
Shuts down the shared infrastructure containers used by Heighliner (nginx reverse proxy, DNS resolver, and Selenium Chrome). This does **not** stop your app or database containers — use \`heighliner down\` for that.
|
|
9
|
+
|
|
10
|
+
NOTE: This command is destructive — it removes the shared Docker network and certs volume, which will affect all Heighliner environments on this machine.
|
|
11
|
+
|
|
12
|
+
USAGE: heighliner shutdown
|
|
13
|
+
EOS
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize
|
|
17
|
+
super
|
|
18
|
+
@use_steerfile = false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def execute(_opts)
|
|
22
|
+
Config.load(Dir.pwd, use_steerfile: false)
|
|
23
|
+
|
|
24
|
+
shared_names = Config.config[:shared_names] || {}
|
|
25
|
+
networkname = Config.config[:networkname] || 'heighliner_net'
|
|
26
|
+
|
|
27
|
+
shared_names.each_value do |container_name|
|
|
28
|
+
killrm container_name
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
CommandRunner.run Config.out, "docker network rm #{networkname}"
|
|
32
|
+
CommandRunner.run Config.out, "docker volume rm #{shared_names[:certs]}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Heighliner
|
|
4
|
+
module Cmds
|
|
5
|
+
class Up < Cli
|
|
6
|
+
option :attach,
|
|
7
|
+
'Bind mount the current source code directory in the app container',
|
|
8
|
+
short: '-a'
|
|
9
|
+
|
|
10
|
+
def usage
|
|
11
|
+
<<~EOS
|
|
12
|
+
Boots up the application in docker as defined in the \`Steerfile\` in its source code. Usually this will create two docker containers \`<ENV_NAME>-db\` and \`<ENV_NAME>-app\` running your database and application respectively.
|
|
13
|
+
|
|
14
|
+
A backup of the default database is created and saved to \`~/.heighliner/<ENV_NAME>/<current_github_branch_name>/default.tar.bz\`. This can be restored at any time using the \`db_reset\` command.
|
|
15
|
+
|
|
16
|
+
USAGE: heighliner up
|
|
17
|
+
EOS
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def execute(opts)
|
|
21
|
+
ensure_setup
|
|
22
|
+
setup_app
|
|
23
|
+
setup_db
|
|
24
|
+
|
|
25
|
+
if opts[:attach]
|
|
26
|
+
attach_app
|
|
27
|
+
else
|
|
28
|
+
start_app
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def build_cmd
|
|
33
|
+
platform_args = ''
|
|
34
|
+
platform_args = "--platform=#{force_platform}" unless force_platform.empty?
|
|
35
|
+
build_args = docker_build_args.map { |k, v| "--build-arg #{k}=#{v}" }
|
|
36
|
+
[
|
|
37
|
+
'docker build',
|
|
38
|
+
"-t heighliner:#{envname}-#{current_branch}",
|
|
39
|
+
"-f #{tmp_dockerfile_name} #{Config.work_dir}",
|
|
40
|
+
platform_args,
|
|
41
|
+
build_args.join(' ').to_s
|
|
42
|
+
]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def setup_app
|
|
46
|
+
Config.info_out.puts 'Setting up application'
|
|
47
|
+
File.write(tmp_dockerfile_name, docker_file_contents)
|
|
48
|
+
|
|
49
|
+
CommandRunner.run! Config.out, build_cmd.join("\n\t"), env_vars: {
|
|
50
|
+
'DOCKER_BUILDKIT' => '1',
|
|
51
|
+
'BUILDKIT_PROGRESS' => 'plain'
|
|
52
|
+
}
|
|
53
|
+
FileUtils.rm(tmp_dockerfile_name)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pty'
|
|
4
|
+
require 'English'
|
|
5
|
+
|
|
6
|
+
module Heighliner
|
|
7
|
+
# This is the command runner
|
|
8
|
+
# it abstracts away the complicated syntax required to deal with
|
|
9
|
+
# PTY and to pass the lines programmatically to the host application
|
|
10
|
+
# as well as to capture the return code at the end.
|
|
11
|
+
class CommandRunner
|
|
12
|
+
def self.run(out, cmd, env_vars: {}, &block)
|
|
13
|
+
out.puts "> #{cmd}"
|
|
14
|
+
CommandRunner.new(out, cmd, env_vars).run_command(&block)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.run!(out, cmd, env_vars: {}, &block)
|
|
18
|
+
status = run(out, cmd, env_vars: env_vars, &block)
|
|
19
|
+
raise Heighliner::CmdError.new(cmd, status) if status.to_s != '0'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(out, cmd, env_vars)
|
|
23
|
+
@out = out
|
|
24
|
+
@cmd = cmd.tr "\n", ' '
|
|
25
|
+
@env_vars = env_vars
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def print_and_return_status(status = 0)
|
|
29
|
+
@out.puts "$? = #{status}"
|
|
30
|
+
@out.flush
|
|
31
|
+
status
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def print_lines(lines)
|
|
35
|
+
lines.each do |line|
|
|
36
|
+
@out.print line
|
|
37
|
+
@out.flush
|
|
38
|
+
yield line.chomp if block_given?
|
|
39
|
+
end
|
|
40
|
+
rescue Errno::EIO
|
|
41
|
+
# Happens when `lines` stream is closed
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def run_command(&block)
|
|
45
|
+
PTY.spawn(@env_vars, "#{@cmd} 2>&1") do |stdout, _stdin, pid|
|
|
46
|
+
print_lines(stdout, &block)
|
|
47
|
+
Process.wait(pid)
|
|
48
|
+
end
|
|
49
|
+
print_and_return_status $CHILD_STATUS.exitstatus
|
|
50
|
+
rescue PTY::ChildExited => e
|
|
51
|
+
print_and_return_status(e.status)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|