satorix 0.0.1 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![build](http://gitlab.iexposure.com/satorix/satorix/badges/master/build.svg)](http://gitlab.iexposure.com/satorix/satorix/pipelines)
|
6
|
+
[![coverage](http://gitlab.iexposure.com/satorix/satorix/badges/master/coverage.svg)](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
|