codebuild 0.2.0 → 0.3.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 +4 -4
- data/.gitmodules +3 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +6 -0
- data/README.md +25 -19
- data/codebuild.gemspec +2 -0
- data/exe/cb +14 -0
- data/img/github-admin-settings-tab.png +0 -0
- data/lib/codebuild/autoloader.rb +21 -0
- data/lib/codebuild/aws_services/helpers.rb +19 -2
- data/lib/codebuild/aws_services.rb +0 -1
- data/lib/codebuild/cli.rb +13 -29
- data/lib/codebuild/completer.rb +0 -2
- data/lib/codebuild/core.rb +61 -0
- data/lib/codebuild/default/settings.yml +3 -0
- data/lib/codebuild/delete.rb +2 -1
- data/lib/codebuild/dsl/project.rb +0 -1
- data/lib/codebuild/evaluate.rb +1 -6
- data/lib/codebuild/init.rb +4 -2
- data/lib/codebuild/project.rb +10 -1
- data/lib/codebuild/sequence.rb +7 -1
- data/lib/codebuild/setting.rb +80 -0
- data/lib/codebuild/stack.rb +46 -7
- data/lib/codebuild/start.rb +17 -6
- data/lib/codebuild/version.rb +1 -1
- data/lib/codebuild.rb +12 -19
- data/lib/template/.codebuild/buildspec.yml +2 -2
- data/lib/template/.codebuild/project.rb.tt +5 -1
- data/lib/template/.codebuild/role.rb +2 -1
- data/readme/github_oauth.md +14 -12
- data/readme/type.md +33 -0
- metadata +41 -5
- data/lib/codebuild/dsl.rb +0 -8
- data/readme/lookup.md +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6bcfea57ca3fcb04bc2f1f79e5bbd6ccb8a69cb736b4be4c4c10cd8bebc422db
|
4
|
+
data.tar.gz: 141de3012147451070013d00cfe3ec4d67d8ed3289f143fe37d4d1f7ff57d3cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dec4e8ba192c051d5b23ab9ca9069e0ea6cfd134fcdb5db210f6cf2d056f5e8a65d0b58d4a92f5ec24b61ed270f0e7d3396ef43b10d18bd12e24979ce32e6921
|
7
|
+
data.tar.gz: 416cb5263cfd06c4691e5f67f016854dca5b3e88fa7342c59358eee8d06ec65d7ee9971382bec3064db6b35aa5e9d2b31d950b57984abd24a4674a7c235b840a
|
data/.gitmodules
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.3
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,12 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
|
5
5
|
|
6
|
+
## [0.3.0]
|
7
|
+
* rework cb cli interface
|
8
|
+
* project_name as cli main parameter
|
9
|
+
* type option for subprojects in .codebuild folder
|
10
|
+
* update to zeitwerk for autoloading
|
11
|
+
|
6
12
|
## [0.2.0]
|
7
13
|
- First good release.
|
8
14
|
- Project and Role DSL
|
data/README.md
CHANGED
@@ -2,13 +2,19 @@
|
|
2
2
|
|
3
3
|

