neptuno 1.0.10 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +6 -5
  3. data/Rakefile +6 -6
  4. data/exe/neptuno +1 -1
  5. data/lib/neptuno/cli/activate.rb +19 -19
  6. data/lib/neptuno/cli/base.rb +4 -4
  7. data/lib/neptuno/cli/clone.rb +8 -2
  8. data/lib/neptuno/cli/configure.rb +3 -3
  9. data/lib/neptuno/cli/execute.rb +4 -4
  10. data/lib/neptuno/cli/init.rb +5 -5
  11. data/lib/neptuno/cli/install.rb +15 -17
  12. data/lib/neptuno/cli/list.rb +21 -31
  13. data/lib/neptuno/cli/version.rb +1 -1
  14. data/lib/neptuno/cli.rb +28 -28
  15. data/lib/neptuno/docker/attach.rb +2 -2
  16. data/lib/neptuno/docker/build.rb +5 -5
  17. data/lib/neptuno/docker/down.rb +18 -9
  18. data/lib/neptuno/docker/log.rb +1 -1
  19. data/lib/neptuno/docker/restart.rb +8 -8
  20. data/lib/neptuno/docker/services.rb +2 -2
  21. data/lib/neptuno/docker/up.rb +6 -11
  22. data/lib/neptuno/environment/config.rb +3 -3
  23. data/lib/neptuno/environment/update.rb +1 -1
  24. data/lib/neptuno/git/pull.rb +2 -2
  25. data/lib/neptuno/git/stash.rb +2 -2
  26. data/lib/neptuno/k8s/attach.rb +6 -6
  27. data/lib/neptuno/overmind/connect.rb +20 -71
  28. data/lib/neptuno/overmind/start.rb +22 -56
  29. data/lib/neptuno/overmind/stop.rb +12 -6
  30. data/lib/neptuno/services/add.rb +9 -15
  31. data/lib/neptuno/services/destroy.rb +1 -1
  32. data/lib/neptuno/services/list.rb +3 -2
  33. data/lib/neptuno/services/update.rb +8 -8
  34. data/lib/neptuno/templates/{tmuxinator.yml → .tmuxinator.yml} +2 -4
  35. data/lib/neptuno/templates/docker-compose.yml +18 -7
  36. data/lib/neptuno/templates/neptuno.yml +6 -0
  37. data/lib/neptuno/tty/config.rb +44 -10
  38. data/lib/neptuno/tty/file.rb +6 -6
  39. data/lib/neptuno/version.rb +1 -1
  40. data/lib/neptuno.rb +11 -11
  41. data/neptuno.gemspec +26 -26
  42. metadata +16 -15
@@ -4,7 +4,7 @@ module Neptuno
4
4
  module Docker
5
5
  module Services
6
6
  include Neptuno::TTY::Config
7
- require 'yaml'
7
+ require "yaml"
8
8
 
9
9
  def running_services
10
10
  running_services = `cd ~/.neptuno/projects/#{current_project} && docker compose ps | awk '{ print $3 }' | awk 'NR>1'`
@@ -13,7 +13,7 @@ module Neptuno
13
13
 
14
14
  def registered_services
15
15
  dc = YAML.load_file("#{neptuno_path}/docker-compose.yml")
16
- dc['services'].keys
16
+ dc["services"].keys
17
17
  end
18
18
 
19
19
  def stopped_services
@@ -4,21 +4,16 @@ module Neptuno
4
4
  module Docker
5
5
  # Build docker container for Neptuno project
6
6
  class Up < Neptuno::CLI::Base
7
- desc 'Docker: bring up docker containers for current project'
7
+ desc "Docker: bring up docker containers for current project"
8
8
 
9
- option :all, type: :boolean, default: false, desc: 'Run on all services'
10
- option :log, type: :boolean, default: false, desc: 'Show service log (only first service)'
11
- argument :services, type: :array, required: false, desc: 'Optional list of services'
9
+ option :all, type: :boolean, default: false, desc: "Run on all services"
10
+ option :wait, type: :boolean, default: true, desc: "Wait for services to be healthy"
11
+ argument :services, type: :array, required: false, desc: "Optional list of services"
12
12
 
