ufo 2.1.0 → 2.2.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.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile.lock +28 -438
  4. data/README.md +0 -8
  5. data/docs/_docs/conventions.md +1 -1
  6. data/docs/_docs/helpers.md +1 -0
  7. data/docs/_docs/settings.md +25 -24
  8. data/docs/_docs/tutorial-ufo-ship.md +1 -1
  9. data/docs/_docs/ufo-env.md +10 -10
  10. data/docs/_docs/variables.md +8 -8
  11. data/lib/starter_project/Dockerfile +1 -1
  12. data/lib/starter_project/ufo/settings.yml +7 -7
  13. data/lib/starter_project/ufo/task_definitions.rb +13 -9
  14. data/lib/starter_project/ufo/variables/{stag.rb → development.rb} +4 -4
  15. data/lib/starter_project/ufo/variables/{prod.rb → production.rb} +3 -3
  16. data/lib/ufo.rb +1 -0
  17. data/lib/ufo/aws_services.rb +4 -1
  18. data/lib/ufo/cli.rb +9 -10
  19. data/lib/ufo/command.rb +23 -0
  20. data/lib/ufo/docker.rb +4 -5
  21. data/lib/ufo/docker/builder.rb +1 -2
  22. data/lib/ufo/env.rb +1 -1
  23. data/lib/ufo/help.rb +9 -0
  24. data/lib/ufo/help/destroy.md +5 -0
  25. data/lib/ufo/help/docker.md +4 -0
  26. data/lib/ufo/help/docker/base.md +9 -0
  27. data/lib/ufo/help/docker/build.md +6 -0
  28. data/lib/ufo/help/docker/clean.md +14 -0
  29. data/lib/ufo/help/docker/name.md +5 -0
  30. data/lib/ufo/help/init.md +11 -0
  31. data/lib/ufo/help/scale.md +5 -0
  32. data/lib/ufo/help/ship.md +17 -0
  33. data/lib/ufo/help/ships.md +18 -0
  34. data/lib/ufo/help/task.md +10 -0
  35. data/lib/ufo/help/tasks.md +7 -0
  36. data/lib/ufo/help/tasks/build.md +7 -0
  37. data/lib/ufo/help/tasks/register.md +5 -0
  38. data/lib/ufo/init.rb +2 -3
  39. data/lib/ufo/ship.rb +1 -1
  40. data/lib/ufo/task.rb +5 -1
  41. data/lib/ufo/tasks.rb +2 -3
  42. data/lib/ufo/version.rb +1 -1
  43. data/ufo.gemspec +4 -1
  44. metadata +63 -9
  45. data/lib/ufo/cli/help.rb +0 -124
  46. data/lib/ufo/docker/help.rb +0 -65
  47. data/lib/ufo/tasks/help.rb +0 -26