|
4
4
|
|
5
|
-
|
5
|
+
The codebuild tool provides a DSL to create a CodeBuild project with some reasonable defaults.
|
6
|
+
|
7
|
+
The codebuild tool installs `cb` and `codebuild` executables. Both of them do the same thing, `cb` is just shorter to type.
|
6
8
|
|
7
9
|
## Quick Start
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
cb init
|
12
|
+
cb deploy
|
13
|
+
cb start
|
14
|
+
|
15
|
+
## Private Repo
|
16
|
+
|
17
|
+
IMPORTANT: Before deploying, if you are using a private repo, use [aws codebuild import-source-credentials](https://docs.aws.amazon.com/cli/latest/reference/codebuild/import-source-credentials.html) to add credentials so that codebuild can clone down the repo. Refer to [github_oauth.md](readme/github_oauth.md) for more info.
|
12
18
|
|
13
19
|
## Usage
|
14
20
|
|
@@ -29,37 +35,37 @@ First, run `codebuild init` to generate a starter .codebuild structure.
|
|
29
35
|
File | Description
|
30
36
|
--- | ---
|
31
37
|
buildspec.yml | The build commands to run.
|
32
|
-
project.rb | The codebuild project
|
33
|
-
role.rb | The IAM role
|
38
|
+
project.rb | The codebuild project written as a DSL.
|
39
|
+
role.rb | The IAM role associated with the codebuild project written as a DSL.
|
34
40
|
|
35
41
|
### Deploy
|
36
42
|
|
37
43
|
Adjust the files in `.codebuild` to fit your needs. When you're ready, deploy the CodeBuild project with:
|
38
44
|
|
39
|
-
|
45
|
+
cb deploy STACK_NAME
|
40
46
|
|
41
47
|
More examples:
|
42
48
|
|
43
|
-
|
44
|
-
|
49
|
+
cb deploy # infers the CloudFormation name from the parent folder
|
50
|
+
cb deploy stack-name # explicitly specify stack name
|
45
51
|
|
46
52
|
It is useful to just see the generated CloudFormation template with `--noop` mode:
|
47
53
|
|
48
|
-
|
54
|
+
cb deploy --noop # see generated CloudFormation template
|
49
55
|
|
50
56
|
For more help:
|
51
57
|
|
52
|
-
|
58
|
+
cb deploy -h
|
53
59
|
|
54
60
|
### Start
|
55
61
|
|
56
62
|
When you are ready to start a codebuild project run, you can use `codebuild start`. Examples:
|
57
63
|
|
58
|
-
|
59
|
-
|
60
|
-
|
64
|
+
cb start # infers the name from the parent folder
|
65
|
+
cb start stack-name # looks up project via CloudFormation stack
|
66
|
+
cb start demo-project # looks up project via CodeBuild project name
|
61
67
|
|
62
|
-
The `
|
68
|
+
The `cb start` command understands multiple identifiers. It will look up the codebuild project either via CloudFormation or the CodeBuild project name.
|
63
69
|
|
64
70
|
## Project DSL
|
65
71
|
|
@@ -68,12 +74,12 @@ The tool provides a DSL to create a codebuild project. Here's an example.
|
|
68
74
|
.codebuild/project.rb:
|
69
75
|
|
70
76
|
```ruby
|
71
|
-
name("demo")
|
77
|
+
# name("demo") # recommended to leave unset and use the conventional name that cb tool sets
|
72
78
|
github_url("https://github.com/tongueroo/demo-ufo")
|
73
79
|
linux_image("aws/codebuild/ruby:2.5.3-1.7.0")
|
74
80
|
environment_variables(
|
75
81
|
UFO_ENV: "development",
|
76
|
-
API_KEY: "ssm:/codebuild/demo/api_key"
|
82
|
+
API_KEY: "ssm:/codebuild/demo/api_key" # ssm param example
|
77
83
|
)
|
78
84
|
```
|
79
85
|
|
@@ -119,9 +125,9 @@ iam_policy(
|
|
119
125
|
|
120
126
|
The convenience DSL methods shown above are short and clean. They merely wrap a DSL that map to the properties of CloudFormation resources like [AWS::CodeBuild::Project](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html) and [AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html). Refer the [Full DSL docs](readme/full_dsl.md) for more info.
|
121
127
|
|
122
|
-
##
|
128
|
+
## Type Option
|
123
129
|
|
124
|
-
By default, the codebuild tool looks up files in the `.codebuild` folder. You can affect the behavior of the
|
130
|
+
By default, the codebuild tool looks up files in the `.codebuild` folder. You can affect the behavior of the Type logic with the `--Type` option. More info [Type docs](readme/type.md).
|
125
131
|
|
126
132
|
## Installation
|
127
133
|
|
data/codebuild.gemspec
CHANGED
@@ -23,7 +23,9 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency "aws-sdk-codebuild"
|
24
24
|
spec.add_dependency "aws-sdk-ssm"
|
25
25
|
spec.add_dependency "cfn_camelizer"
|
26
|
+
spec.add_dependency "memoist"
|
26
27
|
spec.add_dependency "rainbow"
|
28
|
+
spec.add_dependency "render_me_pretty"
|
27
29
|
spec.add_dependency "thor"
|
28
30
|
|
29
31
|
spec.add_development_dependency "bundler"
|
data/exe/cb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Trap ^C
|
4
|
+
Signal.trap("INT") {
|
5
|
+
puts "\nCtrl-C detected. Exiting..."
|
6
|
+
sleep 1
|
7
|
+
exit
|
8
|
+
}
|
9
|
+
|
10
|
+
$:.unshift(File.expand_path("../../lib", __FILE__))
|
11
|
+
require "codebuild"
|
12
|
+
require "codebuild/cli"
|
13
|
+
|
14
|
+
Codebuild::CLI.start(ARGV)
|
Binary file
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "zeitwerk"
|
2
|
+
|
3
|
+
module Codebuild
|
4
|
+
class Autoloader
|
5
|
+
class Inflector < Zeitwerk::Inflector
|
6
|
+
def camelize(basename, _abspath)
|
7
|
+
map = { cli: "CLI", version: "VERSION" }
|
8
|
+
map[basename.to_sym] || super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def setup
|
14
|
+
loader = Zeitwerk::Loader.new
|
15
|
+
loader.inflector = Inflector.new
|
16
|
+
loader.push_dir(File.dirname(__dir__)) # lib
|
17
|
+
loader.setup
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -25,8 +25,25 @@ module Codebuild::AwsServices
|
|
25
25
|
exist
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
29
|
-
|
28
|
+
def project_name_convention(name_base)
|
29
|
+
[@project_name, @options[:type], Codebuild.env, Codebuild.env_extra].reject(&:blank?).compact.join("-")
|
30
|
+
end
|
31
|
+
|
32
|
+
def inferred_project_name
|
33
|
+
# Essentially the project's parent folder
|
34
|
+
File.basename(Dir.pwd).gsub('_','-').gsub(/\.+/,'-').gsub(/[^0-9a-zA-Z,-]/, '')
|
35
|
+
end
|
36
|
+
|
37
|
+
# Examples:
|
38
|
+
#
|
39
|
+
# myapp-ci-deploy # with Settings stack_naming append_env set to false.
|
40
|
+
# myapp-ci-deploy-development
|
41
|
+
# myapp-ci-deploy-development-2
|
42
|
+
#
|
43
|
+
def inferred_stack_name(project_name)
|
44
|
+
items = [project_name, "cb", @options[:type], Codebuild.env_extra]
|
45
|
+
items.insert(3, Codebuild.env) if Codebuild.settings.dig(:stack_naming, :append_env)
|
46
|
+
items.reject(&:blank?).compact.join("-")
|
30
47
|
end
|
31
48
|
|
32
49
|
def are_you_sure?(stack_name, action)
|
data/lib/codebuild/cli.rb
CHANGED
@@ -10,49 +10,33 @@ module Codebuild
|
|
10
10
|
end
|
11
11
|
register(Init, "init", "init", "Set up initial ufo files.")
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
Dsl.new(options).evaluate
|
17
|
-
end
|
18
|
-
|
19
|
-
deploy_options = Proc.new do
|
20
|
-
option :lookup, desc: "folder to use within .codebuild folder for extra lookups of files"
|
21
|
-
end
|
22
|
-
|
23
|
-
desc "create", "Create codebuild project."
|
24
|
-
long_desc Help.text(:create)
|
25
|
-
deploy_options.call
|
26
|
-
def create(stack_name=nil)
|
27
|
-
Create.new(options.merge(stack_name: stack_name)).run
|
28
|
-
end
|
29
|
-
|
30
|
-
desc "update", "Update codebuild project."
|
31
|
-
long_desc Help.text(:update)
|
32
|
-
deploy_options.call
|
33
|
-
def update(stack_name=nil)
|
34
|
-
Update.new(options.merge(stack_name: stack_name)).run
|
13
|
+
common_options = Proc.new do
|
14
|
+
option :type, desc: "folder to use within .codebuild folder for different build types"
|
15
|
+
option :stack_name, desc: "Override the generated stack name. If you use this you must always specify it"
|
35
16
|
end
|
36
17
|
|
37
18
|
desc "deploy", "Deploy codebuild project."
|
38
19
|
long_desc Help.text(:deploy)
|
39
|
-
|
40
|
-
def deploy(
|
41
|
-
Deploy.new(options.merge(
|
20
|
+
common_options.call
|
21
|
+
def deploy(project_name=nil)
|
22
|
+
Deploy.new(options.merge(project_name: project_name)).run
|
42
23
|
end
|
43
24
|
|
44
25
|
desc "delete", "Delete codebuild project."
|
45
26
|
long_desc Help.text(:delete)
|
46
27
|
option :sure, desc: "Bypass are you sure prompt"
|
47
|
-
|
48
|
-
|
28
|
+
common_options.call
|
29
|
+
def delete(project_name=nil)
|
30
|
+
Delete.new(options.merge(project_name: project_name)).run
|
49
31
|
end
|
50
32
|
|
51
33
|
desc "start", "start codebuild project."
|
52
34
|
long_desc Help.text(:start)
|
53
35
|
option :source_version, default: "master", desc: "git branch"
|
54
|
-
|
55
|
-
|
36
|
+
option :branch, aliases: "b", default: "master", desc: "git branch"
|
37
|
+
common_options.call
|
38
|
+
def start(project_name=nil)
|
39
|
+
Start.new(options.merge(project_name: project_name)).run
|
56
40
|
end
|
57
41
|
|
58
42
|
desc "completion *PARAMS", "Prints words for auto-completion."
|
data/lib/codebuild/completer.rb
CHANGED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Codebuild
|
5
|
+
module Core
|
6
|
+
extend Memoist
|
7
|
+
|
8
|
+
def root
|
9
|
+
path = ENV['CB_ROOT'] || '.'
|
10
|
+
Pathname.new(path)
|
11
|
+
end
|
12
|
+
|
13
|
+
def env
|
14
|
+
# 2-way binding
|
15
|
+
cb_env = env_from_profile || 'development'
|
16
|
+
cb_env = ENV['CB_ENV'] if ENV['CB_ENV'] # highest precedence
|
17
|
+
cb_env
|
18
|
+
end
|
19
|
+
memoize :env
|
20
|
+
|
21
|
+
def env_extra
|
22
|
+
env_extra = ENV['CB_ENV_EXTRA'] if ENV['CB_ENV_EXTRA'] # highest precedence
|
23
|
+
return if env_extra&.empty?
|
24
|
+
env_extra
|
25
|
+
end
|
26
|
+
memoize :env_extra
|
27
|
+
|
28
|
+
# Overrides AWS_PROFILE based on the Codebuild.env if set in configs/settings.yml
|
29
|
+
# 2-way binding.
|
30
|
+
def set_aws_profile!
|
31
|
+
return if ENV['TEST']
|
32
|
+
return unless File.exist?("#{Codebuild.root}/.codebuild/settings.yml") # for rake docs
|
33
|
+
return unless settings # Only load if within Codebuild project and there's a settings.yml
|
34
|
+
data = settings[Codebuild.env] || {}
|
35
|
+
if data["aws_profile"]
|
36
|
+
puts "Using AWS_PROFILE=#{data["aws_profile"]} from CB_ENV=#{Codebuild.env} in config/settings.yml"
|
37
|
+
ENV['AWS_PROFILE'] = data["aws_profile"]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def settings
|
42
|
+
Setting.new.data
|
43
|
+
end
|
44
|
+
memoize :settings
|
45
|
+
|
46
|
+
def check_codebuild_project!
|
47
|
+
check_path = "#{Codebuild.root}/.codebuild/settings.yml"
|
48
|
+
unless File.exist?(check_path)
|
49
|
+
puts "ERROR: No settings file at #{check_path}. Are you sure you are in a project with codebuild setup?".color(:red)
|
50
|
+
puts "Current directory: #{Dir.pwd}"
|
51
|
+
puts "If you want to set up codebuild for this prjoect, please create a settings file via: codebuild init"
|
52
|
+
exit 1 unless ENV['TEST']
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def env_from_profile
|
58
|
+
Codebuild::Setting.new.cb_env
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/codebuild/delete.rb
CHANGED
@@ -4,7 +4,8 @@ module Codebuild
|
|
4
4
|
|
5
5
|
def initialize(options)
|
6
6
|
@options = options
|
7
|
-
@
|
7
|
+
@project_name = options[:project_name] || inferred_project_name
|
8
|
+
@stack_name = options[:stack_name] || inferred_stack_name(@project_name)
|
8
9
|
end
|
9
10
|
|
10
11
|
def run
|
data/lib/codebuild/evaluate.rb
CHANGED
@@ -41,12 +41,7 @@ module Codebuild
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def lookup_codebuild_file(name)
|
44
|
-
|
45
|
-
if File.exist?(folder_path)
|
46
|
-
folder_path
|
47
|
-
else
|
48
|
-
".codebuild/#{name}" # default
|
49
|
-
end
|
44
|
+
[".codebuild", @options[:type], name].compact.join("/")
|
50
45
|
end
|
51
46
|
end
|
52
47
|
end
|
data/lib/codebuild/init.rb
CHANGED
@@ -20,7 +20,7 @@ module Codebuild
|
|
20
20
|
def set_source_path
|
21
21
|
return unless @options[:template]
|
22
22
|
|
23
|
-
custom_template = "#{ENV['HOME']}/.codebuild/templates/#{
|
23
|
+
custom_template = "#{ENV['HOME']}/.codebuild/templates/#{full_repo_name}"
|
24
24
|
|
25
25
|
if @options[:template_mode] == "replace" # replace the template entirely
|
26
26
|
override_source_paths(custom_template)
|
@@ -69,7 +69,9 @@ module Codebuild
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
versions = versions.select { |v| v =~ pattern }
|
72
|
-
|
72
|
+
# IE: aws/codebuild/ruby:2.5.3-1.7.0
|
73
|
+
# Falls back to hard-coded image name since the API changed and looks like it's returning no ruby images
|
74
|
+
versions.sort.last || "aws/codebuild/ruby:2.5.3-1.7.0"
|
73
75
|
end
|
74
76
|
end
|
75
77
|
end
|
data/lib/codebuild/project.rb
CHANGED
@@ -5,13 +5,20 @@ module Codebuild
|
|
5
5
|
include Dsl::Project
|
6
6
|
include Evaluate
|
7
7
|
|
8
|
+
attr_reader :project_name, :full_project_name, :project_path
|
8
9
|
def initialize(options={})
|
9
10
|
@options = options
|
11
|
+
@project_name = options[:project_name]
|
12
|
+
@full_project_name = options[:full_project_name] # includes -development at the end
|
10
13
|
@project_path = options[:project_path] || get_project_path
|
11
14
|
# These defaults make it the project.rb simpler
|
12
15
|
@properties = default_properties
|
13
16
|
end
|
14
17
|
|
18
|
+
def exist?
|
19
|
+
File.exist?(@project_path)
|
20
|
+
end
|
21
|
+
|
15
22
|
def run
|
16
23
|
evaluate(@project_path)
|
17
24
|
resource = {
|
@@ -25,6 +32,8 @@ module Codebuild
|
|
25
32
|
|
26
33
|
def default_properties
|
27
34
|
{
|
35
|
+
name: @full_project_name,
|
36
|
+
description: @full_project_name,
|
28
37
|
artifacts: { type: "NO_ARTIFACTS" },
|
29
38
|
service_role: { ref: "IamRole" },
|
30
39
|
badge_enabled: true,
|
@@ -38,7 +47,7 @@ module Codebuild
|
|
38
47
|
source: {
|
39
48
|
type: "GITHUB",
|
40
49
|
# location: "", # required
|
41
|
-
git_clone_depth: 1,
|
50
|
+
# git_clone_depth: 1,
|
42
51
|
git_submodules_config: { fetch_submodules: true },
|
43
52
|
build_spec: build_spec,
|
44
53
|
# auth doesnt seem to work, refer to https://github.com/tongueroo/codebuild/blob/master/readme/github_oauth.md
|
data/lib/codebuild/sequence.rb
CHANGED
@@ -29,7 +29,7 @@ module Codebuild
|
|
29
29
|
abort "Unable to detect git installation on your system. Git needs to be installed in order to use the --template option."
|
30
30
|
end
|
31
31
|
|
32
|
-
template_path = "#{ENV['HOME']}/.codebuild/templates/#{
|
32
|
+
template_path = "#{ENV['HOME']}/.codebuild/templates/#{full_repo_name}"
|
33
33
|
if File.exist?(template_path)
|
34
34
|
sh("cd #{template_path} && git pull")
|
35
35
|
else
|
@@ -38,6 +38,12 @@ module Codebuild
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def full_repo_name
|
42
|
+
full_repo = options[:template].split("/")[-2..-1].join("/")
|
43
|
+
full_repo = full_repo.split(":").last
|
44
|
+
full_repo.sub(".git", "")
|
45
|
+
end
|
46
|
+
|
41
47
|
# normalize repo_url
|
42
48
|
def repo_url
|
43
49
|
template = options[:template]
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'render_me_pretty'
|
3
|
+
|
4
|
+
module Codebuild
|
5
|
+
class Setting
|
6
|
+
extend Memoist
|
7
|
+
def initialize(check_codebuild_project=true)
|
8
|
+
@check_codebuild_project = check_codebuild_project
|
9
|
+
end
|
10
|
+
|
11
|
+
# data contains the settings.yml config. The order or precedence for settings
|
12
|
+
# is the project ufo/settings.yml and then the ~/.codebuild/settings.yml.
|
13
|
+
def data
|
14
|
+
if @check_codebuild_project && !File.exist?(project_settings_path)
|
15
|
+
Codebuild.check_codebuild_project!
|
16
|
+
end
|
17
|
+
|
18
|
+
# project based settings files
|
19
|
+
project = load_file(project_settings_path)
|
20
|
+
|
21
|
+
user_file = "#{ENV['HOME']}/.codebuild/settings.yml"
|
22
|
+
user = File.exist?(user_file) ? YAML.load_file(user_file) : {}
|
23
|
+
|
24
|
+
default_file = File.expand_path("default/settings.yml", __dir__)
|
25
|
+
default = load_file(default_file)
|
26
|
+
|
27
|
+
all_envs = default.deep_merge(user.deep_merge(project))
|
28
|
+
all_envs = merge_base(all_envs)
|
29
|
+
data = all_envs[cb_env] || all_envs["base"] || {}
|
30
|
+
data.deep_symbolize_keys
|
31
|
+
end
|
32
|
+
memoize :data
|
33
|
+
|
34
|
+
# Resolves infinite problem since Codebuild.env can be determined from CB_ENV or settings.yml files.
|
35
|
+
# When ufo is determined from settings it should not called Codebuild.env since that in turn calls
|
36
|
+
# Settings.new.data which can then cause an infinite loop.
|
37
|
+
def cb_env
|
38
|
+
settings = YAML.load_file("#{cb_root}/.codebuild/settings.yml")
|
39
|
+
env = settings.find do |_env, section|
|
40
|
+
section ||= {}
|
41
|
+
ENV['AWS_PROFILE'] && ENV['AWS_PROFILE'] == section['aws_profile']
|
42
|
+
end
|
43
|
+
|
44
|
+
cb_env = env.first if env
|
45
|
+
cb_env = ENV['CB_ENV'] if ENV['CB_ENV'] # highest precedence
|
46
|
+
cb_env || 'development'
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def load_file(path)
|
51
|
+
return Hash.new({}) unless File.exist?(path)
|
52
|
+
|
53
|
+
content = RenderMePretty.result(path)
|
54
|
+
data = YAML.load(content)
|
55
|
+
# If key is is accidentally set to nil it screws up the merge_base later.
|
56
|
+
# So ensure that all keys with nil value are set to {}
|
57
|
+
data.each do |env, _setting|
|
58
|
+
data[env] ||= {}
|
59
|
+
end
|
60
|
+
data
|
61
|
+
end
|
62
|
+
|
63
|
+
# automatically add base settings to the rest of the environments
|
64
|
+
def merge_base(all_envs)
|
65
|
+
base = all_envs["base"] || {}
|
66
|
+
all_envs.each do |env, settings|
|
67
|
+
all_envs[env] = base.merge(settings) unless env == "base"
|
68
|
+
end
|
69
|
+
all_envs
|
70
|
+
end
|
71
|
+
|
72
|
+
def project_settings_path
|
73
|
+
"#{cb_root}/.codebuild/settings.yml"
|
74
|
+
end
|
75
|
+
|
76
|
+
def cb_root
|
77
|
+
ENV["CODEBUILD_ROOT"] || Dir.pwd
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/codebuild/stack.rb
CHANGED
@@ -6,12 +6,28 @@ module Codebuild
|
|
6
6
|
|
7
7
|
def initialize(options)
|
8
8
|
@options = options
|
9
|
-
@
|
10
|
-
@
|
9
|
+
@project_name = @options[:project_name] || inferred_project_name
|
10
|
+
@stack_name = options[:stack_name] || inferred_stack_name(@project_name)
|
11
|
+
|
12
|
+
@full_project_name = project_name_convention(@project_name)
|
13
|
+
@template = {
|
14
|
+
"Description" => "CodeBuild Project: #{@full_project_name}",
|
15
|
+
"Resources" => {}
|
16
|
+
}
|
11
17
|
end
|
12
18
|
|
13
19
|
def run
|
14
|
-
|
20
|
+
options = @options.merge(
|
21
|
+
project_name: @project_name,
|
22
|
+
full_project_name: @full_project_name,
|
23
|
+
)
|
24
|
+
project_builder = Project.new(options)
|
25
|
+
unless project_builder.exist?
|
26
|
+
puts "ERROR: Codebuild project does not exist: #{project_builder.project_path}".color(:red)
|
27
|
+
exit 1
|
28
|
+
return
|
29
|
+
end
|
30
|
+
project = project_builder.run
|
15
31
|
@template["Resources"].merge!(project)
|
16
32
|
|
17
33
|
if project["CodeBuild"]["Properties"]["ServiceRole"] == {"Ref"=>"IamRole"}
|
@@ -19,16 +35,39 @@ module Codebuild
|
|
19
35
|
@template["Resources"].merge!(role)
|
20
36
|
end
|
21
37
|
|
22
|
-
|
23
|
-
|
38
|
+
template_path = "/tmp/codebuild.yml"
|
39
|
+
FileUtils.mkdir_p(File.dirname(template_path))
|
40
|
+
IO.write(template_path, YAML.dump(@template))
|
41
|
+
puts "Generated CloudFormation template at #{template_path.color(:green)}"
|
24
42
|
return if @options[:noop]
|
43
|
+
puts "Deploying stack #{@stack_name.color(:green)} with CodeBuild project #{@full_project_name.color(:green)}"
|
25
44
|
|
26
45
|
begin
|
27
46
|
perform
|
47
|
+
url_info
|
48
|
+
status.wait
|
49
|
+
exit 2 unless status.success?
|
28
50
|
rescue Aws::CloudFormation::Errors::ValidationError => e
|
29
|
-
|
30
|
-
|
51
|
+
if e.message.include?("No updates") # No updates are to be performed.
|
52
|
+
puts "WARN: #{e.message}".color(:yellow)
|
53
|
+
else
|
54
|
+
puts "ERROR: #{e.message}".color(:red)
|
55
|
+
exit 1
|
56
|
+
end
|
31
57
|
end
|
32
58
|
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def url_info
|
62
|
+
stack = cfn.describe_stacks(stack_name: @stack_name).stacks.first
|
63
|
+
region = `aws configure get region`.strip rescue "us-east-1"
|
64
|
+
url = "https://console.aws.amazon.com/cloudformation/home?region=#{region}#/stacks"
|
65
|
+
puts "Stack name #{@stack_name.color(:yellow)} status #{stack["stack_status"].color(:yellow)}"
|
66
|
+
puts "Here's the CloudFormation url to check for more details #{url}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def status
|
70
|
+
@status ||= Cfn::Status.new(@stack_name)
|
71
|
+
end
|
33
72
|
end
|
34
73
|
end
|
data/lib/codebuild/start.rb
CHANGED
@@ -4,26 +4,31 @@ module Codebuild
|
|
4
4
|
|
5
5
|
def initialize(options)
|
6
6
|
@options = options
|
7
|
-
@
|
7
|
+
@project_name = options[:project_name] || inferred_project_name
|
8
|
+
@full_project_name = project_name_convention(@project_name)
|
8
9
|
end
|
9
10
|
|
10
11
|
def run
|
12
|
+
source_version = @options[:branch] || @options[:source_version] || 'master'
|
11
13
|
resp = codebuild.start_build(
|
12
14
|
project_name: project_name,
|
13
|
-
source_version:
|
15
|
+
source_version: source_version
|
14
16
|
)
|
15
17
|
puts "Build started for project: #{project_name}"
|
18
|
+
puts "Please check the CodeBuild console for the status."
|
19
|
+
puts "Codebuild Log Url:"
|
20
|
+
puts codebuild_log_url(resp.build.id)
|
16
21
|
end
|
17
22
|
|
18
23
|
def project_name
|
19
|
-
if
|
20
|
-
|
24
|
+
if project_exists?(@full_project_name)
|
25
|
+
@full_project_name
|
26
|
+
elsif stack_exists?(@project_name) # allow `cb start STACK_NAME` to work too
|
27
|
+
resp = cfn.describe_stack_resources(stack_name: @project_name)
|
21
28
|
resource = resp.stack_resources.find do |r|
|
22
29
|
r.logical_resource_id == "CodeBuild"
|
23
30
|
end
|
24
31
|
resource.physical_resource_id # codebuild project name
|
25
|
-
elsif project_exists?(@identifier)
|
26
|
-
@identifier
|
27
32
|
else
|
28
33
|
puts "ERROR: Unable to find the codebuild project with identifier #@identifier".color(:red)
|
29
34
|
exit 1
|
@@ -31,6 +36,12 @@ module Codebuild
|
|
31
36
|
end
|
32
37
|
|
33
38
|
private
|
39
|
+
def codebuild_log_url(build_id)
|
40
|
+
build_id = build_id.split(':').last
|
41
|
+
region = `aws configure get region`.strip rescue "us-east-1"
|
42
|
+
"https://#{region}.console.aws.amazon.com/codesuite/codebuild/projects/#{project_name}/build/#{project_name}%3A#{build_id}/log"
|
43
|
+
end
|
44
|
+
|
34
45
|
def project_exists?(name)
|
35
46
|
resp = codebuild.batch_get_projects(names: [name])
|
36
47
|
resp.projects.size > 0
|
data/lib/codebuild/version.rb
CHANGED
data/lib/codebuild.rb
CHANGED
@@ -2,26 +2,19 @@ $:.unshift(File.expand_path("../", __FILE__))
|
|
2
2
|
require "cfn_camelizer"
|
3
3
|
require "codebuild/version"
|
4
4
|
require "rainbow/ext/string"
|
5
|
+
require "yaml"
|
6
|
+
|
7
|
+
require "codebuild/autoloader"
|
8
|
+
Codebuild::Autoloader.setup
|
9
|
+
|
10
|
+
gem_root = File.dirname(__dir__)
|
11
|
+
$:.unshift("#{gem_root}/vendor/cfn-status/lib")
|
12
|
+
require "cfn/status"
|
5
13
|
|
6
14
|
module Codebuild
|
7
15
|
class Error < StandardError; end
|
8
|
-
|
9
|
-
autoload :AwsServices, "codebuild/aws_services"
|
10
|
-
autoload :CLI, "codebuild/cli"
|
11
|
-
autoload :Command, "codebuild/command"
|
12
|
-
autoload :Completer, "codebuild/completer"
|
13
|
-
autoload :Completion, "codebuild/completion"
|
14
|
-
autoload :Create, "codebuild/create"
|
15
|
-
autoload :Delete, "codebuild/delete"
|
16
|
-
autoload :Deploy, "codebuild/deploy"
|
17
|
-
autoload :Dsl, "codebuild/dsl"
|
18
|
-
autoload :Evaluate, "codebuild/evaluate"
|
19
|
-
autoload :Help, "codebuild/help"
|
20
|
-
autoload :Init, "codebuild/init"
|
21
|
-
autoload :Project, "codebuild/project"
|
22
|
-
autoload :Role, "codebuild/role"
|
23
|
-
autoload :Sequence, "codebuild/sequence"
|
24
|
-
autoload :Stack, "codebuild/stack"
|
25
|
-
autoload :Start, "codebuild/start"
|
26
|
-
autoload :Update, "codebuild/update"
|
16
|
+
extend Core
|
27
17
|
end
|
18
|
+
|
19
|
+
|
20
|
+
Codebuild.set_aws_profile!
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# For methods, refer to the properties of the CloudFormation CodeBuild::Project https://amzn.to/2UTeNlr
|
2
2
|
# For convenience methods, refer to the source https://github.com/tongueroo/codebuild/blob/master/lib/codebuild/dsl/project.rb
|
3
3
|
|
4
|
-
name("
|
4
|
+
# name("example-project-name") # recommend leaving unset and codebuild will use a conventional name
|
5
5
|
github_url("<%= project_github_url %>")
|
6
6
|
linux_image("<%= lookup_managed_image(/ruby:/) %>")
|
7
7
|
environment_variables(
|
@@ -9,6 +9,10 @@ environment_variables(
|
|
9
9
|
# API_KEY: "ssm:/codebuild/demo/api_key" # Example of ssm parameter
|
10
10
|
)
|
11
11
|
|
12
|
+
# Some useful helpers:
|
13
|
+
# puts "project_name #{project_name}" # IE: demo-web
|
14
|
+
# puts "full_project_name #{full_project_name}" # demo-web-development
|
15
|
+
|
12
16
|
# Uncomment to enable github webhook, the GitHub oauth token needs admin:repo_hook permissions
|
13
17
|
# Refer to https://github.com/tongueroo/codebuild/blob/master/readme/github_oauth.md
|
14
18
|
# triggers(webhook: true)
|
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
# Example:
|
2
|
+
# iam_policy("logs", "ssm")
|
data/readme/github_oauth.md
CHANGED
@@ -4,9 +4,22 @@ Thought that we need to set the oauth token as part of the CloudFormation templa
|
|
4
4
|
|
5
5
|
Instead this guide [Using Access Tokens with Your Source Provider in CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/sample-access-tokens.html) with [aws codebuild import-source-credentials](https://docs.aws.amazon.com/cli/latest/reference/codebuild/import-source-credentials.html) worked.
|
6
6
|
|
7
|
+
## Create the GitHub Oauth Token
|
8
|
+
|
9
|
+
One way to create an GitHub oauth token:
|
10
|
+
|
11
|
+
1. Go to GitHub
|
12
|
+
2. Settings
|
13
|
+
3. Developer Settings
|
14
|
+
4. Personal access tokens
|
15
|
+
|
16
|
+
IMPORTANT: If using webhook, the oauth token needs `admin:repo_hook` also. To check this, you can log into the github, go to the repo, and see if you have access to the "Settings" tab.
|
17
|
+
|
18
|
+

|
19
|
+
|
7
20
|
## Commands
|
8
21
|
|
9
|
-
Here are the commands for posterity.
|
22
|
+
Here are the import-source-credentials commands for posterity.
|
10
23
|
|
11
24
|
Save the GitHub oauth token to parameter store, in case we need it in the future.
|
12
25
|
|
@@ -24,14 +37,3 @@ Import the source credential into codebuild.
|
|
24
37
|
EOL
|
25
38
|
aws codebuild import-source-credentials --cli-input-json file:///tmp/codebuild-source-credentials.json
|
26
39
|
aws codebuild list-source-credentials
|
27
|
-
|
28
|
-
## Creating the GitHub Oauth Token
|
29
|
-
|
30
|
-
One way to create an GitHub oauth token:
|
31
|
-
|
32
|
-
1. Go to GitHub
|
33
|
-
2. Settings
|
34
|
-
3. Developer Settings
|
35
|
-
4. Personal access tokens
|
36
|
-
|
37
|
-
If using webhook, the oauth token needs `admin:repo_hook` also.
|
data/readme/type.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Type Option
|
2
|
+
|
3
|
+
By default, the codebuild tool looks up files in the `.codebuild` folder. You can affect the behavior of the lookup logic with the `--type` option.
|
4
|
+
|
5
|
+
## Examples
|
6
|
+
|
7
|
+
cb deploy --type deploy
|
8
|
+
|
9
|
+
This will look up buildspec.yml, project.rb, and role.rb files in the `.codebuild/deploy` folder. So:
|
10
|
+
|
11
|
+
.codebuild/deploy/buildspec.yml
|
12
|
+
.codebuild/deploy/project.rb
|
13
|
+
.codebuild/deploy/role.rb
|
14
|
+
|
15
|
+
Likewise `cb deploy --type unit` would result in:
|
16
|
+
|
17
|
+
.codebuild/unit/buildspec.yml
|
18
|
+
.codebuild/unit/project.rb
|
19
|
+
.codebuild/unit/role.rb
|
20
|
+
|
21
|
+
## Type Stack Name
|
22
|
+
|
23
|
+
The CloudFormation stack name is appended with the name of the type option. So if you project folder is `demo` and the type option is `unit`.
|
24
|
+
|
25
|
+
cd demo # project folder
|
26
|
+
cb deploy --type deploy
|
27
|
+
|
28
|
+
It produces an inferred stack name of `demo-cb-deploy-development`. You can override the CloudFormation stack name by specifying the project name explicitly. The project name is an optional first argument. Here's an example:
|
29
|
+
|
30
|
+
cd demo # project folder
|
31
|
+
cb deploy demo-web --type deploy # stack name: demo-web-cb-deploy-development
|
32
|
+
|
33
|
+
You can also override the stack name with the `--stack-name` option.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codebuild
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: memoist
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: rainbow
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +108,20 @@ dependencies:
|
|
94
108
|
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: render_me_pretty
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
97
125
|
- !ruby/object:Gem::Dependency
|
98
126
|
name: thor
|
99
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -182,6 +210,7 @@ description:
|
|
182
210
|
email:
|
183
211
|
- tongueroo@gmail.com
|
184
212
|
executables:
|
213
|
+
- cb
|
185
214
|
- codebuild
|
186
215
|
extensions: []
|
187
216
|
extra_rdoc_files: []
|
@@ -189,7 +218,9 @@ files:
|
|
189
218
|
- ".codebuild/buildspec.yml"
|
190
219
|
- ".codebuild/project.rb"
|
191
220
|
- ".gitignore"
|
221
|
+
- ".gitmodules"
|
192
222
|
- ".rspec"
|
223
|
+
- ".ruby-version"
|
193
224
|
- CHANGELOG.md
|
194
225
|
- Gemfile
|
195
226
|
- Guardfile
|
@@ -197,8 +228,11 @@ files:
|
|
197
228
|
- README.md
|
198
229
|
- Rakefile
|
199
230
|
- codebuild.gemspec
|
231
|
+
- exe/cb
|
200
232
|
- exe/codebuild
|
233
|
+
- img/github-admin-settings-tab.png
|
201
234
|
- lib/codebuild.rb
|
235
|
+
- lib/codebuild/autoloader.rb
|
202
236
|
- lib/codebuild/aws_services.rb
|
203
237
|
- lib/codebuild/aws_services/helpers.rb
|
204
238
|
- lib/codebuild/cli.rb
|
@@ -206,10 +240,11 @@ files:
|
|
206
240
|
- lib/codebuild/completer.rb
|
207
241
|
- lib/codebuild/completer/script.rb
|
208
242
|
- lib/codebuild/completer/script.sh
|
243
|
+
- lib/codebuild/core.rb
|
209
244
|
- lib/codebuild/create.rb
|
245
|
+
- lib/codebuild/default/settings.yml
|
210
246
|
- lib/codebuild/delete.rb
|
211
247
|
- lib/codebuild/deploy.rb
|
212
|
-
- lib/codebuild/dsl.rb
|
213
248
|
- lib/codebuild/dsl/project.rb
|
214
249
|
- lib/codebuild/dsl/project/ssm.rb
|
215
250
|
- lib/codebuild/dsl/role.rb
|
@@ -224,6 +259,7 @@ files:
|
|
224
259
|
- lib/codebuild/project.rb
|
225
260
|
- lib/codebuild/role.rb
|
226
261
|
- lib/codebuild/sequence.rb
|
262
|
+
- lib/codebuild/setting.rb
|
227
263
|
- lib/codebuild/stack.rb
|
228
264
|
- lib/codebuild/start.rb
|
229
265
|
- lib/codebuild/update.rb
|
@@ -233,7 +269,7 @@ files:
|
|
233
269
|
- lib/template/.codebuild/role.rb
|
234
270
|
- readme/full_dsl.md
|
235
271
|
- readme/github_oauth.md
|
236
|
-
- readme/
|
272
|
+
- readme/type.md
|
237
273
|
- spec/fixtures/app/.codebuild/project.rb
|
238
274
|
- spec/fixtures/app/.codebuild/role.rb
|
239
275
|
- spec/lib/cli_spec.rb
|
@@ -259,7 +295,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
259
295
|
- !ruby/object:Gem::Version
|
260
296
|
version: '0'
|
261
297
|
requirements: []
|
262
|
-
rubygems_version: 3.0.
|
298
|
+
rubygems_version: 3.0.3
|
263
299
|
signing_key:
|
264
300
|
specification_version: 4
|
265
301
|
summary: CodeBuild DSL Tool to Quickly Create CodeBuild Project
|
data/lib/codebuild/dsl.rb
DELETED
data/readme/lookup.md
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# Lookup Paths
|
2
|
-
|
3
|
-
By default, the codebuild tool looks up files in the `.codebuild` folder. You can affect the behavior of the lookup logic with the `--lookup` option.
|
4
|
-
|
5
|
-
## Example 1
|
6
|
-
|
7
|
-
codebuild deploy --lookup unit
|
8
|
-
|
9
|
-
This will look up buildspec.yml, project.rb, and role.rb files in the `.codebuild/unit` folder first. If files are found, then it will use those files in that folder. If not found, it'll fall back to the `.codebuild` parent folder.
|
10
|
-
|
11
|
-
Lookup order with `--lookup unit` for `buildspec.yml`:
|
12
|
-
|
13
|
-
1. .codebuild/unit/buildspec.yml
|
14
|
-
2. .codebuild/buildspec.yml
|
15
|
-
|
16
|
-
Lookup order with `--lookup unit` for `project.rb`:
|
17
|
-
|
18
|
-
1. .codebuild/unit/project.rb
|
19
|
-
2. .codebuild/project.rb
|
20
|
-
|
21
|
-
The same goes other files in the `.codebuild` like `role.rb`.
|
22
|
-
|
23
|
-
## Example 2
|
24
|
-
|
25
|
-
Here's another example:
|
26
|
-
|
27
|
-
codebuild deploy --lookup deploy
|
28
|
-
|
29
|
-
Lookup order with `--lookup deploy` for `buildspec.yml`:
|
30
|
-
|
31
|
-
1. .codebuild/deploy/buildspec.yml
|
32
|
-
2. .codebuild/buildspec.yml
|
33
|
-
|
34
|
-
The same goes other files in the `.codebuild` like `project.rb` and `role.rb`.
|