buildkiq 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 23fac219e9f534bde3ea62ea97d17bfc980a00de
4
+ data.tar.gz: d96d7dd91329c63cb2bdc43962cb93b8d0433f7c
5
+ SHA512:
6
+ metadata.gz: 4b9db6e8321d361a32a50f2de18e9ff96e45cb3aa209a7aeb9446c1ab286395909952a2a48ad5e6d9e6aeb288b0674d74deec31ca51e41b219a1fed08d19ca79
7
+ data.tar.gz: 5fa821eb57026e11af3aeb6f521d41c7601b85c728bd8c47b0771ae0f50f5adc6ce2bcabd74b519b49adb04117c596874b30f5ce79c726f6e1f667aab7e8ccc1
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.13.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in buildkiq.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # Buildkiq
2
+
3
+ AWS CodeBuild container launcher
4
+
5
+ - Buildkiq enables you to run UnitTest in a distributed manner.
6
+ - And many more
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'buildkiq'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install buildkiq
23
+
24
+ ## Configuration
25
+
26
+ You need to configure [AWS SDK](https://github.com/aws/aws-sdk-ruby) credentials
27
+
28
+ Create configuration file (~/.aws/credentials) or require environments `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` and `AWS_REGION`
29
+
30
+ ## Usage
31
+
32
+ ### :rocket: run by CLI
33
+
34
+ #### Example: create build 2 containers
35
+
36
+ ```sh
37
+ $ buildkiq run_builds -p your_project_name \
38
+ -c "ruby -v" \
39
+ -e "CI=true,NODE_TOTAL=2" \
40
+ -b "NODE_INDEX=1" "NODE_INDEX=2"
41
+ ```
42
+
43
+ ##### build:1
44
+
45
+ ```
46
+ % export CI=true && export NODE_TOTAL=2
47
+ % export NODE_INDEX=1
48
+ % ruby -v
49
+ ```
50
+
51
+ ##### build:2
52
+
53
+ ```
54
+ % export CI=true && export NODE_TOTAL=2
55
+ % export NODE_INDEX=2
56
+ % ruby -v
57
+ ```
58
+
59
+ #### CLI Parameters
60
+
61
+ | name | alias | desc | required | type |
62
+ | ------------------- | ----- | ----------------------------------------- | -------- | ------ |
63
+ | project | -p | AWS CodeBuild project name | **Yes** | String |
64
+ | builds_environments | -b | builds environments (csv) | **Yes** | Array |
65
+ | environments | -e | common environments (csv) | No | String |
66
+ | source_version | -s | git commit hash or github pullrequest | No | String |
67
+ | command | -c | override buildspec.yml with shell command | No | String |
68
+
69
+ ### :rocket: run by ruby
70
+
71
+ #### Example: create build 2 containers
72
+
73
+ ```ruby
74
+ jobs = Buildkiq.run(project: 'your_project_name',
75
+ build_cmd: 'ruby -v', # override buildspec.yml
76
+ default_environments: [{name: 'CI', value: 'true'}, {name: 'NODE_TOTAL', value: '2'}],
77
+ jobs: [
78
+ {environments: [{name: 'NODE_INDEX', value: '1'}]},
79
+ {environments: [{name: 'NODE_INDEX', value: '2'}]},
80
+ ])
81
+
82
+ puts jobs.size # 2
83
+ puts jobs[0].status # IN_PROGRESS
84
+ jobs[0].wait_for_job
85
+ puts jobs[0].status # SUCCEEDED
86
+ puts jobs[0].build.class # Aws::CodeBuild::Types::Build
87
+
88
+ # Download artifacts file from S3
89
+ # json_text = jobs[0].artifact.find_by('path/to/spec.json')
90
+ ```
91
+
92
+ ## Development
93
+
94
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
95
+
96
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
97
+
98
+ ## Contributing
99
+
100
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bluerabbit/buildkiq.
101
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+ require "buildkiq"
4
+
5
+ require "pry"
6
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/buildkiq.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "buildkiq/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "buildkiq"
8
+ spec.version = Buildkiq::VERSION
9
+ spec.authors = ["Akira Kusumoto"]
10
+ spec.email = ["akirakusumo10@gmail.com"]
11
+
12
+ spec.summary = "AWS CodeBuild container launcher"
13
+ spec.description = "AWS CodeBuild container launcher"
14
+ spec.homepage = "https://github.com/bluerabbit/buildkiq"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_runtime_dependency "aws-sdk", ">= 3.0.1"
25
+ spec.add_runtime_dependency "rubyzip"
26
+ spec.add_runtime_dependency "thor"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.13"
29
+ spec.add_development_dependency "pry-byebug"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec", "~> 3.0"
32
+ end
data/exe/buildkiq ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require "buildkiq/cli"
3
+
4
+ Buildkiq::Cli.start
@@ -0,0 +1,45 @@
1
+ require "aws-sdk"
2
+ require "buildkiq/zip_reader"
3
+
4
+ class Artifact
5
+ def initialize(job)
6
+ @s3_client = Aws::S3::Client.new
7
+ @job = job
8
+ end
9
+
10
+ def upload_success?
11
+ @job.artifact_upload_success?
12
+ end
13
+
14
+ def find_by(path)
15
+ io = if packaging_zip?
16
+ fetch_zip_file.find_by_name(path)
17
+ else
18
+ fetch_s3_object("/#{path}")
19
+ end
20
+
21
+ io.read
22
+ end
23
+
24
+ private
25
+
26
+ def packaging_zip?
27
+ @job.project.artifacts.packaging == "ZIP"
28
+ end
29
+
30
+ def fetch_zip_file
31
+ @zip_reader ||= Buildkiq::ZipReader.new(fetch_s3_object)
32
+ end
33
+
34
+ def fetch_s3_object(path = "")
35
+ @s3_client.get_object(bucket: bucket_name, key: "#{file_key}#{path}").body
36
+ end
37
+
38
+ def bucket_name
39
+ @bucket_name ||= @job.build.artifacts.location.split(":::").last.split("/").first
40
+ end
41
+
42
+ def file_key
43
+ @file_key ||= @job.build.artifacts.location.split(":::").last.split("/")[1..-1].join("/")
44
+ end
45
+ end
@@ -0,0 +1,44 @@
1
+ require "thor"
2
+ require "buildkiq"
3
+ require "logger"
4
+
5
+ module Buildkiq
6
+ class Cli < Thor
7
+ default_command :run_builds
8
+
9
+ desc "run_builds", "Run containers"
10
+ method_option :project, aliases: "-p", required: true, desc: 'AWS CodeBuild project name'
11
+ method_option :builds_environments, aliases: "-b", required: true, type: :array, desc: 'builds environments(csv)'
12
+ method_option :environments, aliases: "-e", desc: 'common environments(csv)'
13
+ method_option :source_version, aliases: "-s", desc: 'git commit hash or github pullrequest'
14
+ method_option :command, aliases: "-c", desc: 'override buildspec.yml with shell command'
15
+
16
+ def run_builds
17
+ logger = Logger.new(STDOUT)
18
+ jobs = Buildkiq.run(project: options[:project],
19
+ jobs: options[:builds_environments].map {|job|
20
+ {environments: parse_environments_text(job)}
21
+ },
22
+ default_environments: parse_environments_text(options[:environments]),
23
+ source_version: options[:source_version],
24
+ build_cmd: options[:command],
25
+ logger: logger)
26
+
27
+ jobs.each {|job| logger.info(job.build_url) }
28
+ end
29
+
30
+ desc "version", "Show Version"
31
+
32
+ def version
33
+ say "Version: #{Buildkiq::VERSION}"
34
+ end
35
+
36
+ private
37
+
38
+ def parse_environments_text(env_csv_text)
39
+ env_csv_text.to_s.split(/,\s*/).map { |kv| kv.split("=") }.map do |k, v|
40
+ { name: k, value: v }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,87 @@
1
+ require "logger"
2
+ require "aws-sdk"
3
+
4
+ module Buildkiq
5
+ class Job
6
+ attr_reader :logger, :project_name, :environments, :build
7
+
8
+ def initialize(project_name:, environments:, logger: Logger.new(STDOUT))
9
+ @client = Aws::CodeBuild::Client.new
10
+ @project_name = project_name
11
+ @environments = environments
12
+ @logger = logger
13
+ end
14
+
15
+ def start(source_version: nil, build_cmd: nil)
16
+ params = {project_name: project_name, environment_variables_override: environments}
17
+
18
+ if source_version && source_type == "S3"
19
+ raise ArgumentError.new("source_version parameter can not be used, project source type is S3")
20
+ end
21
+
22
+ params[:source_version] = source_version if source_version
23
+ params[:buildspec_override] = build_spec(build_cmd) if build_cmd
24
+ logger.info("build parameter: #{params}")
25
+
26
+ @build = @client.start_build(params).build
27
+ end
28
+
29
+ def wait_for_job(timeout_sec: build.timeout_in_minutes * 60, sleep_sec: 5)
30
+ Timeout.timeout(timeout_sec) do
31
+ sleep(sleep_sec) until done?
32
+ end
33
+
34
+ self
35
+ end
36
+
37
+ def status
38
+ fetch_build.build_status
39
+ end
40
+
41
+ def build_url
42
+ "https://#{@client.config.region}.console.aws.amazon.com/codebuild/home#/builds/#{build[:id]}/view/new"
43
+ end
44
+
45
+ def watch_log_url
46
+ build.logs.deep_link if build
47
+ end
48
+
49
+ def artifact_upload_success?
50
+ !fetch_build.phases.select { |v|
51
+ v.phase_type == "UPLOAD_ARTIFACTS" && v.phase_status == "SUCCEEDED"
52
+ }.empty?
53
+ end
54
+
55
+ def project
56
+ @project ||= @client.batch_get_projects(names: [project_name])[0][0]
57
+ end
58
+
59
+ def artifact
60
+ @artifact ||= Artifact.new(self)
61
+ end
62
+
63
+ private
64
+
65
+ def fetch_build
66
+ @build = @client.batch_get_builds(ids: [build[:id]]).builds[0]
67
+ end
68
+
69
+ def source_type
70
+ project.source.type
71
+ end
72
+
73
+ def done?
74
+ fetch_build.build_complete
75
+ end
76
+
77
+ def build_spec(cmd)
78
+ <<~EOS
79
+ version: 0.2
80
+ phases:
81
+ build:
82
+ commands:
83
+ - #{cmd}
84
+ EOS
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module Buildkiq
2
+ VERSION = "0.1.0".freeze
3
+ end
@@ -0,0 +1,22 @@
1
+ require "zip"
2
+
3
+ module Buildkiq
4
+ class ZipReader
5
+ def initialize(zip_io)
6
+ @zip_io = zip_io
7
+ end
8
+
9
+ def find_by_name(filename)
10
+ entry = find_by { |e| e.name == filename }
11
+ entry ? entry.get_input_stream : nil
12
+ end
13
+
14
+ def find_by
15
+ Zip::File.open_buffer(@zip_io) do |zip|
16
+ zip.each { |e| return e if yield(e) }
17
+ end
18
+
19
+ nil
20
+ end
21
+ end
22
+ end
data/lib/buildkiq.rb ADDED
@@ -0,0 +1,29 @@
1
+ require "logger"
2
+ require "buildkiq/version"
3
+ require "buildkiq/job"
4
+ require "buildkiq/artifact"
5
+
6
+ module Buildkiq
7
+ class << self
8
+ def run(project:, jobs:, default_environments: [], build_cmd: nil, source_version: nil, logger: Logger.new(STDOUT))
9
+ jobs.each { |job| merge_environments!(job[:environments], default_environments) }
10
+
11
+ jobs.map do |job|
12
+ job = Buildkiq::Job.new(project_name: project, environments: job[:environments])
13
+ job.start(source_version: source_version, build_cmd: build_cmd)
14
+ logger.info("build_id: #{job.build.id}")
15
+ job
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def merge_environments!(job_environments, default_environments)
22
+ default_environments.each do |env|
23
+ unless job_environments.any? { |h| h[:name] == env[:name] }
24
+ job_environments << env
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: buildkiq
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Akira Kusumoto
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubyzip
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.13'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.13'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
111
+ description: AWS CodeBuild container launcher
112
+ email:
113
+ - akirakusumo10@gmail.com
114
+ executables:
115
+ - buildkiq
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rspec"
121
+ - ".travis.yml"
122
+ - Gemfile
123
+ - README.md
124
+ - Rakefile
125
+ - bin/console
126
+ - bin/setup
127
+ - buildkiq.gemspec
128
+ - exe/buildkiq
129
+ - lib/buildkiq.rb
130
+ - lib/buildkiq/artifact.rb
131
+ - lib/buildkiq/cli.rb
132
+ - lib/buildkiq/job.rb
133
+ - lib/buildkiq/version.rb
134
+ - lib/buildkiq/zip_reader.rb
135
+ homepage: https://github.com/bluerabbit/buildkiq
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.6.13
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: AWS CodeBuild container launcher
159
+ test_files: []