data/README.md CHANGED
@@ -22,14 +22,6 @@ See [ufoships.com](http://ufoships.com) for full documentation.
22
22
 
23
23
  ## Installation
24
24
 
25
- If you want to quickly install ufo without having to worry about ufo’s dependencies you can simply install the Bolts Toolbelt which has ufo included.
26
-
27
- ```sh
28
- brew cask install boltopslabs/software/bolts
29
- ```
30
-
31
- Or if you prefer you can install ufo with RubyGems
32
-
33
25
  ```sh
34
26
  gem install ufo
35
27
  ```
@@ -6,7 +6,7 @@ Ufo uses a set of naming conventions. This helps enforce some best practices an
6
6
 
7
7
  ### UFO_ENV to ECS Cluster Convention
8
8
 
9
- By default, the ECS cluster value is the same as UFO_ENV's value. So if `UFO_ENV=prod` then the ECS Cluster is prod and if `UFO_ENV=stag` then the ECS Cluster is stag. You can easily override this convention by specifying the `--cluster` CLI option. You can also override this behavior with [settings.yml]({% link _docs/settings.md %}) to spare you from having to type `--cluster` over and over.
9
+ By default, the ECS cluster value is the same as UFO_ENV's value. So if `UFO_ENV=production` then the ECS Cluster is production and if `UFO_ENV=staging` then the ECS Cluster is staging. You can easily override this convention by specifying the `--cluster` CLI option. You can also override this behavior with [settings.yml]({% link _docs/settings.md %}) to spare you from having to type `--cluster` over and over.
10
10
 
11
11
  ### Service and Task Names Convention
12
12
 
@@ -12,6 +12,7 @@ full\_image\_name | The full docker image name that ufo builds. The "base" por
12
12
  dockerfile\_port | Exposed port extracted from the Dockerfile of the project. 
13
13
  env_vars(text) | This method takes a block of text that contains the env values in key=value format and converts that block of text to the proper task definition json format.
14
14
  env_file(path) | This method takes an `.env` file which contains a simple key value list of environment variables and converts the list to the proper task definition json format.
15
+ task_definition_name | The name of the task_definition. So if the code looks like this `task_definition "demo-web" do`, the task_definition_name is "demo-web".
15
16
 
16
17
  To call the helper in task_definitions.rb you must add `helper.` in front. So full\_image\_name  is called via `helper.full_image_name`.
17
18
 
@@ -15,17 +15,18 @@ image: tongueroo/hi
15
15
  clean_keep: 30
16
16
  ecr_keep: 30
17
17
  aws_profile_ufo_env_map:
18
- default: prod
19
- # More examples:
20
- # aws_profile1: prod
21
- # aws_profile2: stag
22
- # aws_profile3: dev
18
+ default: staging
19
+ # # More examples:
20
+ # aws_profile1: production
21
+ # aws_profile2: staging
22
+ # aws_profile3: development
23
+
23
24
  ufo_env_cluster_map:
24
- default: prod
25
- # More examples:
26
- # aws_profile1: prod
27
- # aws_profile2: stag
28
- # aws_profile3: dev
25
+ default: production
26
+ # # More examples:
27
+ # production: production
28
+ # staging: staging
29
+ # development: development
29
30
  ```
30
31
 
31
32
  The table below covers what each setting does:
@@ -39,19 +40,19 @@ Setting | Description
39
40
 
40
41
  ### UFO_ENV to ECS Cluster Mapping
41
42
 
42
- The `ufo_env_cluster_map` option allows you to override the [UFO_ENV to ECS Cluster Convention]({% link _docs/conventions.md %}). Normally, the ECS cluster defaults to whatever UFO_ENV is set to. For example, when `UFO_ENV=prod` the ECS Cluster is prod and when `UFO_ENV=stag` the ECS Cluster is stag. This setting allows you to override this behavior so that you do not have to specify the `--cluster` CLI option repeatedly. Let's go through an example:
43
+ The `ufo_env_cluster_map` option allows you to override the [UFO_ENV to ECS Cluster Convention]({% link _docs/conventions.md %}). Normally, the ECS cluster defaults to whatever UFO_ENV is set to. For example, when `UFO_ENV=production` the ECS Cluster is production and when `UFO_ENV=staging` the ECS Cluster is staging. This setting allows you to override this behavior so that you do not have to specify the `--cluster` CLI option repeatedly. Let's go through an example:
43
44
 
44
45
  By default:
45
46
 
46
47
  ```sh
47
- UFO_ENV=prod ufo ship hi-web # cluster defaults to UFO_ENV which is prod
48
- UFO_ENV=prod ufo ship hi-web --cluster prod # same as above
48
+ UFO_ENV=production ufo ship hi-web # cluster defaults to UFO_ENV which is prod
49
+ UFO_ENV=production ufo ship hi-web --cluster prod # same as above
49
50
  ```
50
51
 
51
52
  Override the convention and explicitly specify the `--cluster` option in the CLI.
52
53
 
53
54
  ```sh
54
- UFO_ENV=prod ufo ship hi-web --cluster custom-cluster # override the default UFO_ENV TO cluster mapping
55
+ UFO_ENV=production ufo ship hi-web --cluster custom-cluster # override the default UFO_ENV TO cluster mapping
55
56
  ```
56
57
 
57
58
  We can also override the convention with `settings.yml`:
@@ -64,7 +65,7 @@ ufo_env_cluster_map:
64
65
  Because of the `ufo_env_cluster_map` setting, the `--cluster` CLI option is not longer required:
65
66
 
66
67
  ```sh
67
- UFO_ENV=prod ufo ship hi-web # same as --cluster custom-cluster because of settings.yml
68
+ UFO_ENV=production ufo ship hi-web # same as --cluster custom-cluster because of settings.yml
68
69
  ```
69
70
 
70
71
  ### AWS_PROFILE TO UFO_ENV Mapping
@@ -73,23 +74,23 @@ An interesting way to set `UFO_ENV` is with the `aws_profile_ufo_env_map` in `uf
73
74
 
74
75
  ```yaml
75
76
  aws_profile_ufo_env_map:
76
- default: dev
77
- my-prod-profile: prod
78
- my-stag-profile: stag
77
+ default: development
78
+ my-prod-profile: production
79
+ my-stag-profile: staging
79
80
  ```
80
81
 
81
82
  In this case, when you set `AWS_PROFILE` to switch AWS profiles, ufo picks this up and maps the `AWS_PROFILE` value to the specified `UFO_ENV` using the `aws_profile_ufo_env_map` lookup. Example:
82
83
 
83
84
  ```sh
84
- AWS_PROFILE=my-prod-profile => UFO_ENV=prod
85
- AWS_PROFILE=my-stag-profile => UFO_ENV=stag
86
- AWS_PROFILE=default => UFO_ENV=dev
87
- AWS_PROFILE=whatever => UFO_ENV=dev
85
+ AWS_PROFILE=my-prod-profile => UFO_ENV=production
86
+ AWS_PROFILE=my-stag-profile => UFO_ENV=staging
87
+ AWS_PROFILE=default => UFO_ENV=development
88
+ AWS_PROFILE=whatever => UFO_ENV=development
88
89
  ```
89
90
 
90
- Notice how `AWS_PROFILE=whatever` results in `UFO_ENV=dev`. This is because the `default: dev` map is specially treated. If you set the `default` map, this becomes the default value when the profile map is not specified in the rest of `ufo/settings.yml`.
91
+ Notice how `AWS_PROFILE=whatever` results in `UFO_ENV=development`. This is because the `default: development` map is specially treated. If you set the `default` map, this becomes the default value when the profile map is not specified in the rest of `ufo/settings.yml`.
91
92
 
92
- This behavior prevents you from switching `AWS_PROFILE`s and then accidentally deploying a production based docker image to staging and vice versas because you forgot to also switch `LONO_ENV` to its respective environment.
93
+ This behavior prevents you from switching `AWS_PROFILE`s and then accidentally deploying a production based docker image to staging and vice versas because you forgot to also switch `UFO_ENV` to its respective environment.
93
94
 
94
95
 
95
96
  <a id="prev" class="btn btn-basic" href="{% link _docs/ufo-help.md %}">Back</a>
@@ -14,7 +14,7 @@ By convention, ufo will ship the docker container to an ECS cluster with the sam
14
14
 
15
15
  ```sh
16
16
  ufo ship hi-web --cluster prod
17
- UFO_ENV=prod ufo ship hi-web --cluster prod
17
+ UFO_ENV=production ufo ship hi-web --cluster prod
18
18
  ```
19
19
 
20
20
  When you run `ufo ship hi-web`:
@@ -15,13 +15,13 @@ The `UFO_ENV` can be set easily in several ways:
15
15
  ### At the CLI Command
16
16
 
17
17
  ```sh
18
- UFO_ENV=prod ufo ship hi-web --cluster prod
18
+ UFO_ENV=production ufo ship hi-web --cluster prod
19
19
  ```
20
20
 
21
21
  ### As an environment variable
22
22
 
23
23
  ```sh
24
- export UFO_ENV=prod
24
+ export UFO_ENV=production
25
25
  ufo ship hi-web --cluster prod
26
26
  ```
27
27
 
@@ -33,21 +33,21 @@ The most interesting way to set `UFO_ENV` is with the `aws_profile_ufo_env_map`
33
33
 
34
34
  ```yaml
35
35
  aws_profile_ufo_env_map:
36
- default: dev
37
- my-prod-profile: prod
38
- my-stag-profile: stag
36
+ default: development
37
+ my-prod-profile: production
38
+ my-stag-profile: staging
39
39
  ```
40
40
 
41
41
  In this case, when you set `AWS_PROFILE` to switch AWS profiles, ufo picks this up and maps the `AWS_PROFILE` value to the specified `UFO_ENV` using the `aws_profile_ufo_env_map` lookup. Example:
42
42
 
43
43
  ```sh
44
- AWS_PROFILE=my-prod-profile => UFO_ENV=prod
45
- AWS_PROFILE=my-stag-profile => UFO_ENV=stag
46
- AWS_PROFILE=default => UFO_ENV=dev
47
- AWS_PROFILE=whatever => UFO_ENV=dev
44
+ AWS_PROFILE=my-prod-profile => UFO_ENV=production
45
+ AWS_PROFILE=my-stag-profile => UFO_ENV=staging
46
+ AWS_PROFILE=default => UFO_ENV=development
47
+ AWS_PROFILE=whatever => UFO_ENV=development
48
48
  ```
49
49
 
50
- Notice how `AWS_PROFILE=whatever` results in `UFO_ENV=dev`. This is because the `default: dev` map is specially treated. If you set the `default` map, this becomes the default value when the profile map is not specified in the rest of `ufo/settings.yml`. More info on settings is available at [settings]({% link _docs/settings.md %}).
50
+ Notice how `AWS_PROFILE=whatever` results in `UFO_ENV=development`. This is because the `default: development` map is specially treated. If you set the `default` map, this becomes the default value when the profile map is not specified in the rest of `ufo/settings.yml`. More info on settings is available at [settings]({% link _docs/settings.md %}).
51
51
 
52
52
  <a id="prev" class="btn btn-basic" href="{% link _docs/settings.md %}">Back</a>
53
53
  <a id="next" class="btn btn-primary" href="{% link _docs/variables.md %}">Next Step</a>
@@ -28,27 +28,27 @@ Shared variables also support a concept called layering. The `config/variables/
28
28
  @environment = helper.env_file(".env")
29
29
  ```
30
30
 
31
- When `ufo ship` is ran with `UFO_ENV=prod` he `config/variables/prod.rb` will be evaluated and layered on top of the variables defined in `base.rb:
31
+ When `ufo ship` is ran with `UFO_ENV=production` he `config/variables/production.rb` will be evaluated and layered on top of the variables defined in `base.rb:
32
32
 
33
- `ufo/variables/prod.rb`:
33
+ `ufo/variables/production.rb`:
34
34
 
35
35
  ```ruby
36
- @environment = helper.env_vars(%Q{
36
+ @environment = helper.env_vars(%Q[
37
37
  RAILS_ENV=production
38
38
  SECRET_KEY_BASE=secret
39
- })
39
+ ])
40
40
  ```
41
41
 
42
- When `ufo ship` is ran with `UFO_ENV=stag` he `config/variables/stag.rb` will be evaluated and layered on top of the variables defined in `base.rb:
42
+ When `ufo ship` is ran with `UFO_ENV=staging` he `config/variables/staging.rb` will be evaluated and layered on top of the variables defined in `base.rb:
43
43
 
44
44
 
45
- `ufo/variables/prod.rb`:
45
+ `ufo/variables/production.rb`:
46
46
 
47
47
  ```ruby
48
- @environment = helper.env_vars(%Q{
48
+ @environment = helper.env_vars(%Q[
49
49
  RAILS_ENV=staging
50
50
  SECRET_KEY_BASE=secret
51
- })
51
+ ])
52
52
  ```
53
53
 
54
54
 
@@ -1,4 +1,4 @@
1
- FROM ruby:2.3.3
1
+ FROM ruby:2.5.0
2
2
  MAINTAINER Tung Nguyen <tongueroo@gmail.com>
3
3
 
4
4
  # This is just a sample Dockerfile. This is meant to be overriden.
@@ -4,15 +4,15 @@ image: <%= @image %>
4
4
  # ecr_keep: 30
5
5
 
6
6
  # aws_profile_ufo_env_map:
7
- # default: prod
7
+ # default: staging
8
8
  # # More examples:
9
- # aws_profile1: prod
10
- # aws_profile2: stag
11
- # aws_profile3: dev
9
+ # aws_profile1: production
10
+ # aws_profile2: staging
11
+ # aws_profile3: development
12
12
 
13
13
  # ufo_env_cluster_map:
14
14
  # default: prod
15
15
  # # More examples:
16
- # aws_profile1: prod
17
- # aws_profile2: stag
18
- # aws_profile3: dev
16
+ # production: prod
17
+ # staging: stag
18
+ # development: dev
@@ -1,11 +1,12 @@
1
- # There will be some special variables that are automatically available in this file.
1
+ # There some built-in helpers that are automatically available in this file.
2
2
  #
3
- # Some of variables are from the Dockerfile and some are from other places.
3
+ # Some of helpers get data from the Dockerfile and some are from other places.
4
+ # Here's a summary of the some helpers:
4
5
  #
5
- # * helper.full_image_name - Docker image name with the tag when docker image is built by ufo. This is defined in ufo/settings.yml. The helper.full_image_name includes the git sha tongueroo/hi:ufo-[sha].
6
- # * helper.dockerfile_port - Expose port in the Dockerfile. Only supports one exposed port, the first one that is encountered.
7
- #
8
- # helper.env_vars - is a helper method that generates the proper environment Array of Hashes
6
+ # full_image_name
7
+ # dockerfile_port
8
+ # env_vars(text)
9
+ # env_file(path)
9
10
  #
10
11
  # More info: http://ufoships.com/docs/helpers/
11
12
  #
@@ -18,7 +19,8 @@ task_definition "<%= @app %>-web" do
18
19
  # uncomment out to set the log group
19
20
  # awslogs_group: "<%= @app %>-web",
20
21
  # awslogs_stream_prefix: "<%= @app %>",
21
- command: ["bin/web"]
22
+ # awslogs_region: "us-east-1",
23
+ # command: ["bin/web"] # IMPORTANT: change or create a bin/web file
22
24
  )