13
13
  def call(services: [], **options)
14
- command_services_to('come up', all: options.fetch(:all), services_as_args: services) do |services, project|
14
+ command_services_to("come up", all: options.fetch(:all), services_as_args: services) do |services, _project|
15
15
  make_service_files(services)
16
- system("cd #{neptuno_path} && docker compose up -d #{services.join(' ')}")
17
- success = system("cd #{neptuno_path} && docker logs -f #{project}_#{services.first}_1") if options.fetch(:log)
18
- unless success
19
- puts "Trying #{project}-#{services.first}-1"
20
- system("cd #{neptuno_path} && docker logs -f #{project}-#{services.first}-1") if options.fetch(:log)
21
- end
16
+ system("cd #{neptuno_path} && docker-compose up -d --wait #{services.join(" ")}")
22
17
  end
23
18
  end
24
19
  end
@@ -4,12 +4,12 @@ module Neptuno
4
4
  module Environment
5
5
  # Build docker container for Neptuno project
6
6
  class Config < Neptuno::CLI::Base
7
- desc 'Environment: Configure local or remote'
7
+ desc "Environment: Configure local or remote"
8
8
 
9
- argument :services, type: :array, required: false, desc: 'Optional list of services'
9
+ argument :services, type: :array, required: false, desc: "Optional list of services"
10
10
 
11
11
  def call(services: [], **_options)
12
- command_services_to('print', services_as_args: services) do |services|
12
+ command_services_to("print", services_as_args: services) do |services|
13
13
  services.each do |service|
14
14
  puts service
15
15
  end
@@ -4,7 +4,7 @@ module Neptuno
4
4
  module Environment
5
5
  # Build docker container for Neptuno project
6
6
  class Update < Neptuno::CLI::Base
7
- desc 'Environment: Update all environment files'
7
+ desc "Environment: Update all environment files"
8
8
 
9
9
  def call
10
10
  env_path = "#{neptuno_path}/environments/"
@@ -4,10 +4,10 @@ module Neptuno
4
4
  module Git
5
5
  # Pull all submodule changes
6
6
  class Pull < Neptuno::CLI::Base
7
- desc 'Git: pull all submodule changes'
7
+ desc "Git: pull all submodule changes"
8
8
 
9
9
  def call(services: [], **_options)
10
- system('git submodule foreach git pull')
10
+ system("git submodule foreach git pull")
11
11
  end
12
12
  end
13
13
  end
@@ -4,10 +4,10 @@ module Neptuno
4
4
  module Git
5
5
  # Stash all submodule changes
6
6
  class Stash < Neptuno::CLI::Base
7
- desc 'Git: stash all submodule changes'
7
+ desc "Git: stash all submodule changes"
8
8
 
9
9
  def call(services: [], **_options)
10
- system('git submodule foreach git stash')
10
+ system("git submodule foreach git stash")
11
11
  end
12
12
  end
13
13
  end
@@ -4,20 +4,20 @@ module Neptuno
4
4
  module K8s
5
5
  class Attach < Neptuno::CLI::Base
6
6
  include ::Neptuno::TTY::Config
7
- desc 'K8s: Attach to a container with k8s'
7
+ desc "K8s: Attach to a container with k8s"
8
8
 
9
- option :context, type: :string, default: 'int', desc: 'K8s context to run in'
10
- option :namespace, type: :string, default: 'thrillshare', desc: 'K8s namespace to run in'
11
- option :dependent, type: :string, desc: 'Dependent service'
9
+ option :context, type: :string, default: "int", desc: "K8s context to run in"
10
+ option :namespace, type: :string, default: "thrillshare", desc: "K8s namespace to run in"
11
+ option :dependent, type: :string, desc: "Dependent service"
12
12
  option :pr, type: :integer, desc: "PR's Github ID"
