buildkiq 0.1.0

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 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: []