23
25
  end
24
26
 
@@ -30,7 +32,8 @@ task_definition "<%= @app %>-worker" do
30
32
  # uncomment out to set the log group
31
33
  # awslogs_group: "<%= @app %>-worker",
32
34
  # awslogs_stream_prefix: "<%= @app %>",
33
- command: ["bin/worker"]
35
+ # awslogs_region: "us-east-1",
36
+ # command: ["bin/worker"] # IMPORTANT: change or create a bin/worker file
34
37
  )
35
38
  end
36
39
 
@@ -42,6 +45,7 @@ task_definition "<%= @app %>-clock" do
42
45
  # uncomment out to set the log group
43
46
  # awslogs_group: "<%= @app %>-clock",
44
47
  # awslogs_stream_prefix: "<%= @app %>",
45
- command: ["bin/clock"]
48
+ # awslogs_region: "us-east-1",
49
+ # command: ["bin/clock"] # IMPORTANT: change or create a bin/clock file
46
50
  )
47
51
  end
@@ -1,7 +1,7 @@
1
- # Example ufo/variables/prod.rb
1
+ # Example ufo/variables/development.rb
2
2
  # More info on how variables work: http://ufoships.com/docs/variables/
3
3
  @cpu = 192
4
- @environment = helper.env_vars(%Q{
5
- RAILS_ENV=staging
4
+ @environment = helper.env_vars(%Q[
5
+ RAILS_ENV=development
6
6
  SECRET_KEY_BASE=secret
7
- })
7
+ ])
@@ -1,7 +1,7 @@
1
- # Example ufo/variables/prod.rb
1
+ # Example ufo/variables/production.rb
2
2
  # More info on how variables work: http://ufoships.com/docs/variables/