13
13
 
14
14
  def call(**options)
15
- command_service_to('attach with k8s', service_as_args: options[:args]&.first) do |service, _project|
15
+ command_service_to("attach with k8s", service_as_args: options[:args]&.first) do |service, _project|
16
16
  deployment = "deploy/#{options[:dependent] || service}"
17
17
  deployment += "-#{service}-#{options[:pr]}" unless options[:pr].nil?
18
18
 
19
19
  context = options[:context]
20
- context = 'qa' unless options[:pr].nil?
20
+ context = "qa" unless options[:pr].nil?
21
21
 
22
22
  system("kubectl config use-context #{context} > /dev/null 2>&1")
23
23
  puts "Attaching to #{deployment} in the #{options[:namespace]} namespace using the #{context} context"
@@ -7,91 +7,40 @@ module Neptuno
7
7
  include ::Neptuno::TTY::Config
8
8
  desc 'Overmind: Connect to processes inside docker containers'
9
9
 
10
- option :force, type: :boolean, default: false, desc: 'Try to connect disrigarding container status'
10
+ option :up, type: :boolean, default: true, desc: 'Try to start containers before connecting'
11
+ option :start, type: :boolean, default: true, desc: 'Try to start processes on containers before connecting'
11
12
  option :all, type: :boolean, default: false, desc: 'Run on all services'
12
- option :up, type: :boolean, default: false, desc: 'Try to start containers before connecting'
13
- option :tmux, type: :boolean, default: false, desc: 'Connect to services using Tmux'
14
- option :tmux_sessions, type: :boolean, default: false, desc: 'Connect to services using Tmux'
13
+ option :wait, type: :boolean, default: true, desc: 'Wait for all services to be healthy'
14
+ option :dependencies, type: :boolean, default: true, desc: 'Connect to service and its dependencies'
15
15
  argument :services, type: :array, required: false, desc: 'Optional list of services'
16
16
 
17
17
  def call(services: [], **options)
18
- multi_spinner = ::TTY::Spinner::Multi.new('[:spinner] Services')
19
- spinners = {}
20
- count = 0
21
18
  command_services_to('connect to procs', all: options.fetch(:all), services_as_args: services) do |services|
