envirobly 0.5.2 → 0.6.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7cbc25ee0033c84e86fd94e67a3be65ee43c8fbcfd86cd962ecf9e5f616bf042
4
- data.tar.gz: e07002a42e3490bd841f6538ab7cd565990bf55e159fe8d7ce033cff62f6c38d
3
+ metadata.gz: 3e30e5017a85588ff1c6122ffb0a3fbb13b132793ca8a53a25b05e3402cdebc5
4
+ data.tar.gz: ff5049f4c3f9679586cfa6595ac52070eaaf8e10e34a9f96ec054a3df583e9c5
5
5
  SHA512:
6
- metadata.gz: eb490ba6309b3775f548522596c6a5d42504ba2ca878ef8c74b530af12733b9a9ac1ce016ece2afdb7d6c616f4121ca418a49ef3037e06790a9e3da3b916ba93
7
- data.tar.gz: 7abc4689844be2617b74bb425c0ba8136b793d5c0c36600d58defdeadf8a84e9b31715442467c1e912b8988ee1c708c61eedb0192a2af3eadf9fc0b54bf0a327
6
+ metadata.gz: d4aa3b80f59d1dbe19a045e802a36341d7b7393ec7320c9382fecbaa3f8182800b86b6b25bb1af02ff69badc3efb1fd200e2229314b20ed8960ed894f567d562
7
+ data.tar.gz: fa4076c20c3cda9c05a6c356ea125aec3879ce68b4448c6becda3448ce8cb8a37c0dc8525fa8f4f4fdd85161e01a18efaad78dde37bfc80b4e4ebe15b85d84f1
@@ -4,6 +4,25 @@ class Envirobly::Cli::Main < Envirobly::Base
4
4
  puts Envirobly::VERSION
5
5
  end
6
6
 
7
+ desc "validate", "Validates config"
8
+ def validate
9
+ commit = Envirobly::Git::Unstaged.new
10
+ config = Envirobly::Config.new(commit)
11
+ config.validate
12
+
13
+ if config.errors.any?
14
+ puts "Issues found validating `#{Envirobly::Config::PATH}`:"
15
+ puts
16
+ config.errors.each_with_index do |error, index|
17
+ puts " #{index + 1}. #{error}"
18
+ end
19
+ puts
20
+ exit 1
21
+ else
22
+ puts "All checks pass."
23
+ end
24
+ end
25
+
7
26
  desc "deploy ENVIRONMENT", "Deploy to environment identified by name or URL"
8
27
  method_option :commit, type: :string, default: "HEAD"
9
28
  method_option :dry_run, type: :boolean, default: false
@@ -15,7 +34,9 @@ class Envirobly::Cli::Main < Envirobly::Base
15
34
  desc "set_access_token TOKEN", "Save and use an access token generated at Envirobly"
16
35
  def set_access_token
17
36
  token = ask("Access Token:", echo: false).strip
18
- if token == ""
37
+
38
+ if token.blank?
39
+ $stderr.puts
19
40
  $stderr.puts "Token can't be empty."
20
41
  exit 1
21
42
  end
@@ -11,9 +11,10 @@ class Envirobly::Config
11
11
  def initialize(commit)
12
12
  @commit = commit
13
13
  @errors = []
14
- @result = nil
14
+ @result = {}
15
15
  @project_url = nil
16
16
  @raw = @commit.file_content PATH
17
+ @project = parse
17
18
  end
18
19
 
19
20
  def dig(*args)
@@ -22,14 +23,21 @@ class Envirobly::Config
22
23
  nil
23
24
  end
24
25
 
26
+ def validate
27
+ return unless @project
28
+ validate_top_level_keys
29
+ validate_services @project.fetch(:services)
30
+ validate_environments
31
+ end
32
+
25
33
  def compile(environment = nil)
34
+ return unless @project
26
35
  @environment = environment
27
- return unless @project = parse
36
+ @result = @project.slice(:services)
28
37
  set_project_url