3
3
  @cpu = 256
4
- @environment = helper.env_vars(%Q{
4
+ @environment = helper.env_vars(%Q[
5
5
  RAILS_ENV=production
6
6
  SECRET_KEY_BASE=secret
7
- })
7
+ ])
data/lib/ufo.rb CHANGED
@@ -13,6 +13,7 @@ module Ufo
13
13
  autoload :Util, 'ufo/util'
14
14
  autoload :Init, 'ufo/init'
15
15
  autoload :CLI, 'ufo/cli'
16
+ autoload :Help, 'ufo/help'
16
17
  autoload :Ship, 'ufo/ship'
17
18
  autoload :Task, 'ufo/task'
18
19
  autoload :Destroy, 'ufo/destroy'
@@ -1,4 +1,7 @@
1
- require 'aws-sdk'
1
+ require "aws-sdk-ecs"
2
+ require "aws-sdk-ec2"
3
+ require "aws-sdk-elasticloadbalancingv2"
4
+ require "aws-sdk-cloudwatchlogs"
2
5
 
3
6
  module Ufo
4
7
  module AwsServices
@@ -1,6 +1,5 @@
1
1
  require 'thor'
2
2
  require 'ufo/command'
3
- require 'ufo/cli/help'
4
3
 
5
4
  module Ufo
