shipitron 1.2.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.buildkite/pipeline.yml +94 -0
- data/.dockerignore +1 -0
- data/.gitattributes +1 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/Deskfile +15 -0
- data/Dockerfile +40 -15
- data/Dockerfile.release +29 -6
- data/Dockerfile.staging +70 -0
- data/Gemfile +2 -0
- data/README.md +53 -15
- data/docker-compose.yml +54 -0
- data/lib/shipitron.rb +19 -2
- data/lib/shipitron/cli.rb +42 -42
- data/lib/shipitron/client.rb +9 -0
- data/lib/shipitron/client/bootstrap_application.rb +1 -0
- data/lib/shipitron/client/create_ecs_services.rb +7 -7
- data/lib/shipitron/client/deploy_application.rb +2 -0
- data/lib/shipitron/client/ensure_deploy_not_running.rb +2 -1
- data/lib/shipitron/client/fetch_clusters.rb +1 -0
- data/lib/shipitron/client/force_deploy.rb +1 -0
- data/lib/shipitron/client/generate_deploy.rb +41 -0
- data/lib/shipitron/client/load_application_config.rb +17 -0
- data/lib/shipitron/client/load_templates.rb +1 -0
- data/lib/shipitron/client/register_ecs_task_definitions.rb +5 -5
- data/lib/shipitron/client/run_ecs_tasks.rb +101 -72
- data/lib/shipitron/docker_image.rb +4 -1
- data/lib/shipitron/find_docker_volume_name.rb +68 -0
- data/lib/shipitron/git_info.rb +57 -0
- data/lib/shipitron/mustache_yaml_parser.rb +12 -8
- data/lib/shipitron/s3_copy.rb +46 -0
- data/lib/shipitron/server/deploy_application.rb +2 -0
- data/lib/shipitron/server/docker/build_image.rb +4 -1
- data/lib/shipitron/server/docker/configure.rb +46 -10
- data/lib/shipitron/server/docker/push_image.rb +3 -0
- data/lib/shipitron/server/docker/run_build_script.rb +17 -10
- data/lib/shipitron/server/download_build_cache.rb +11 -3
- data/lib/shipitron/server/fetch_deploy.rb +50 -0
- data/lib/shipitron/server/git/clone_local_copy.rb +4 -5
- data/lib/shipitron/server/git/update_cache.rb +2 -1
- data/lib/shipitron/server/run_post_build.rb +40 -1
- data/lib/shipitron/server/transform_cli_args.rb +4 -0
- data/lib/shipitron/server/update_ecs_task_definitions.rb +2 -1
- data/lib/shipitron/server/upload_build_cache.rb +10 -9
- data/lib/shipitron/version.rb +1 -1
- data/scripts/docker-entrypoint.sh +37 -3
- data/scripts/release-entrypoint.sh +20 -0
- data/shipitron.gemspec +11 -8
- data/test.yml +5 -0
- metadata +78 -25
- data/build_dev.sh +0 -27
data/docker-compose.yml
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
version: '3.8'
|
2
|
+
services:
|
3
|
+
shipitron:
|
4
|
+
build: .
|
5
|
+
image: outstand/shipitron:dev
|
6
|
+
environment:
|
7
|
+
FIXUID:
|
8
|
+
FIXGID:
|
9
|
+
volumes:
|
10
|
+
- bundler-data:/usr/local/bundle
|
11
|
+
- ~/dev/app:/app # Set this to the application to be shipitron'd
|
12
|
+
- shipitron-home:/home/shipitron
|
13
|
+
- ~/.config/shipitron:/home/shipitron/.config/shipitron
|
14
|
+
- .:/shipitron
|
15
|
+
|
16
|
+
specs:
|
17
|
+
build: .
|
18
|
+
image: outstand/shipitron:dev
|
19
|
+
command: rspec
|
20
|
+
environment:
|
21
|
+
FOG_LOCAL: 'true'
|
22
|
+
FIXUID:
|
23
|
+
FIXGID:
|
24
|
+
BUILDKITE:
|
25
|
+
BUILDKITE_BUILD_URL:
|
26
|
+
BUILDKITE_JOB_ID:
|
27
|
+
BUILDKITE_AGENT_ACCESS_TOKEN:
|
28
|
+
working_dir: /shipitron
|
29
|
+
volumes:
|
30
|
+
- bundler-data:/usr/local/bundle
|
31
|
+
- fog:/fog
|
32
|
+
- shipitron-home:/home/shipitron
|
33
|
+
- .:/shipitron
|
34
|
+
|
35
|
+
release_gem:
|
36
|
+
image: outstand/shipitron:dev
|
37
|
+
command: rake release
|
38
|
+
working_dir: /shipitron
|
39
|
+
environment:
|
40
|
+
FIXUID:
|
41
|
+
FIXGID:
|
42
|
+
volumes:
|
43
|
+
- bundler-data:/usr/local/bundle
|
44
|
+
- shipitron-home:/home/shipitron
|
45
|
+
- .:/shipitron
|
46
|
+
- ~/.dotfiles/gitconfig:/root/.gitconfig
|
47
|
+
- ~/.dotfiles/gitconfig.user:/root/.gitconfig.user
|
48
|
+
- ~/.ssh/id_rsa:/root/.ssh/id_rsa
|
49
|
+
- ~/.gem:/root/.gem
|
50
|
+
|
51
|
+
volumes:
|
52
|
+
fog:
|
53
|
+
shipitron-home:
|
54
|
+
bundler-data:
|
data/lib/shipitron.rb
CHANGED
@@ -7,6 +7,8 @@ require 'shipitron/smash'
|
|
7
7
|
module Shipitron
|
8
8
|
CONFIG_FILE = 'shipitron/config.yml'.freeze
|
9
9
|
SECRETS_FILE = '~/.config/shipitron/secrets.yml'.freeze
|
10
|
+
GLOBAL_CONFIG_FILE = '~/.config/shipitron/config.yml'.freeze
|
11
|
+
DEPLOY_BUCKET_PREFIX = "deploys/"
|
10
12
|
|
11
13
|
class << self
|
12
14
|
def config_file
|
@@ -18,10 +20,10 @@ module Shipitron
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def config
|
21
|
-
@config ||= Smash.load(Pathname.new(config_file).expand_path.to_s).merge(secrets)
|
23
|
+
@config ||= Smash.load(Pathname.new(config_file).expand_path.to_s).merge(secrets).merge(global_config)
|
22
24
|
rescue ArgumentError
|
23
25
|
Logger.warn "Config file '#{config_file}' does not exist"
|
24
|
-
@config = secrets
|
26
|
+
@config = secrets.merge(global_config)
|
25
27
|
end
|
26
28
|
|
27
29
|
def secrets_file
|
@@ -38,5 +40,20 @@ module Shipitron
|
|
38
40
|
Logger.warn "Secrets file '#{secrets_file}' does not exist"
|
39
41
|
@secrets = Smash.new
|
40
42
|
end
|
43
|
+
|
44
|
+
def global_config_file
|
45
|
+
@global_config_file ||= GLOBAL_CONFIG_FILE
|
46
|
+
end
|
47
|
+
|
48
|
+
def global_config_file=(file)
|
49
|
+
@global_config_file = file
|
50
|
+
end
|
51
|
+
|
52
|
+
def global_config
|
53
|
+
@global_config ||= Smash.load(Pathname.new(global_config_file).expand_path.to_s)
|
54
|
+
rescue ArgumentError
|
55
|
+
Logger.warn "Global config file '#{global_config_file}' does not exist"
|
56
|
+
@global_config = Smash.new
|
57
|
+
end
|
41
58
|
end
|
42
59
|
end
|
data/lib/shipitron/cli.rb
CHANGED
@@ -12,22 +12,26 @@ module Shipitron
|
|
12
12
|
desc 'deploy <app>', 'Deploys the app'
|
13
13
|
option :config_file, default: 'shipitron/config.yml'
|
14
14
|
option :secrets_file, default: '~/.config/shipitron/secrets.yml'
|
15
|
+
option :global_config_file, default: '~/.config/shipitron/config.yml'
|
15
16
|
option :debug, type: :boolean, default: false
|
16
17
|
option :simulate, type: :boolean, default: false
|
18
|
+
option :simulate_store_deploy, type: :boolean, default: false, desc: "Simulate and store deploy config in S3"
|
17
19
|
def deploy(app)
|
18
20
|
setup(
|
19
21
|
config_file: options[:config_file],
|
20
|
-
secrets_file: options[:secrets_file]
|
22
|
+
secrets_file: options[:secrets_file],
|
23
|
+
global_config_file: options[:global_config_file]
|
21
24
|
)
|
22
25
|
|
23
26
|
require 'shipitron/client/deploy_application'
|
24
27
|
result = Client::DeployApplication.call(
|
25
28
|
application: app,
|
26
|
-
simulate: options[:simulate]
|
29
|
+
simulate: options[:simulate],
|
30
|
+
simulate_store_deploy: options[:simulate_store_deploy]
|
27
31
|
)
|
28
32
|
|
29
33
|
if result.failure?
|
30
|
-
result.
|
34
|
+
result.error_messages.each do |error|
|
31
35
|
Logger.fatal error
|
32
36
|
end
|
33
37
|
Logger.fatal 'Deploy failed.'
|
@@ -50,7 +54,7 @@ module Shipitron
|
|
50
54
|
)
|
51
55
|
|
52
56
|
if result.failure?
|
53
|
-
result.
|
57
|
+
result.error_messages.each do |error|
|
54
58
|
Logger.fatal error
|
55
59
|
end
|
56
60
|
Logger.fatal 'Deploy failed.'
|
@@ -59,45 +63,40 @@ module Shipitron
|
|
59
63
|
|
60
64
|
|
61
65
|
desc 'server_deploy', 'Server-side component of deploy'
|
62
|
-
option :
|
63
|
-
option :repository, required: true
|
64
|
-
option :repository_branch, default: 'master'
|
65
|
-
option :bucket, required: true
|
66
|
-
option :build_cache_location, default: 'tmp/build-cache.tar.gz'
|
67
|
-
option :image_name, required: true
|
68
|
-
option :named_tag, default: 'latest'
|
69
|
-
option :region, required: true
|
70
|
-
option :clusters, type: :array, required: true
|
71
|
-
option :ecs_task_defs, type: :array, required: true
|
72
|
-
option :ecs_task_def_templates, type: :array, default: []
|
73
|
-
option :ecs_services, type: :array, default: []
|
74
|
-
option :ecs_service_templates, type: :array, default: []
|
75
|
-
option :build_script, default: nil
|
76
|
-
option :post_builds, type: :array
|
77
|
-
option :secrets_file, default: '~/.config/shipitron/secrets.yml'
|
78
|
-
option :debug, type: :boolean, default: false
|
66
|
+
option :deploy_id, required: true
|
79
67
|
def server_deploy
|
80
|
-
setup
|
81
|
-
|
82
|
-
)
|
68
|
+
setup
|
69
|
+
|
70
|
+
if !ENV.key?("SHIPITRON_DEPLOY_BUCKET") || !ENV.key?("SHIPITRON_DEPLOY_BUCKET_REGION")
|
71
|
+
raise "Missing shipitron deploy bucket env vars!"
|
72
|
+
end
|
73
|
+
|
74
|
+
require 'shipitron/server/fetch_deploy'
|
75
|
+
deploy_options = Server::FetchDeploy.call!(
|
76
|
+
deploy_bucket: ENV["SHIPITRON_DEPLOY_BUCKET"],
|
77
|
+
deploy_bucket_region: ENV["SHIPITRON_DEPLOY_BUCKET_REGION"],
|
78
|
+
deploy_id: options[:deploy_id]
|
79
|
+
).deploy_options
|
83
80
|
|
84
81
|
require 'shipitron/server/transform_cli_args'
|
85
82
|
cli_args = Server::TransformCliArgs.call!(
|
86
|
-
application:
|
87
|
-
repository_url:
|
88
|
-
repository_branch:
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
83
|
+
application: deploy_options[:name],
|
84
|
+
repository_url: deploy_options[:repository],
|
85
|
+
repository_branch: deploy_options[:repository_branch],
|
86
|
+
registry: deploy_options[:registry],
|
87
|
+
s3_cache_bucket: deploy_options[:bucket],
|
88
|
+
build_cache_location: deploy_options[:build_cache_location],
|
89
|
+
image_name: deploy_options[:image_name],
|
90
|
+
named_tag: deploy_options[:named_tag],
|
91
|
+
skip_push: deploy_options[:skip_push],
|
92
|
+
region: deploy_options[:region],
|
93
|
+
clusters: deploy_options[:clusters],
|
94
|
+
ecs_task_defs: deploy_options[:ecs_task_defs],
|
95
|
+
ecs_task_def_templates: deploy_options[:ecs_task_def_templates],
|
96
|
+
ecs_services: deploy_options[:ecs_services],
|
97
|
+
ecs_service_templates: deploy_options[:ecs_service_templates],
|
98
|
+
build_script: deploy_options[:build_script],
|
99
|
+
post_builds: deploy_options[:post_builds]
|
101
100
|
).cli_args
|
102
101
|
|
103
102
|
require 'shipitron/server/deploy_application'
|
@@ -106,7 +105,7 @@ module Shipitron
|
|
106
105
|
)
|
107
106
|
|
108
107
|
if result.failure?
|
109
|
-
result.
|
108
|
+
result.error_messages.each do |error|
|
110
109
|
Logger.fatal error
|
111
110
|
end
|
112
111
|
Logger.fatal 'Deploy failed.'
|
@@ -137,7 +136,7 @@ module Shipitron
|
|
137
136
|
)
|
138
137
|
|
139
138
|
if result.failure?
|
140
|
-
result.
|
139
|
+
result.error_messages.each do |error|
|
141
140
|
Logger.fatal error
|
142
141
|
end
|
143
142
|
Logger.fatal 'Bootstrap failed.'
|
@@ -145,7 +144,7 @@ module Shipitron
|
|
145
144
|
end
|
146
145
|
|
147
146
|
private
|
148
|
-
def setup(config_file:nil, secrets_file:nil)
|
147
|
+
def setup(config_file:nil, secrets_file:nil, global_config_file:nil)
|
149
148
|
$stdout.sync = true
|
150
149
|
if options[:debug] == false
|
151
150
|
Logger.level = :info
|
@@ -153,6 +152,7 @@ module Shipitron
|
|
153
152
|
|
154
153
|
Shipitron.config_file = config_file unless config_file.nil?
|
155
154
|
Shipitron.secrets_file = secrets_file unless secrets_file.nil?
|
155
|
+
Shipitron.global_config_file = global_config_file unless global_config_file.nil?
|
156
156
|
end
|
157
157
|
end
|
158
158
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'shipitron'
|
2
|
+
require 'shipitron/client'
|
2
3
|
require 'shipitron/ecs_client'
|
3
4
|
require 'shipitron/mustache_yaml_parser'
|
4
5
|
require 'securerandom'
|
@@ -29,13 +30,12 @@ module Shipitron
|
|
29
30
|
|
30
31
|
service_def = Smash.load(
|
31
32
|
path.to_s,
|
32
|
-
parser: MustacheYamlParser
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
)
|
33
|
+
parser: MustacheYamlParser,
|
34
|
+
context: {
|
35
|
+
cluster: cluster_name,
|
36
|
+
revision: nil, # ECS will default to latest ACTIVE
|
37
|
+
count: service_count
|
38
|
+
}
|
39
39
|
).merge(
|
40
40
|
client_token: SecureRandom.uuid
|
41
41
|
)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'shipitron'
|
2
|
+
require 'shipitron/client'
|
2
3
|
require 'shipitron/client/load_application_config'
|
3
4
|
require 'shipitron/client/load_templates'
|
4
5
|
require 'shipitron/client/fetch_clusters'
|
@@ -13,6 +14,7 @@ module Shipitron
|
|
13
14
|
|
14
15
|
required :application
|
15
16
|
optional :simulate
|
17
|
+
optional :simulate_store_deploy
|
16
18
|
|
17
19
|
organize [
|
18
20
|
LoadApplicationConfig,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'shipitron'
|
2
|
+
require 'shipitron/client'
|
2
3
|
require 'shipitron/ecs_client'
|
3
4
|
|
4
5
|
# Note: This is a best effort client side check to make sure there
|
@@ -21,7 +22,7 @@ module Shipitron
|
|
21
22
|
begin
|
22
23
|
response = ecs_client(region: cluster.region).list_tasks(
|
23
24
|
cluster: cluster.name,
|
24
|
-
started_by:
|
25
|
+
started_by: Shipitron::Client.started_by,
|
25
26
|
max_results: 1,
|
26
27
|
desired_status: status
|
27
28
|
)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'shipitron'
|
2
|
+
require 'shipitron/client'
|
3
|
+
require 'shipitron/fetch_bucket'
|
4
|
+
require 'aws-sdk-s3'
|
5
|
+
require 'pastel'
|
6
|
+
|
7
|
+
module Shipitron
|
8
|
+
module Client
|
9
|
+
class GenerateDeploy
|
10
|
+
include Metaractor
|
11
|
+
|
12
|
+
required :server_deploy_opts
|
13
|
+
required :deploy_id
|
14
|
+
|
15
|
+
def call
|
16
|
+
s3_key = "#{Shipitron::DEPLOY_BUCKET_PREFIX}#{context.deploy_id}"
|
17
|
+
pastel = Pastel.new
|
18
|
+
Logger.info "Uploading deploy config to #{pastel.blue("s3://#{deploy_bucket}/#{s3_key}")}"
|
19
|
+
|
20
|
+
client = Aws::S3::Client.new(region: deploy_bucket_region)
|
21
|
+
|
22
|
+
client.put_object(
|
23
|
+
bucket: deploy_bucket,
|
24
|
+
key: s3_key,
|
25
|
+
body: context.server_deploy_opts.to_json,
|
26
|
+
acl: "private"
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def deploy_bucket
|
33
|
+
Shipitron.config.deploy_bucket
|
34
|
+
end
|
35
|
+
|
36
|
+
def deploy_bucket_region
|
37
|
+
Shipitron.config.deploy_bucket_region
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'shipitron'
|
2
|
+
require 'shipitron/client'
|
2
3
|
require 'shipitron/post_build'
|
4
|
+
require 'aws-sdk-core'
|
3
5
|
|
4
6
|
module Shipitron
|
5
7
|
module Client
|
@@ -11,6 +13,7 @@ module Shipitron
|
|
11
13
|
def call
|
12
14
|
context.repository_url = config.repository
|
13
15
|
context.repository_branch = config.repository_branch
|
16
|
+
context.registry = config.registry
|
14
17
|
context.s3_cache_bucket = config.cache_bucket
|
15
18
|
context.build_cache_location = config.build_cache_location
|
16
19
|
context.image_name = config.image_name
|
@@ -21,6 +24,7 @@ module Shipitron
|
|
21
24
|
config.named_tag
|
22
25
|
end
|
23
26
|
end
|
27
|
+
context.skip_push = config.skip_push
|
24
28
|
context.build_script = config.build_script
|
25
29
|
context.post_builds = begin
|
26
30
|
if config.post_builds.nil?
|
@@ -35,6 +39,19 @@ module Shipitron
|
|
35
39
|
context.ecs_services = config.ecs_services
|
36
40
|
context.ecs_task_def_dir = config.ecs_task_def_dir
|
37
41
|
context.ecs_service_dir = config.ecs_service_dir
|
42
|
+
|
43
|
+
if Shipitron.config.aws_access_key_id? && Shipitron.config.aws_secret_access_key?
|
44
|
+
Aws.config.update(
|
45
|
+
credentials: Aws::Credentials.new(
|
46
|
+
Shipitron.config.aws_access_key_id,
|
47
|
+
Shipitron.config.aws_secret_access_key
|
48
|
+
)
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
if !Shipitron.config.deploy_bucket? || !Shipitron.config.deploy_bucket_region?
|
53
|
+
raise "Missing required deploy bucket configuration!"
|
54
|
+
end
|
38
55
|
end
|
39
56
|
|
40
57
|
private
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'shipitron'
|
2
|
+
require 'shipitron/client'
|
2
3
|
require 'shipitron/ecs_client'
|
3
4
|
require 'shipitron/mustache_yaml_parser'
|
4
5
|
|
@@ -26,11 +27,10 @@ module Shipitron
|
|
26
27
|
|
27
28
|
task_def = Smash.load(
|
28
29
|
path.to_s,
|
29
|
-
parser: MustacheYamlParser
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
)
|
30
|
+
parser: MustacheYamlParser,
|
31
|
+
context: {
|
32
|
+
tag: 'latest'
|
33
|
+
}
|
34
34
|
)
|
35
35
|
|
36
36
|
begin
|