satorix 0.0.1 → 1.5.3
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 +5 -5
- data/.gitignore +4 -1
- data/.gitlab-ci.yml +45 -0
- data/.rspec +2 -1
- data/.rubocop.yml +11 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +25 -0
- data/Procfile +1 -0
- data/README.md +93 -1
- data/Rakefile +8 -4
- data/bin/console +3 -3
- data/bin/satorix +8 -0
- data/lib/satorix/CI/deploy/flynn/environment_variables.rb +123 -0
- data/lib/satorix/CI/deploy/flynn/resources.rb +79 -0
- data/lib/satorix/CI/deploy/flynn/routes.rb +267 -0
- data/lib/satorix/CI/deploy/flynn/scale.rb +52 -0
- data/lib/satorix/CI/deploy/flynn.rb +132 -0
- data/lib/satorix/CI/shared/buildpack_manager/buildpack.rb +159 -0
- data/lib/satorix/CI/shared/buildpack_manager.rb +220 -0
- data/lib/satorix/CI/shared/ruby/gem_manager.rb +80 -0
- data/lib/satorix/CI/shared/yarn_manager.rb +25 -0
- data/lib/satorix/CI/test/python/django_test.rb +38 -0
- data/lib/satorix/CI/test/python/safety.rb +30 -0
- data/lib/satorix/CI/test/ruby/brakeman.rb +35 -0
- data/lib/satorix/CI/test/ruby/bundler_audit.rb +35 -0
- data/lib/satorix/CI/test/ruby/cucumber.rb +29 -0
- data/lib/satorix/CI/test/ruby/rails_test.rb +29 -0
- data/lib/satorix/CI/test/ruby/rspec.rb +29 -0
- data/lib/satorix/CI/test/ruby/rubocop.rb +98 -0
- data/lib/satorix/CI/test/shared/database.rb +74 -0
- data/lib/satorix/shared/console.rb +157 -0
- data/lib/satorix/version.rb +1 -1
- data/lib/satorix.rb +343 -2
- data/satorix/CI/deploy/ie_gem_server.rb +80 -0
- data/satorix/CI/deploy/rubygems.rb +81 -0
- data/satorix/custom.rb +21 -0
- data/satorix.gemspec +13 -11
- metadata +57 -29
- data/.travis.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9088dfa5e536b94cd4ab988c4201161bb2d830a7ff2417885cd51819457d5b46
|
4
|
+
data.tar.gz: 184dcbd4d9ed1c939e293a1186ea9db8189d9cc527e9db3f75add9b02b02dc94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 803dd33cf23c8febee87bb48c0546b304afb1b286be05827a171e4a08bbc23e7c2967692f819d89ea255d3ca751d0052dd38ad0bb7a44e8268bffe4a51745bca
|
7
|
+
data.tar.gz: c1b2517847dc98193ec4fe56383299d803aff291a5858fa2e1057753ae1c4ecf2031093e453e510a58442d38c4fc5ea01c6e84841fed870a201de40d782c9cdd
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
image: 'satorix/base'
|
2
|
+
|
3
|
+
cache:
|
4
|
+
key: "$CI_PROJECT_ID"
|
5
|
+
paths:
|
6
|
+
- 'tmp/satorix/cache' # To cache buildpack gems between runs.
|
7
|
+
|
8
|
+
|
9
|
+
.satorix: &satorix
|
10
|
+
script:
|
11
|
+
- gem install satorix --source https://gems.iexposure.com --no-document
|
12
|
+
- satorix
|
13
|
+
|
14
|
+
|
15
|
+
# bundler-audit
|
16
|
+
# Patch-level verification for Bundler
|
17
|
+
# https://github.com/rubysec/bundler-audit
|
18
|
+
bundler_audit:
|
19
|
+
<<: *satorix
|
20
|
+
|
21
|
+
|
22
|
+
# RSpec
|
23
|
+
# Behaviour Driven Development for Ruby
|
24
|
+
# http://rspec.info/
|
25
|
+
rspec:
|
26
|
+
<<: *satorix
|
27
|
+
|
28
|
+
|
29
|
+
# RuboCop
|
30
|
+
# A Ruby static code analyzer, based on the community Ruby style guide.
|
31
|
+
# https://github.com/bbatsov/rubocop
|
32
|
+
rubocop:
|
33
|
+
<<: *satorix
|
34
|
+
allow_failure: true
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
# This is a custom job, defined at satorix/CI/deploy/rubygems.rb
|
39
|
+
deploy_to_rubygems:
|
40
|
+
stage: deploy
|
41
|
+
only:
|
42
|
+
- master
|
43
|
+
except:
|
44
|
+
- schedules
|
45
|
+
<<: *satorix
|
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.6.6
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
satorix (1.5.3)
|
5
|
+
airbrake-ruby
|
6
|
+
bundler (~> 1.13)
|
7
|
+
rake
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
airbrake-ruby (2.0.0)
|
13
|
+
rake (13.0.1)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
satorix!
|
20
|
+
|
21
|
+
RUBY VERSION
|
22
|
+
ruby 2.6.6p146
|
23
|
+
|
24
|
+
BUNDLED WITH
|
25
|
+
1.17.3
|
data/Procfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# This is an empty file, to silence an buildpack warning during testing.
|
data/README.md
CHANGED
@@ -1,3 +1,95 @@
|
|
1
1
|
# Satorix
|
2
2
|
|
3
|
-
By [
|
3
|
+
By [Satorix](https://www.satorix.com/)
|
4
|
+
|
5
|
+
[](http://gitlab.iexposure.com/satorix/satorix/pipelines)
|
6
|
+
[](http://gitlab.iexposure.com/satorix/satorix/pipelines)
|
7
|
+
|
8
|
+
This gem is a commandline tool used to tie together SCM, CI/CD, and hosting environments.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Install Satorix from the command line:
|
13
|
+
|
14
|
+
$ gem install satorix
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
Run Satorix from the command line:
|
19
|
+
|
20
|
+
$ satorix
|
21
|
+
|
22
|
+
Note: Satorix is currently designed to be run via GitLab CI, not locally.
|
23
|
+
|
24
|
+
## Application Preparation
|
25
|
+
|
26
|
+
To prepare your application:
|
27
|
+
|
28
|
+
[Satorix Docs](https://www.satorix.com/docs)
|
29
|
+
|
30
|
+
|
31
|
+
## Development
|
32
|
+
|
33
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
34
|
+
Then, run `bundle exec rspec spec` to run the tests.
|
35
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
36
|
+
|
37
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
38
|
+
|
39
|
+
|
40
|
+
## CI/CD
|
41
|
+
|
42
|
+
Satorix is used to provide continuous integration and continuous deployment for this application.
|
43
|
+
|
44
|
+
CI is run against every push.
|
45
|
+
|
46
|
+
CD is used to automatically build and deploy the gem for the master branch.
|
47
|
+
|
48
|
+
## Environment Variables
|
49
|
+
|
50
|
+
Satorix uses environment variables as an authoritative source for application configuration.
|
51
|
+
|
52
|
+
Environment variables are named with the scheme of PREFIX_BRANCH_KEY.
|
53
|
+
|
54
|
+
|
55
|
+
### Application (AEEV)
|
56
|
+
|
57
|
+
Application-level environment variables are identified by the AEEV prefix (Application Exportable Environment Variable).
|
58
|
+
|
59
|
+
These environment variables are passed to the Satorix Hosting Evnvironment for consumption by the application. A
|
60
|
+
likely use case would be secrets.yml
|
61
|
+
|
62
|
+
The prefix and branch are removed.
|
63
|
+
|
64
|
+
|
65
|
+
* AEEV_PRODUCTION_SECRET_API_KEY
|
66
|
+
* AEEV_STAGING_SECRET_API_KEY
|
67
|
+
|
68
|
+
The variable name passed to the application in the respective environment would be SECRET_API_KEY
|
69
|
+
|
70
|
+
|
71
|
+
### Flynn (FLYNN)
|
72
|
+
|
73
|
+
Environment variables used to configure Flynn are identified by the FLYNN prefix.
|
74
|
+
|
75
|
+
#### Required
|
76
|
+
|
77
|
+
* DOMAIN
|
78
|
+
* KEY
|
79
|
+
* TLSPIN
|
80
|
+
|
81
|
+
#### Optional
|
82
|
+
|
83
|
+
* SCALE
|
84
|
+
* RESOURCES
|
85
|
+
|
86
|
+
### Domain (DDEV, CRT, KEY)
|
87
|
+
|
88
|
+
Domain information can be configured with environment variables identified by the DOMAIN prefix.
|
89
|
+
|
90
|
+
* KEY_PRODUCTION_DOMAINDOM
|
91
|
+
* CRT_PRODUCTION_DOMAINDOM
|
92
|
+
* DDEV_PRODUCTION_DOMAINDOM
|
93
|
+
* KEY_PRODUCTION_DEFAULT
|
94
|
+
* CRT_PRODUCTION_DEFAULT
|
95
|
+
|
data/Rakefile
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
begin
|
3
|
+
require 'rspec/core/rake_task'
|
3
4
|
|
4
|
-
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
6
|
|
6
|
-
task :
|
7
|
+
task default: :spec
|
8
|
+
rescue LoadError
|
9
|
+
# no rspec available
|
10
|
+
end
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'satorix'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "satorix"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start
|
data/bin/satorix
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Satorix
|
4
|
+
module CI
|
5
|
+
module Deploy
|
6
|
+
module Flynn
|
7
|
+
module EnvironmentVariables
|
8
|
+
|
9
|
+
|
10
|
+
def adjust_env_vars
|
11
|
+
ensure_required_env_vars_are_defined unless ENV["SATORIX_#{ current_branch }_ENFORCE_ENV_VAR_DEFINITION"] == 'false'
|
12
|
+
env_unset
|
13
|
+
env_set
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def aeev_key_exists?
|
18
|
+
!(run_command('flynn env', quiet: true) =~ /#{ exported_aeevs_key }=/mi).nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def aeev_prefix
|
23
|
+
# AEEV - Application Exportable Environment Variable
|
24
|
+
"AEEV_#{ current_branch }_"
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def ci_provided_env_vars
|
29
|
+
{}.tap do |vars|
|
30
|
+
ENV.each do |key, value|
|
31
|
+
vars[key.sub(aeev_prefix, '')] = value.sub('***EMPTY_STRING***', '') if key.start_with?(aeev_prefix)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def current_flynn_keys
|
38
|
+
aeev_key_exists? ? run_command("flynn env get #{ exported_aeevs_key }", quiet: true).split : []
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def desired_env_vars
|
43
|
+
ci_provided_env_vars.tap do |vars|
|
44
|
+
vars[exported_aeevs_key] = (vars.keys << exported_aeevs_key).sort.join("\n")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def ensure_required_env_vars_are_defined(configuration_file: 'config/secrets.yml')
|
50
|
+
# TODO : handle new Rails secrets methods, like encrypted secrets
|
51
|
+
if File.file?(configuration_file)
|
52
|
+
secrets = YAML.load_file(configuration_file)
|
53
|
+
|
54
|
+
all_secrets = {}
|
55
|
+
all_secrets.merge!(secrets['shared']) if secrets['shared']
|
56
|
+
all_secrets.merge!(secrets['production']) if secrets['production']
|
57
|
+
|
58
|
+
required = all_secrets.to_yaml.scan(/ENV\[['"](?<var>[A-Z0-9_.]+)['"]\]/).flatten.uniq
|
59
|
+
set = ci_provided_env_vars.keys
|
60
|
+
|
61
|
+
missing = required - set
|
62
|
+
|
63
|
+
if missing.empty?
|
64
|
+
log "All required environment variables from #{ configuration_file } have been defined."
|
65
|
+
else
|
66
|
+
log_error "Environment variables specified in #{ configuration_file } were not defined for the #{ current_branch.downcase } branch."
|
67
|
+
log_error "\nPlease define the following variables in your dashboard:\n#{ missing.join("\n") }\n"
|
68
|
+
log_error_and_abort 'Missing required environment variables.'
|
69
|
+
end
|
70
|
+
else
|
71
|
+
log "No #{ configuration_file } exists, skipping environment variable enforcement."
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def env_set
|
77
|
+
if env_vars_to_set.empty?
|
78
|
+
log 'No new environment variables to set.'
|
79
|
+
else
|
80
|
+
keys_and_values = env_vars_to_set.map { |k, v| "#{ k }=#{ v }" }
|
81
|
+
run_command(['flynn', 'env', 'set', keys_and_values].flatten, filtered_text: env_vars_to_set.values)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def env_unset
|
87
|
+
if env_vars_to_unset.empty?
|
88
|
+
log 'No existing environment variables to unset.'
|
89
|
+
else
|
90
|
+
run_command "flynn env unset #{ env_vars_to_unset.join(' ') }"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def env_vars
|
96
|
+
@_env_vars ||= begin
|
97
|
+
{}.tap do |vars|
|
98
|
+
current_flynn_keys.each { |key| vars[key] = run_command("flynn env get #{ key }", quiet: true).chomp }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
def env_vars_to_set
|
105
|
+
@_env_vars_to_set ||= desired_env_vars.reject { |k, v| env_vars.key?(k) && env_vars[k] == v }
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
def env_vars_to_unset
|
110
|
+
@_env_vars_to_unset ||= env_vars.keys - desired_env_vars.keys
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def exported_aeevs_key
|
115
|
+
'AEEV_KEYS'
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Satorix
|
2
|
+
module CI
|
3
|
+
module Deploy
|
4
|
+
module Flynn
|
5
|
+
module Resources
|
6
|
+
|
7
|
+
|
8
|
+
def add_resources
|
9
|
+
if resources_to_add.empty?
|
10
|
+
log 'No resources to add.'
|
11
|
+
else
|
12
|
+
resources_to_add.each { |resource| run_command "flynn resource add #{ resource }" }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def available_resources
|
18
|
+
%w(postgres mysql mongodb redis)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def current_resource_provider_names
|
23
|
+
resource.split("\n").drop(1).map(&:split).map(&:last)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def desired_resource_provider_names
|
28
|
+
names = ENV[resource_provider_key].to_s.split
|
29
|
+
disallowed = names - available_resources
|
30
|
+
unless disallowed.empty?
|
31
|
+
log_error_and_abort("Invalid resource#{ 's' if disallowed.length > 1 }: #{ disallowed.join(' ') }")
|
32
|
+
end
|
33
|
+
names
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def remove_resources
|
38
|
+
if resources_to_remove.empty?
|
39
|
+
log 'No resources to remove.'
|
40
|
+
else
|
41
|
+
log "The following previously allocated resources are no longer defined in #{ resource_provider_key }:"
|
42
|
+
log resources_to_remove.join(' ')
|
43
|
+
log ''
|
44
|
+
log 'To remove them, use the flynn resource command: https://flynn.io/docs/cli#resource'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def resource
|
50
|
+
run_command('flynn resource', quiet: true).chomp
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def resource_provider_key
|
55
|
+
"FLYNN_#{ current_branch }_RESOURCES"
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def resources_to_add
|
60
|
+
desired_resource_provider_names - current_resource_provider_names
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def resources_to_remove
|
65
|
+
current_resource_provider_names - desired_resource_provider_names
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def set_resources
|
70
|
+
add_resources
|
71
|
+
remove_resources
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|