6
5
  class CLI < Command
@@ -11,17 +10,17 @@ module Ufo
11
10
  class_option :cluster, desc: "Cluster. Overrides ufo/settings.yml."
12
11
 
13
12
  desc "docker [ACTION]", "docker related tasks"
14
- long_desc Help.docker
13
+ long_desc Help.text(:docker)
15
14
  subcommand "docker", Docker
16
15
 
17
16
  desc "tasks [ACTION]", "task definition related tasks"
18
- long_desc Help.tasks
17
+ long_desc Help.text(:tasks)
19
18
  subcommand "tasks", Tasks
20
19
 
21
20
  desc "init", "setup initial ufo files"
22
21
  option :image, type: :string, required: true, desc: "Docker image name without the tag. Example: tongueroo/hi. Configures ufo/settings.yml"
23
22
  option :app, type: :string, required: true, desc: "App name. Preferably one word. Used in the generated ufo/task_definitions.rb."
24
- long_desc Help.init
23
+ long_desc Help.text(:init)
25
24
  def init
26
25
  Init.new(options).setup
27
26
  end
@@ -40,7 +39,7 @@ module Ufo
40
39
  end
41
40
 
42
41
  desc "ship [SERVICE]", "builds and ships container image to the ECS service"
43
- long_desc Help.ship
42
+ long_desc Help.text(:ship)
44
43
  ship_options.call