29
38
  merge_environment_overrides! unless @environment.nil?
30
39
  transform_env_var_values!
31
40
  append_image_tags!
32
- @result = @project.slice(:services)
33
41
  end
34
42
 
35
43
  def to_deployment_params
@@ -58,16 +66,13 @@ class Envirobly::Config
58
66
 
59
67
  def set_project_url
60
68
  @project_url = dig :project
61
- if @project_url.blank?
62
- @errors << "Missing `project: <url>` top level attribute."
63
- end
64
69
  end
65
70
 
66
71
  def transform_env_var_values!
67
- @project.fetch(:services, {}).each do |name, service|
72
+ @result[:services].each do |name, service|
68
73
  service.fetch(:env, {}).each do |key, value|
69
74
  if value.is_a?(Hash) && value.has_key?(:file)
70
- @project[:services][name][:env][key] = @commit.file_content(value.fetch(:file)).strip
75
+ @result[:services][name][:env][key] = @commit.file_content(value.fetch(:file)).strip
71
76
  end
72
77
  end
73
78
  end
@@ -79,21 +84,19 @@ class Envirobly::Config
79
84
  build_context: [ ".", :dir_exists? ]
80
85
  }
81
86
  def append_image_tags!
82
- @project.fetch(:services, {}).each do |name, service|
87
+ @result[:services].each do |name, service|
83
88
  next if NON_BUILDABLE_TYPES.include?(service[:type]) || service[:image].present?
84
89
  checksums = []
85
90
 
86
91
  BUILD_DEFAULTS.each do |attribute, options|
87
92
  value = service.fetch(attribute, options.first)
88
- unless @commit.public_send(options.second, value)
89
- @errors << "Service `#{name}` specifies `#{attribute}` as `#{value}` which doesn't exist in this commit."
90
- else
93
+ if @commit.public_send(options.second, value)
91
94
  checksums << @commit.objects_with_checksum_at(value)
92
95
  end
93
96
  end
94
97
 
95
98
  if checksums.size == 2
96
- @project[:services][name][:image_tag] = Digest::SHA1.hexdigest checksums.to_json
99
+ @result[:services][name][:image_tag] = Digest::SHA1.hexdigest checksums.to_json
97
100
  end
98
101
  end
99
102
  end
@@ -102,13 +105,106 @@ class Envirobly::Config
102
105
  return unless services = @project.dig(:environments, @environment.to_sym)
103
106
  services.each do |name, service|
104
107
  service.each do |attribute, value|
105
- if value.is_a?(Hash) && @project[:services][name][attribute].is_a?(Hash)
106
- @project[:services][name][attribute].merge! value
107
- @project[:services][name][attribute].compact!
108
+ if value.is_a?(Hash) && @result[:services][name][attribute].is_a?(Hash)
109
+ @result[:services][name][attribute].merge! value
110
+ @result[:services][name][attribute].compact!
108
111
  else
109
- @project[:services][name][attribute] = value
112
+ @result[:services][name][attribute] = value
110
113
  end
111
114
  end
112
115
  end
113
116
  end