22
- system("cd #{neptuno_path} && docker-compose up -d #{services.join(' ')}") if options.fetch(:up)
23
- running_services = ::Neptuno::CLI::List.new.running_services.first.keys
24
- running_services.sort.each do |service|
25
- spinners[service] ||= multi_spinner.register("[:spinner] :state #{service}")
26
- spinners[service].update(state: '- ')
27
- spinners[service].auto_spin
28
- end
29
- loop do
30
- ps = `cd #{neptuno_path} && docker-compose ps`.split("\n").compact.select { |x| x.match(/^\s*#{project}/) }
31
-
32
- running_services.sort.each do |service|
33
- service_ps = ps.find {|s| s =~ /#{project}[-_]#{service}[-_]\d\s/ }
19
+ `neptuno up #{services.join(' ')}` if options.fetch(:up)
20
+ original_services = services
21
+ services = services_with_procs.intersection(get_dependants(services).concat(services).uniq).sort
34
22
 
35
- status = :dead if service_ps.to_s.include?('exited')
36
- status = :starting if service_ps.to_s.include?('starting')
37
- status = :unhealthy if service_ps.to_s.include?('(unhealthy')
38
- status = :healthy if service_ps.to_s.include?('(healthy')
39
- status = :force if options.fetch(:force)
23
+ outside_tmux = `echo $TMUX`.strip.empty?
40
24
 
41
- case status
42
- when :force
43
- spinners[service].success
44
- `cd #{neptuno_path}/procfiles/#{service} && overmind start -D -N #{auto_restart_procs.unshift("-r").join(" ") if auto_restart_procs.to_a.count > 0} > /dev/null 2>&`
45
- when :dead
46
- spinners[service].update(state: 'dead ')
47
- spinners[service].error
48
- when :starting
49
- spinners[service].update(state: 'starting ')
50
- when :unhealthy
51
- spinners[service].update(state: 'unhealthy ')
52
- spinners[service].error if spinners[service].instance_variable_get(:@state) == :spinning && count > 50
53
- when :healthy
54
- spinners[service].update(state: 'ready ')
55
- spinners[service].success
56
- else
57
- spinners[service].update(state: 'down ')
58
- spinners[service].error
25
+ if config.fetch('procfile_manager') == 'tmux'
26
+ services.each do |service|
27
+ if /#{service}/.match?(`tmux ls`)
28
+ puts "Neptuno wil use existing Tmux session for: #{service}"
29
+ next
59
30
  end
60
- end
61
- break if spinners.values.map { |s| s.instance_variable_get(:@state) }.uniq.all?(:stopped)
62
31
 
63
- count += 1
64
- sleep(5)
65
- end
66
- spinner = ::TTY::Spinner.new('Neptuno: Connecting[:spinner]', format: :dots)
67
- spinner.auto_spin
68
-
69
- healthy_services = spinners.select { |_k, v| v.instance_variable_get(:@succeeded) == :success }.keys
70
- spinner.stop
71
- if config.fetch('procfile_manager') == 'tmux'
72
- healthy_services.each do |service|
73
- pid = spawn("cd #{neptuno_path} && tmuxinator start neptuno_#{service} #{service} -n #{service}",
32
+ pid = spawn("cd #{neptuno_path} && tmuxinator start neptuno_#{service} #{service}",
74
33
  3 => '/dev/null')
75
34
  Process.detach(pid)
76
- puts "Neptuno started tmux session for: #{service}"
35
+ puts "Neptuno started Tmux session for: #{service}" if `echo $TMUX`.strip.empty?
77
36
  end
78
37
  else
79
- spinners.select { |_k, v| v.instance_variable_get(:@succeeded) == :success }.each_key do |service|
80
- system("cd #{neptuno_path}/procfiles/#{service} && overmind start -D -N #{auto_restart_procs.unshift("-r").join(" ") if auto_restart_procs.to_a.count > 0} > /dev/null 2>&1")
81
- end
82
- sleep(5)
83
- spinner.stop
84
- if options.fetch(:tmux)
85
- system("cd #{neptuno_path} && tmuxinator start neptuno #{healthy_services.join(' ')}")
38
+ puts `neptuno start --no-up #{services.join(' ')}` if options.fetch(:start)
39
+ if outside_tmux
40
+ system("cd #{neptuno_path} && tmuxinator start neptuno #{services.join(' ')}")
86
41
  else
87
- begin
88
- system("cd #{neptuno_path}/procfiles/#{services.first} && overmind connect shell", exception: true)
89
- rescue RuntimeError
90
- system("cd #{neptuno_path} && docker compose exec #{service} kill -9 -1")
91
- system("cd #{neptuno_path}/procfiles/#{service} && rm .overmind.sock > /dev/null 2>&1")
92
- system("cd #{neptuno_path}/procfiles/#{service} && overmind start -D -N #{auto_restart_procs.unshift("-r").join(" ") if auto_restart_procs.to_a.count > 0} > /dev/null 2>&1")
93
- retry
94
- end
42
+ puts "Connecting to #{original_services.first}"
43
+ system("cd #{neptuno_path}/procfiles/#{original_services.first} && overmind connect shell")
95
44
  end
96
45
  end
97
46
  end
@@ -5,67 +5,33 @@ module Neptuno
5
5
  # Build docker container for Neptuno project
6
6
  class Start < Neptuno::CLI::Base
7
7
  include ::Neptuno::TTY::Config
8
- desc 'Overmind: Start processes inside docker containers'
8
+ desc "Overmind: Start processes inside docker containers"
9
9
 
10
- option :force, type: :boolean, default: false, desc: 'Try to start disrigarding container status'
11
- option :all, type: :boolean, default: false, desc: 'Run on all services'
12
- option :up, type: :boolean, default: false, desc: 'Try to start containers before connecting'
13
- argument :services, type: :array, required: false, desc: 'Optional list of services'
10
+ option :all, type: :boolean, default: false, desc: "Run on all services"
11
+ option :up, type: :boolean, default: true, desc: "Try to start containers before connecting"
12
+ argument :services, type: :array, required: false, desc: "Optional list of services"
14
13
 
15
14
  def call(services: [], **options)
16
- multi_spinner = ::TTY::Spinner::Multi.new('[:spinner] Services')
17
- spinners = {}
18
- count = 0
19
- command_services_to('connect to procs', all: options.fetch(:all), services_as_args: services) do |services|
20
- system("cd #{neptuno_path} && docker compose up -d #{services.join(' ')}") if options.fetch(:up)
21
- running_services = ::Neptuno::CLI::List.new.running_services.first.keys
22
- running_services.sort.each do |service|
23
- spinners[service] ||= multi_spinner.register("[:spinner] :state #{service}")
24
- spinners[service].update(state: '- ')
25
- spinners[service].auto_spin
26
- end
27
- loop do
28
- ps = `cd #{neptuno_path} && docker compose ps`.split("\n").compact.select { |x| x.match(/^\s*#{project}/) }
29
-
30
- running_services.sort.each do |service|
31
- service_ps = ps.find {|s| s =~ /#{project}[-_]#{service}[-_]\d\s/ }
32
-
33
- status = :dead if service_ps.to_s.include?('exited')
34
- status = :starting if service_ps.to_s.include?('starting')
35
- status = :unhealthy if service_ps.to_s.include?('(unhealthy')
36
- status = :healthy if service_ps.to_s.include?('(healthy')
37
- status = :force if options.fetch(:force)
38
-
39
- case status
40
- when :force
41
- spinners[service].success
42
- `cd #{neptuno_path}/procfiles/#{service} && overmind start -D -N > /dev/null 2>&1`
43
- when :dead
44
- spinners[service].update(state: 'dead ')
45
- spinners[service].error
46
- when :starting
47
- spinners[service].update(state: 'starting ')
48
- when :unhealthy
49
- spinners[service].update(state: 'unhealthy ')
50
- spinners[service].error if spinners[service].instance_variable_get(:@state) == :spinning && count > 50
51
- when :healthy
52
- spinners[service].update(state: 'ready ')
53
- spinners[service].success
54
- `cd #{neptuno_path}/procfiles/#{service} && overmind start -D -N > /dev/null 2>&1`
55
- else
56
- spinners[service].update(state: 'down ')
57
- spinners[service].error
58
- end
15
+ command_services_to("start procs", all: options.fetch(:all), services_as_args: services) do |services|
16
+ `neptuno up #{services.join(" ")}` if options.fetch(:up)
17
+
18
+ services = services_with_procs.intersection(get_dependants(services).concat(services).uniq).sort
19
+ puts "Starting processes on services: #{services.join(", ")}"
20
+
21
+ if config.fetch("procfile_manager") == "tmux"
22
+ services.each do |service|
23
+ pid = spawn("cd #{neptuno_path} && tmuxinator start neptuno_#{service} #{service} -n #{service}",
24
+ 3 => "/dev/null")
25
+ Process.detach(pid)
26
+ puts "Neptuno started Tmux session for: #{service}" if `echo $TMUX`.strip.empty?
27
+ end
28
+ else
29
+ services.each do |service|
30
+ system("cd #{neptuno_path}/procfiles/#{service} && overmind start -D -N #{if auto_restart_procs.to_a.size > 0
31
+ ("-r " + auto_restart_procs.join(",") + " ")
32
+ end} > /dev/null 2>&1")
59
33
  end
60
- break if spinners.values.map { |s| s.instance_variable_get(:@state) }.uniq.all?(:stopped)
61
-
62
- count += 1
63
- sleep(5)
64
34
  end
65
- spinner = ::TTY::Spinner.new('Neptuno: Starting[:spinner]', format: :dots)
66
- spinner.auto_spin
67
-
68
- spinner.stop
69
35
  end
70
36
  end
71
37
  end
@@ -4,16 +4,22 @@ module Neptuno
4
4
  module Overmind
5
5
  # Build docker container for Neptuno project
6
6
  class Stop < Neptuno::CLI::Base
7
- desc 'Overmind: Stop processes inside docker containers'
7
+ desc "Stop processes inside docker containers"
8
8
 
9
- option :all, type: :boolean, default: false, desc: 'Run on all services'
10
- argument :services, type: :array, required: false, desc: 'Optional list of services'
9
+ option :all, type: :boolean, default: false, desc: "Run on all services"
10
+ argument :services, type: :array, required: false, desc: "Optional list of services"
11
11
 
12
12
  def call(services: [], **options)
13
- command_services_to('stop procs', all: options.fetch(:all), services_as_args: services) do |services|
14
- services.each do |service|
13
+ command_services_to("stop procs", all: options.fetch(:all), services_as_args: services) do |services|
14
+ services_to_stop = services.intersection(services_with_procs).intersection(running_services)
15
+ services_to_stop.each do |service|
15
16
  system("cd #{neptuno_path} && docker compose exec #{service} kill -9 -1")
16
- system("cd #{neptuno_path}/procfiles/#{service} && rm .overmind.sock > /dev/null 2>&1")
17
+ if config.fetch("procfile_manager") == "tmux"
18
+ system("tmux kill-session -t #{service} 2>/dev/null ")
19
+ puts "Neptuno killed Tmux session for: #{service}" if `echo $TMUX`.strip.empty?
20
+ else
21
+ system("cd #{neptuno_path}/procfiles/#{service} && rm .overmind.sock > /dev/null 2>&1")
22
+ end
17
23
  end
18
24
  end
19
25
  end
@@ -8,24 +8,18 @@ module Neptuno
8
8
  include TTY::Config
9
9
  include TTY::File
10
10
 
11
- desc 'Add a Neptuno service with Git'
11
+ desc "Add a Neptuno service with Git"
12
12
 
13
13
  def call(**)
14
- name = prompt.ask('? Service name:')
15
- add_name_to_config(name)
16
- repo = prompt.ask('? Git repo:')
14
+ name = prompt.ask("? Service name:")
15
+ repo = prompt.ask("? Git repo:")
17
16
  clone_into_folder(repo, name)
18
- add_dockerfile(name)
17
+ # add_dockerfile(name)
19
18
  add_procfile(name)
20
19
  add_environment(name)
21
20
  add_service_to_dc(name)
22
21
  end
23
22
 
24
- def add_name_to_config(name)
25
- config.append(name, to: :services) unless config.fetch(:services).include? name
26
- config.write(force: true)
27
- end
28
-
29
23
  def clone_into_folder(repo, name)
30
24
  if repo.nil?
31
25
  command.run("mkdir #{neptuno_path}/services/#{name}")
@@ -62,16 +56,16 @@ module Neptuno
62
56
  stdin_open: true
63
57
  tty: true
64
58
  command: ash
65
- build:#{' '}
59
+ build:#{" "}
66
60
  context: .
67
61
  dockerfile: ./dockerfiles/#{name}/Dockerfile
68
- env_file:#{' '}
62
+ env_file:#{" "}
69
63
  - ./environments/#{name}/default
70
- # volumes:#{' '}
64
+ # volumes:#{" "}
71
65
  # -
72
- # ports:#{' '}
66
+ # ports:#{" "}
73
67
  # -
74
- # depends_on:#{' '}
68
+ # depends_on:#{" "}
75
69
  # -
76
70
 
77
71
  #---------------------------------------------------------------
@@ -4,7 +4,7 @@ module Neptuno
4
4
  module Services
5
5
  # Add project to neptuno
6
6
  class Destroy < Neptuno::CLI::Base
7
- desc 'Remove a Neptuno service'
7
+ desc "Remove a Neptuno service"
8
8
 
9
9
  def call(**)
10
10
  puts destroy
@@ -4,9 +4,10 @@ module Neptuno
4
4
  module Services
5
5
  # Add project to neptuno
6
6
  class List < Neptuno::CLI::Base
7
- desc 'List Neptuno projects'
7
+ desc "List Neptuno projects"
8
8
 
9
- def call(**); end
9
+ def call(**)
10
+ end
10
11
  end
11
12
  end
12
13
  end
@@ -4,15 +4,15 @@ module Neptuno
4
4
  module Services
5
5
  # Update project to to latest GH master/main
6
6
  class Update < Neptuno::CLI::Base
7
- desc 'Stashes changes and pulls latest from main/master'
7
+ desc "Stashes changes and pulls latest from main/master"
8
8
 
9
- option :all, type: :boolean, default: false, desc: 'Run on all services'
9
+ option :all, type: :boolean, default: false, desc: "Run on all services"
10
10
  option :main, type: :boolean, default: false,
11
- desc: "Keep service on main/master after pull. Uncommited changes are stashed as 'neptuno_stash'"
12
- argument :services, type: :array, required: false, desc: 'Optional list of services'
11
+ desc: "Keep service on main/master after pull. Uncommited changes are stashed as 'neptuno_stash'"
12
+ argument :services, type: :array, required: false, desc: "Optional list of services"
13
13
 
14
14
  def call(services: [], **options)
15
- command_services_to('update', all: options.fetch(:all), services_as_args: services) do |services|
15
+ command_services_to("update", all: options.fetch(:all), services_as_args: services) do |services|
16
16
  services.each do |service|
17
17
  puts "---Updating #{service}---"
18
18
  current_branch = `git branch --show-current`
@@ -22,14 +22,14 @@ module Neptuno
22
22
  `cd #{neptuno_path}/services/#{service} 2>/dev/null && git checkout master 2>/dev/null`
23
23
  system("cd #{neptuno_path}/services/#{service} 2>/dev/null && git pull")
24
24
  unless options.fetch(:main)
25
- stash_id = `git stash list`.lines.find { |str| str =~ /neptuno_stash/ }&.split(':')&.first
25
+ stash_id = `git stash list`.lines.find { |str| str =~ /neptuno_stash/ }&.split(":")&.first
26
26
  `cd #{neptuno_path}/services/#{service} 2>/dev/null && git checkout #{current_branch} 2>/dev/null`
27
27
  if stash_id
28
- puts 'Applying stashed changes'
28
+ puts "Applying stashed changes"
29
29
  system("cd #{neptuno_path}/services/#{service} 2>/dev/null && git stash pop -q #{stash_id}")
30
30
  end
31
31
  end
32
- puts ''
32
+ puts ""
33
33
  end
34
34
  end
35
35
  end
@@ -1,4 +1,5 @@
1
- # ./.tmuxinator.yml
1
+ # This file defines what Tmux will do when Neptuno connects to your services.
2
+ # You can add or remove Tmux windows and panes for each service here.
2
3
 
3
4
  <% if YAML.load_file('neptuno.yml')["procfile_manager"] == "tmux" %>
4
5
  name: <%= @args[0] %>
@@ -19,9 +20,7 @@ on_project_exit: tmux kill-session -t neptuno
19
20
  windows:
20
21
  - neptuno:
21
22
  panes:
22
- - sleep 2 && vim
23
23
  - neptuno ps
24
- - # host shell
25
24
 
26
25
  <% @args.each do |service| %>
27
26
  - <%= service %>:
@@ -40,5 +39,4 @@ windows:
40
39
  neptuno c <%= service %>
41
40
  <% end %>
42
41
  <% end %>
43
-
44
42
  <% end %>
@@ -1,7 +1,18 @@
1
- version: '3'
2
- services:
3
- alpine:
4
- image: alpine
5
- tty: true
6
- stdin_open: true
7
- command: ash
1
+ # This file should contain all your project's services with references to their dockerfiles, env_files, volumes, etc.
2
+ # You can then connect to your services using `neptuno connect <service1 service2 ...>`
3
+ #
4
+ # Example:
5
+ #
6
+ # version: '3'
7
+ #
8
+ # services:
9
+ # alpine:
10
+ # tty: true
11
+ # stdin_open: true
12
+ # build:
13
+ # context: .
14
+ # dockerfile: ./dockerfiles/alpine/Dockerfile
15
+ # env_file:
16
+ # - ./environments/alpine/local_env
17
+ # volumes:
18
+ # - ./services/alpine:/usr/src/app:cached
@@ -0,0 +1,6 @@
1
+ ---
2
+ # mode: ide
3
+ # procfile_manager = ["overmind" | "tmux"] # overmind is the default
4
+ configured_services: ''
5
+ services: []
6
+ auto_restart_procs: []
@@ -6,37 +6,71 @@ module Neptuno
6
6
  module Config
7
7
  include TTY::File
8
8
  TTY = ::TTY::Config.new
9
- TTY.filename = 'neptuno'
9
+ TTY.filename = "neptuno"
10
10
 
11
- ABORT_MESSAGE = 'fatal: there are no registered services. Add one with: neptuno services add'
11
+ ABORT_MESSAGE = "fatal: there are no registered services. Add one with: neptuno services add"
12
12
 
13
13
  def config
14
14
  TTY
15
15
  end
16
16
 
17
- def docker_compose_services
17
+ def docker_compose_hash
18
18
  source = ::File.read("#{neptuno_path}/docker-compose.yml")
19
- docker_compose = begin
19
+ @@docker_compose ||= begin
20
20
  YAML.load(source, aliases: true)
21
21
  rescue ArgumentError
22
22
  YAML.load(source)
23
23
  end
24
- docker_compose.fetch('services').keys
24
+ @@docker_compose
25
+ end
26
+
27
+ def docker_compose_services
28
+ docker_compose_hash.fetch("services").keys.sort
25
29
  end
26
30
 
27
31
  def auto_restart_procs
28
- config.fetch('auto_restart_procs')
32
+ config.fetch("auto_restart_procs")
29
33
  end
30
34
 
31
35
  def services
32
- s = config.fetch('services')
33
- s = s.to_a.union(docker_compose_services)
36
+ s = docker_compose_services
34
37
  abort ABORT_MESSAGE if s.count.zero?
35
- s.sort
38
+ s
36
39
  end
37
40
 
38
41
  def configured_services
39
- config.fetch('configured_services')
42
+ config.fetch("configured_services")
43
+ end
44
+
45
+ def running_services
46
+ `cd #{neptuno_path} && docker-compose ps --status running --services`.split
47
+ end
48
+
49
+ def json_services_status
50
+ JSON.parse(`cd #{neptuno_path} && docker compose ps --all --format json`).map do |service|
51
+ [service.dig("Service"), service.dig("Status")]
52
+ end
53
+ end
54
+
55
+ def starting_services(status: nil)
56
+ data = status || json_services_status
57
+ data.select { |service| service.last.match(/starting\)|\(unhealthy\)/) }
58
+ end
59
+
60
+ def healthy_services(status: nil)
61
+ data = status || json_services_status
62
+ data.select { |service| service.last.match(/\(healthy\)/) }
63
+ end
64
+
65
+ def services_with_procs
66
+ `cd #{neptuno_path} && find procfiles -type f -size +0`.split.map { |x| x.split("/")[1] }
67
+ end
68
+
69
+ def get_dependants(services = [])
70
+ return [] if services.empty?
71
+
72
+ deps = services.map { |service| docker_compose_hash.dig("services", service, "depends_on") }.flatten.uniq
73
+ [deps, get_dependants(deps - services)].flatten.compact.uniq
40
74
  end
41
75
  end
42
76
  end