45
44
  def ship(service)
46
45
  builder = build_docker
@@ -55,7 +54,7 @@ module Ufo
55
54
  end
56
55
 
57
56
  desc "ships [LIST-OF-SERVICES]", "builds and ships same container image to multiple ECS services"
58
- long_desc Help.ships
57
+ long_desc Help.text(:ships)
59
58
  ship_options.call
60
59
  def ships(*services)
61
60
  builder = build_docker
@@ -73,7 +72,7 @@ module Ufo
73
72
  end
74
73
 
75
74
  desc "task [TASK_DEFINITION]", "runs a one time task"
76
- long_desc Help.task
75
+ long_desc Help.text(:task)
77
76
  option :docker, type: :boolean, desc: "Enable docker build and push", default: true
78
77
  option :command, type: :array, desc: "Override the command used for the container"
79
78
  def task(task_definition)
@@ -83,7 +82,7 @@ module Ufo
83
82
  end
84
83
 
85
84
  desc "destroy [SERVICE]", "destroys the ECS service"
86
- long_desc Help.destroy
85
+ long_desc Help.text(:destroy)
87
86
  option :sure, type: :boolean, desc: "By pass are you sure prompt."
88
87
  def destroy(service)
89
88
  task_definition = options[:task] || service # convention
@@ -91,14 +90,14 @@ module Ufo
91
90
  end
92
91
 
93
92
  desc "scale [SERVICE] [COUNT]", "scale the ECS service"
94
- long_desc Help.scale
93
+ long_desc Help.text(:scale)
95
94
  def scale(service, count)
96
95
  Scale.new(service, count, options).update
97
96
  end
98
97
 
99
98
  desc "version", "Prints version number of installed ufo"
100
99
  def version
101
- puts Ufo::VERSION
100
+ puts VERSION
102
101
  end
103
102
 
104
103
  no_tasks do
@@ -1,3 +1,18 @@
1
+ require "thor"
2
+
3
+ # Override thor's long_desc identation behavior
4
+ # https://github.com/erikhuda/thor/issues/398
5
+ class Thor
6
+ module Shell
7
+ class Basic
8
+ def print_wrapped(message, options = {})
9
+ message = "\n#{message}" unless message[0] == "\n"
10
+ stdout.puts message
11
+ end
12
+ end
13
+ end
14
+ end
15
+
1
16
  module Ufo
2
17
  class Command < Thor
3
18
  class << self
@@ -16,6 +31,14 @@ module Ufo
16
31
  args -= help_flags
17
32
  args.insert(-2, "help")
18
33
  end
34
+
35
+ # ufo --version
36
+ # ufo -v
37
+ version_flags = ["-v", "--version"]
38
+ if args.length == 1 && !(args & version_flags).empty?
39
+ args = ["version"]
40
+ end
41
+
19
42
  super
20
43
  end
21
44
  end