117
+
118
+ VALID_TOP_LEVEL_KEYS = %i[ project services environments ]
119
+ def validate_top_level_keys
120
+ unless @project.is_a?(Hash)
121
+ @errors << "Config doesn't contain a top level hash structure."
122
+ return
123
+ end
124
+
125
+ @errors << "Missing `project: <url>` top level attribute." if @project[:project].blank?
126
+
127
+ @project.keys.each do |key|
128
+ unless VALID_TOP_LEVEL_KEYS.include?(key)
129
+ @errors << "Top level key `#{key}` is not allowed. Allowed keys: #{VALID_TOP_LEVEL_KEYS.map{ "`#{_1}`" }.join(", ")}."
130
+ end
131
+ end
132
+ end
133
+
134
+ VALID_SERVICE_KEYS = %i[
135
+ type
136
+ image
137
+ engine_version
138
+ instance_type
139
+ min_instances
140
+ max_instances
141
+ volume_size
142
+ volume_mount
143
+ dockerfile
144
+ build_context
145
+ command
146
+ release_command
147
+ env
148
+ health_check
149
+ private
150
+ aliases
151
+ ]
152
+ NAME_FORMAT = /\A[a-z0-9\-_]+\z/
153
+ def validate_services(services)
154
+ unless services.is_a?(Hash)
155
+ @errors << "`services` key must be a hash."
156
+ return
157
+ end
158
+
159
+ services.each do |name, service|
160
+ unless name =~ NAME_FORMAT
161
+ @errors << "`#{name}` is not a valid service name. Allowed characters: a-z, 0-9, -, _"
162
+ end
163
+
164
+ unless service.is_a?(Hash)
165
+ @errors << "Service `#{name}` must be a hash."
166
+ next
167
+ end
168
+
169
+ service.each do |attribute, value|
170
+ unless VALID_SERVICE_KEYS.include?(attribute)
171
+ @errors << "Service `#{name}` attribute `#{attribute}` is not a valid attribute."
172
+ end
173
+ end
174
+
175
+ BUILD_DEFAULTS.each do |attribute, options|
176
+ value = service.fetch(attribute, options.first)
177
+ unless @commit.public_send(options.second, value)
178
+ @errors << "Service `#{name}` specifies `#{attribute}` as `#{value}` which doesn't exist in this commit."
179
+ end
180
+ end
181
+
182
+ service.fetch(:env, {}).each do |key, value|
183
+ if value.is_a?(Hash) && value.has_key?(:file)
184
+ unless @commit.file_exists?(value.fetch(:file))
185
+ @errors << "Environment variable `#{key}` referring to a file `#{value.fetch(:file)}` doesn't exist in this commit."
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ def validate_environments
193
+ return unless @project.has_key?(:environments)
194
+
195
+ environments = @project.fetch :environments, nil
196
+
197
+ unless environments.is_a?(Hash)
198
+ @errors << "`environments` key must be a hash."
199
+ return
200
+ end
201
+
202
+ environments.each do |environment, services|
203
+ unless environment =~ NAME_FORMAT
204
+ @errors << "`#{environment}` is not a valid environment name. Allowed characters: a-z, 0-9, -, _"
205
+ end
206
+
207
+ validate_services services
208
+ end
209
+ end
114
210
  end
@@ -8,7 +8,7 @@ class Envirobly::Deployment
8
8
  end
9
9
 
10
10
  config = Envirobly::Config.new(commit)
11
- config.compile(environment)
11
+ config.validate
12
12
 
13
13
  if config.errors.any?
14
14
  $stderr.puts "Errors found while parsing #{Envirobly::Config::PATH}:"
@@ -21,6 +21,7 @@ class Envirobly::Deployment
21
21
  exit 1
22
22
  end
23
23
 
24
+ config.compile(environment)
24
25
  params = config.to_deployment_params
25
26
 
26
27
  puts "Deployment config:"
@@ -0,0 +1,17 @@
1
+ class Envirobly::Git::Unstaged < Envirobly::Git::Commit
2
+ def initialize(working_dir: Dir.getwd)
3
+ @working_dir = working_dir
4
+ end
5
+
6
+ def file_exists?(path)
7
+ File.exist? path
8
+ end
9
+
10
+ def dir_exists?(path)
11
+ Dir.exist? path
12
+ end
13
+
14
+ def file_content(path)
15
+ File.read path
16
+ end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module Envirobly
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: envirobly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Starsi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-20 00:00:00.000000000 Z
11
+ date: 2024-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -130,6 +130,7 @@ files:
130
130
  - lib/envirobly/deployment.rb
131
131
  - lib/envirobly/git.rb
132
132
  - lib/envirobly/git/commit.rb
133
+ - lib/envirobly/git/unstaged.rb
133
134
  - lib/envirobly/version.rb
134
135
  homepage: https://github.com/envirobly/envirobly-cli
135
136
  licenses: