codebuild 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codebuild/buildspec.yml +8 -0
- data/.codebuild/project.rb +16 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +7 -0
- data/README.md +118 -4
- data/codebuild.gemspec +5 -2
- data/lib/codebuild/aws_services/helpers.rb +52 -0
- data/lib/codebuild/aws_services.rb +17 -0
- data/lib/codebuild/cli.rb +50 -4
- data/lib/codebuild/create.rb +12 -0
- data/lib/codebuild/delete.rb +26 -0
- data/lib/codebuild/deploy.rb +11 -0
- data/lib/codebuild/dsl/project/ssm.rb +22 -0
- data/lib/codebuild/dsl/project.rb +116 -0
- data/lib/codebuild/dsl/role.rb +40 -0
- data/lib/codebuild/dsl.rb +8 -0
- data/lib/codebuild/evaluate.rb +52 -0
- data/lib/codebuild/help/deploy.md +8 -0
- data/lib/codebuild/help/init.md +24 -0
- data/lib/codebuild/help/start.md +6 -0
- data/lib/codebuild/init.rb +75 -0
- data/lib/codebuild/project.rb +62 -0
- data/lib/codebuild/role.rb +73 -0
- data/lib/codebuild/sequence.rb +60 -0
- data/lib/codebuild/stack.rb +34 -0
- data/lib/codebuild/start.rb +39 -0
- data/lib/codebuild/update.rb +12 -0
- data/lib/codebuild/version.rb +1 -1
- data/lib/codebuild.rb +14 -2
- data/lib/template/.codebuild/buildspec.yml +12 -4
- data/lib/template/.codebuild/project.rb.tt +17 -0
- data/lib/template/.codebuild/role.rb +1 -0
- data/readme/full_dsl.md +84 -0
- data/readme/github_oauth.md +37 -0
- data/readme/lookup.md +34 -0
- data/spec/fixtures/app/.codebuild/project.rb +2 -0
- data/spec/fixtures/app/.codebuild/role.rb +1 -0
- data/spec/lib/cli_spec.rb +10 -30
- data/spec/lib/project_spec.rb +12 -0
- data/spec/lib/role_spec.rb +12 -0
- metadata +83 -10
- data/Gemfile.lock +0 -80
- data/lib/codebuild/help/hello.md +0 -5
- data/lib/template/.codebuild/buildspec-example.yml +0 -37
- data/lib/template/.codebuild/project.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57f656279e8afad7619113d3834b6af34c1dd7d583934b2829f7a621e8a07c60
|
4
|
+
data.tar.gz: e72dcd6f7db6f3b9569074e41f0c478aaf808def00360a00eabf7eea4aeee4fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64c0580f8f1dfdfefc7494cdb33a4d7805d2867158b76334f5725cc5f5fdf1103e116b160b912c1a60a8da6dcec39a2a8e6a8fd0d372e57e367e55c073028378
|
7
|
+
data.tar.gz: 856cf81c1c5c6eda69a87933727c9924ae9548c398adefed1c12503fd6f92bcc67518dfaa23b0f9c04ba80d269a75db3f800297cd9bf1258133c0e67f41dafe7
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# For methods, refer to the properties of the CloudFormation CodeBuild::Project https://amzn.to/2UTeNlr
|
2
|
+
# For convenience methods, refer to the source https://github.com/tongueroo/codebuild/blob/master/lib/codebuild/dsl/project.rb
|
3
|
+
|
4
|
+
# Note: for the oauth_token, you have to set this parameter in ssm parameter store
|
5
|
+
# One way to create an GitHub oauth token:
|
6
|
+
# Go to GitHub / Settings / Developer Settings / Personal access tokens
|
7
|
+
# If using webhook, the oauth token needs admin:repo_hook
|
8
|
+
|
9
|
+
name("codebuild")
|
10
|
+
github_url("https://github.com/tongueroo/codebuild")
|
11
|
+
linux_image("aws/codebuild/ruby:2.5.3-1.7.0")
|
12
|
+
environment_variables(
|
13
|
+
JETS_ENV: "test",
|
14
|
+
)
|
15
|
+
triggers(webhook: true)
|
16
|
+
local_cache(false)
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/CHANGELOG.md
CHANGED
@@ -3,5 +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.2.0]
|
7
|
+
- First good release.
|
8
|
+
- Project and Role DSL
|
9
|
+
- codebuild commands: init, deploy, start
|
10
|
+
- lookup path support
|
11
|
+
- Docs in main readme and readme folder
|
12
|
+
|
6
13
|
## [0.1.0]
|
7
14
|
- Initial release.
|
data/README.md
CHANGED
@@ -1,14 +1,128 @@
|
|
1
1
|
# Codebuild
|
2
2
|
|
3
|
-
|
3
|
+
![Build Status](https://codebuild.us-west-2.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoidHFFaithL1pLZWFEUzBXbk5LY05Mc0FrZW56NDVJWTArbUlOdzBUalVPWWZ5a1ZYUEFtTkhlbFBjeURRZEd1Q292WTI1RUJwWkcvdEgxUXhSYnBqVU9VPSIsIml2UGFyYW1ldGVyU3BlYyI6IjJ0dnpqMC9XMzQ4VExCMGgiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master)
|
4
4
|
|
5
|
-
|
5
|
+
Tool creates a CodeBuild project with some reasonable defaults. It provides a DSL that can be used to create and override setting if required.
|
6
|
+
|
7
|
+
## Quick Start
|
6
8
|
|
7
9
|
codebuild init
|
8
|
-
codebuild
|
9
|
-
codebuild update
|
10
|
+
codebuild deploy
|
10
11
|
codebuild start
|
11
12
|
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
1. **init**: generate starter .codebuild files.
|
16
|
+
2. **deploy**: deploy the CodeBuild project on AWS.
|
17
|
+
3. **start**: kick off a CodeBuild project run.
|
18
|
+
|
19
|
+
### Init
|
20
|
+
|
21
|
+
First, run `codebuild init` to generate a starter .codebuild structure.
|
22
|
+
|
23
|
+
$ tree .codebuild
|
24
|
+
.codebuild
|
25
|
+
├── buildspec.yml
|
26
|
+
├── project.rb
|
27
|
+
└── role.rb
|
28
|
+
|
29
|
+
File | Description
|
30
|
+
--- | ---
|
31
|
+
buildspec.yml | The build commands to run.
|
32
|
+
project.rb | The codebuild project defined as a DSL.
|
33
|
+
role.rb | The IAM role assocaited with the codebuild project defined as a DSL.
|
34
|
+
|
35
|
+
### Deploy
|
36
|
+
|
37
|
+
Adjust the files in `.codebuild` to fit your needs. When you're ready, deploy the CodeBuild project with:
|
38
|
+
|
39
|
+
codebuild deploy STACK_NAME
|
40
|
+
|
41
|
+
More examples:
|
42
|
+
|
43
|
+
codebuild deploy # infers the CloudFormation name from the parent folder
|
44
|
+
codebuild deploy stack-name # explicitly specify stack name
|
45
|
+
|
46
|
+
It is useful to just see the generated CloudFormation template with `--noop` mode:
|
47
|
+
|
48
|
+
codebuild deploy --noop # see generated CloudFormation template
|
49
|
+
|
50
|
+
For more help:
|
51
|
+
|
52
|
+
codebuild deploy -h
|
53
|
+
|
54
|
+
### Start
|
55
|
+
|
56
|
+
When you are ready to start a codebuild project run, you can use `codebuild start`. Examples:
|
57
|
+
|
58
|
+
codebuild start # infers the name from the parent folder
|
59
|
+
codebuild start stack-name # looks up project via CloudFormation stack
|
60
|
+
codebuild start demo-project # looks up project via CodeBuild project name
|
61
|
+
|
62
|
+
The `codebuild start` command understands multiple identifiers. It will look up the codebuild project either via CloudFormation or the CodeBuild project name.
|
63
|
+
|
64
|
+
## Project DSL
|
65
|
+
|
66
|
+
The tool provides a DSL to create a codebuild project. Here's an example.
|
67
|
+
|
68
|
+
.codebuild/project.rb:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
name("demo")
|
72
|
+
github_url("https://github.com/tongueroo/demo-ufo")
|
73
|
+
linux_image("aws/codebuild/ruby:2.5.3-1.7.0")
|
74
|
+
environment_variables(
|
75
|
+
UFO_ENV: "development",
|
76
|
+
API_KEY: "ssm:/codebuild/demo/api_key"
|
77
|
+
)
|
78
|
+
```
|
79
|
+
|
80
|
+
Here's a list of some of the convenience shorthand DSL methods:
|
81
|
+
|
82
|
+
* github_url(url)
|
83
|
+
* github_source(options={})
|
84
|
+
* linux_image(name)
|
85
|
+
* linux_environment(options={})
|
86
|
+
* environment_variables(vars)
|
87
|
+
* local_cache(enable=true)
|
88
|
+
|
89
|
+
Please refer to [lib/codebuild/dsl/project.rb](lib/codebuild/dsl/project.rb) for the full list.
|
90
|
+
|
91
|
+
More slightly more control, you may be interested in the `github_source` and `linux_environment` methods. For even more control, see [Full DSL docs](readme/full_dsl.md).
|
92
|
+
|
93
|
+
## IAM Role DSL
|
94
|
+
|
95
|
+
The codebuild tool can create the IAM service role associated with the codebuild project. Here's an example:
|
96
|
+
|
97
|
+
.codebuild/role.rb:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
iam_policy("logs", "ssm")
|
101
|
+
```
|
102
|
+
|
103
|
+
For more control, here's a longer form:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
iam_policy(
|
107
|
+
action: [
|
108
|
+
"logs:CreateLogGroup",
|
109
|
+
"logs:CreateLogStream",
|
110
|
+
"logs:PutLogEvents",
|
111
|
+
"ssm:*",
|
112
|
+
],
|
113
|
+
effect: "Allow",
|
114
|
+
resource: "*"
|
115
|
+
)
|
116
|
+
```
|
117
|
+
|
118
|
+
## Full DSL
|
119
|
+
|
120
|
+
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
|
+
|
122
|
+
## Lookup Paths
|
123
|
+
|
124
|
+
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. More info [Lookup docs](readme/lookup.md).
|
125
|
+
|
12
126
|
## Installation
|
13
127
|
|
14
128
|
Add this line to your application's Gemfile:
|
data/codebuild.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Codebuild::VERSION
|
9
9
|
spec.authors = ["Tung Nguyen"]
|
10
10
|
spec.email = ["tongueroo@gmail.com"]
|
11
|
-
spec.summary = "
|
11
|
+
spec.summary = "CodeBuild DSL Tool to Quickly Create CodeBuild Project"
|
12
12
|
spec.homepage = "https://github.com/tongueroo/codebuild"
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
@@ -19,9 +19,12 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "activesupport"
|
22
|
+
spec.add_dependency "aws-sdk-cloudformation"
|
23
|
+
spec.add_dependency "aws-sdk-codebuild"
|
24
|
+
spec.add_dependency "aws-sdk-ssm"
|
25
|
+
spec.add_dependency "cfn_camelizer"
|
22
26
|
spec.add_dependency "rainbow"
|
23
27
|
spec.add_dependency "thor"
|
24
|
-
spec.add_dependency "aws-sdk-codebuild"
|
25
28
|
|
26
29
|
spec.add_development_dependency "bundler"
|
27
30
|
spec.add_development_dependency "byebug"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Codebuild::AwsServices
|
2
|
+
module Helpers
|
3
|
+
def stack_exists?(stack_name)
|
4
|
+
return false if ENV['TEST']
|
5
|
+
|
6
|
+
exist = nil
|
7
|
+
begin
|
8
|
+
# When the stack does not exist an exception is raised. Example:
|
9
|
+
# Aws::CloudFormation::Errors::ValidationError: Stack with id blah does not exist
|
10
|
+
cfn.describe_stacks(stack_name: stack_name)
|
11
|
+
exist = true
|
12
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
13
|
+
if e.message =~ /does not exist/
|
14
|
+
exist = false
|
15
|
+
elsif e.message.include?("'stackName' failed to satisfy constraint")
|
16
|
+
# Example of e.message when describe_stack with invalid stack name
|
17
|
+
# "1 validation error detected: Value 'instance_and_route53' at 'stackName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*|arn:[-a-zA-Z0-9:/._+]*"
|
18
|
+
puts "Invalid stack name: #{stack_name}"
|
19
|
+
puts "Full error message: #{e.message}"
|
20
|
+
exit 1
|
21
|
+
else
|
22
|
+
raise # re-raise exception because unsure what other errors can happen
|
23
|
+
end
|
24
|
+
end
|
25
|
+
exist
|
26
|
+
end
|
27
|
+
|
28
|
+
def inferred_stack_name
|
29
|
+
File.basename(Dir.pwd).gsub('_','-').gsub(/[^0-9a-zA-Z,-]/, '')
|
30
|
+
end
|
31
|
+
|
32
|
+
def are_you_sure?(stack_name, action)
|
33
|
+
if @options[:sure]
|
34
|
+
sure = 'y'
|
35
|
+
else
|
36
|
+
message = case action
|
37
|
+
when :update
|
38
|
+
"Are you sure you want to want to update the #{stack_name.color(:green)} stack with the changes? (y/N)"
|
39
|
+
when :delete
|
40
|
+
"Are you sure you want to want to delete the #{stack_name.color(:green)} stack? (y/N)"
|
41
|
+
end
|
42
|
+
puts message
|
43
|
+
sure = $stdin.gets
|
44
|
+
end
|
45
|
+
|
46
|
+
unless sure =~ /^y/
|
47
|
+
puts "Whew! Exiting without running #{action}."
|
48
|
+
exit 0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "aws-sdk-codebuild"
|
2
|
+
require "aws-sdk-cloudformation"
|
3
|
+
|
4
|
+
module Codebuild
|
5
|
+
module AwsServices
|
6
|
+
autoload :Helpers, "codebuild/aws_services/helpers"
|
7
|
+
include Helpers
|
8
|
+
|
9
|
+
def codebuild
|
10
|
+
@codebuild ||= Aws::CodeBuild::Client.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def cfn
|
14
|
+
@cfn ||= Aws::CloudFormation::Client.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/codebuild/cli.rb
CHANGED
@@ -5,18 +5,64 @@ module Codebuild
|
|
5
5
|
|
6
6
|
desc "init", "Initialize project with .codebuild files"
|
7
7
|
long_desc Help.text(:init)
|
8
|
-
|
9
|
-
|
8
|
+
Init.cli_options.each do |args|
|
9
|
+
option(*args)
|
10
|
+
end
|
11
|
+
register(Init, "init", "init", "Set up initial ufo files.")
|
12
|
+
|
13
|
+
desc "evaluate", "Evaluate the .codebuild/project.rb DSL."
|
14
|
+
long_desc Help.text(:evaluate)
|
15
|
+
def evaluate
|
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
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "deploy", "Deploy codebuild project."
|
38
|
+
long_desc Help.text(:deploy)
|
39
|
+
deploy_options.call
|
40
|
+
def deploy(stack_name=nil)
|
41
|
+
Deploy.new(options.merge(stack_name: stack_name)).run
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "delete", "Delete codebuild project."
|
45
|
+
long_desc Help.text(:delete)
|
46
|
+
option :sure, desc: "Bypass are you sure prompt"
|
47
|
+
def delete(stack_name=nil)
|
48
|
+
Delete.new(options.merge(stack_name: stack_name)).run
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "start", "start codebuild project."
|
52
|
+
long_desc Help.text(:start)
|
53
|
+
option :source_version, default: "master", desc: "git branch"
|
54
|
+
def start(identifier=nil)
|
55
|
+
Start.new(options.merge(identifier: identifier)).run
|
10
56
|
end
|
11
57
|
|
12
58
|
desc "completion *PARAMS", "Prints words for auto-completion."
|
13
|
-
long_desc Help.text(
|
59
|
+
long_desc Help.text(:completion)
|
14
60
|
def completion(*params)
|
15
61
|
Completer.new(CLI, *params).run
|
16
62
|
end
|
17
63
|
|
18
64
|
desc "completion_script", "Generates a script that can be eval to setup auto-completion."
|
19
|
-
long_desc Help.text(
|
65
|
+
long_desc Help.text(:completion_script)
|
20
66
|
def completion_script
|
21
67
|
Completer::Script.generate
|
22
68
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Codebuild
|
2
|
+
class Create < Stack
|
3
|
+
def perform
|
4
|
+
cfn.create_stack(
|
5
|
+
stack_name: @stack_name,
|
6
|
+
template_body: YAML.dump(@template),
|
7
|
+
capabilities: ["CAPABILITY_IAM"]
|
8
|
+
)
|
9
|
+
puts "Creating stack #{@stack_name}. Check CloudFormation console for status."
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Codebuild
|
2
|
+
class Delete
|
3
|
+
include AwsServices
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
@options = options
|
7
|
+
@stack_name = options[:stack_name] || inferred_stack_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
message = "Deleted #{@stack_name} stack."
|
12
|
+
if @options[:noop]
|
13
|
+
puts "NOOP #{message}"
|
14
|
+
else
|
15
|
+
are_you_sure?(@stack_name, :delete)
|
16
|
+
|
17
|
+
if stack_exists?(@stack_name)
|
18
|
+
cfn.delete_stack(stack_name: @stack_name)
|
19
|
+
puts message
|
20
|
+
else
|
21
|
+
puts "#{@stack_name.inspect} stack does not exist".color(:red)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "aws-sdk-ssm"
|
2
|
+
|
3
|
+
module Codebuild::Dsl::Project
|
4
|
+
module Ssm
|
5
|
+
# This method grabs the ssm parameter store value at "compile" time vs
|
6
|
+
# CloudFormation run time. In case we need it as part of the DSL compile phase.
|
7
|
+
def ssm(name)
|
8
|
+
resp = ssm_client.get_parameter(name: name)
|
9
|
+
if resp.parameter.type == "SecureString"
|
10
|
+
resp = ssm_client.get_parameter(name: name, with_decryption: true)
|
11
|
+
end
|
12
|
+
|
13
|
+
resp.parameter.value
|
14
|
+
rescue Aws::SSM::Errors::ParameterNotFound
|
15
|
+
puts "WARN: #{name} found on AWS SSM.".color(:yellow)
|
16
|
+
end
|
17
|
+
|
18
|
+
def ssm_client
|
19
|
+
@ssm_client ||= Aws::SSM::Client.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Codebuild::Dsl
|
2
|
+
module Project
|
3
|
+
autoload :Ssm, "codebuild/dsl/project/ssm"
|
4
|
+
include Ssm
|
5
|
+
|
6
|
+
PROPERTIES = %w[
|
7
|
+
artifacts
|
8
|
+
badge_enabled
|
9
|
+
cache
|
10
|
+
description
|
11
|
+
encryption_key
|
12
|
+
environment
|
13
|
+
logs_config
|
14
|
+
name
|
15
|
+
queued_timeout_in_minutes
|
16
|
+
secondary_artifacts
|
17
|
+
secondary_sources
|
18
|
+
service_role
|
19
|
+
source
|
20
|
+
tags
|
21
|
+
timeout_in_minutes
|
22
|
+
triggers
|
23
|
+
vpc_config
|
24
|
+
]
|
25
|
+
PROPERTIES.each do |prop|
|
26
|
+
define_method(prop) do |v|
|
27
|
+
@properties[prop.to_sym] = v
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Convenience wrapper methods
|
32
|
+
def github_url(url)
|
33
|
+
@properties[:source][:location] = url
|
34
|
+
end
|
35
|
+
|
36
|
+
# So it looks like the auth resource property doesnt really get used.
|
37
|
+
# Instead an account level credential is worked. Refer to:
|
38
|
+
# https://github.com/tongueroo/codebuild/blob/master/readme/github_oauth.md
|
39
|
+
#
|
40
|
+
# Keeping this method around in case the CloudFormation method works one day,
|
41
|
+
# or end up figuring out to use it properly.
|
42
|
+
def github_token(token)
|
43
|
+
@properties[:source][:auth][:resource] = token
|
44
|
+
end
|
45
|
+
|
46
|
+
def github_source(options={})
|
47
|
+
source = {
|
48
|
+
type: "GITHUB",
|
49
|
+
location: options[:location],
|
50
|
+
git_clone_depth: 1,
|
51
|
+
git_submodules_config: { fetch_submodules: true },
|
52
|
+
build_spec: options[:buildspec] || ".codebuild/buildspec.yml",
|
53
|
+
report_build_status: true,
|
54
|
+
}
|
55
|
+
|
56
|
+
if options[:oauth_token]
|
57
|
+
source[:auth] = {
|
58
|
+
type: "OAUTH",
|
59
|
+
resource: options[:oauth_token],
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
@properties[:source] = source
|
64
|
+
end
|
65
|
+
|
66
|
+
def linux_image(name)
|
67
|
+
linux_environment(image: name)
|
68
|
+
end
|
69
|
+
|
70
|
+
def linux_environment(options={})
|
71
|
+
image = options[:image] || "aws/codebuild/ruby:2.5.3-1.7.0"
|
72
|
+
env = {
|
73
|
+
compute_type: options[:compute_type] || "BUILD_GENERAL1_SMALL",
|
74
|
+
image_pull_credentials_type: "CODEBUILD", # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environment.html#cfn-codebuild-project-environment-imagepullcredentialstype
|
75
|
+
privileged_mode: true,
|
76
|
+
image: image,
|
77
|
+
type: "LINUX_CONTAINER"
|
78
|
+
}
|
79
|
+
# @mapped_env_vars is in memory
|
80
|
+
env[:environment_variables] = @mapped_env_vars if @mapped_env_vars
|
81
|
+
# options has highest precedence
|
82
|
+
env[:environment_variables] = options[:environment_variables] if options[:environment_variables]
|
83
|
+
@properties[:environment] = env
|
84
|
+
end
|
85
|
+
|
86
|
+
def environment_variables(vars)
|
87
|
+
@env_vars = vars
|
88
|
+
@mapped_env_vars = @env_vars.map { |k,v|
|
89
|
+
k = k.to_s
|
90
|
+
if v =~ /^ssm:/
|
91
|
+
{ type: "PARAMETER_STORE", name: k, value: v.sub('ssm:','') }
|
92
|
+
else
|
93
|
+
{ type: "PLAINTEXT", name: k, value: v }
|
94
|
+
end
|
95
|
+
}
|
96
|
+
@properties[:environment] ||= {}
|
97
|
+
@properties[:environment][:environment_variables] = @mapped_env_vars
|
98
|
+
end
|
99
|
+
|
100
|
+
def local_cache(enable=true)
|
101
|
+
cache = if enable
|
102
|
+
{
|
103
|
+
type: "LOCAL",
|
104
|
+
modes: [
|
105
|
+
"LOCAL_DOCKER_LAYER_CACHE",
|
106
|
+
"LOCAL_SOURCE_CACHE",
|
107
|
+
"LOCAL_CUSTOM_CACHE"
|
108
|
+
]
|
109
|
+
}
|
110
|
+
else
|
111
|
+
{type: "NO_CACHE"}
|
112
|
+
end
|
113
|
+
@properties[:cache] = cache
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Codebuild::Dsl
|
2
|
+
module Role
|
3
|
+
PROPERTIES = %w[
|
4
|
+
assume_role_policy_document
|
5
|
+
managed_policy_arns
|
6
|
+
max_session_duration
|
7
|
+
path
|
8
|
+
permissions_boundary
|
9
|
+
policies
|
10
|
+
role_name
|
11
|
+
]
|
12
|
+
PROPERTIES.each do |prop|
|
13
|
+
define_method(prop) do |v|
|
14
|
+
@properties[prop.to_sym] = v
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# convenience wrapper methods
|
19
|
+
def iam_policy(*definitions)
|
20
|
+
@iam_statements = definitions.map { |definition| standardize(definition) }
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns standarized IAM statement
|
24
|
+
def standardize(definition)
|
25
|
+
case definition
|
26
|
+
when String
|
27
|
+
# Expands simple string from: logs => logs:*
|
28
|
+
definition = "#{definition}:*" unless definition.include?(':')
|
29
|
+
{
|
30
|
+
action: [definition],
|
31
|
+
effect: "Allow",
|
32
|
+
resource: "*",
|
33
|
+
}
|
34
|
+
when Hash
|
35
|
+
definition
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Codebuild
|
2
|
+
module Evaluate
|
3
|
+
def evaluate(path)
|
4
|
+
source_code = IO.read(path)
|
5
|
+
begin
|
6
|
+
instance_eval(source_code, path)
|
7
|
+
rescue Exception => e
|
8
|
+
if e.class == SystemExit # allow exit to happen normally
|
9
|
+
raise
|
10
|
+
else
|
11
|
+
task_definition_error(e)
|
12
|
+
puts "\nFull error:"
|
13
|
+
raise
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
# Prints out a user friendly task_definition error message
|
20
|
+
def task_definition_error(e)
|
21
|
+
error_info = e.backtrace.first
|
22
|
+
path, line_no, _ = error_info.split(':')
|
23
|
+
line_no = line_no.to_i
|
24
|
+
puts "Error evaluating #{path}:".color(:red)
|
25
|
+
puts e.message
|
26
|
+
puts "Here's the line in #{path} with the error:\n\n"
|
27
|
+
|
28
|
+
contents = IO.read(path)
|
29
|
+
content_lines = contents.split("\n")
|
30
|
+
context = 5 # lines of context
|
31
|
+
top, bottom = [line_no-context-1, 0].max, line_no+context-1
|
32
|
+
spacing = content_lines.size.to_s.size
|
33
|
+
content_lines[top..bottom].each_with_index do |line_content, index|
|
34
|
+
line_number = top+index+1
|
35
|
+
if line_number == line_no
|
36
|
+
printf("%#{spacing}d %s\n".color(:red), line_number, line_content)
|
37
|
+
else
|
38
|
+
printf("%#{spacing}d %s\n", line_number, line_content)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def lookup_codebuild_file(name)
|
44
|
+
folder_path = [".codebuild", @options[:lookup], name].compact.join("/")
|
45
|
+
if File.exist?(folder_path)
|
46
|
+
folder_path
|
47
|
+
else
|
48
|
+
".codebuild/#{name}" # default
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
## Examples
|
2
|
+
|
3
|
+
codebuild deploy # infers the CloudFormation name from the parent folder
|
4
|
+
codebuild deploy stack-name # explicitly specify stack name
|
5
|
+
|
6
|
+
It is useful to just see the generated CloudFormation template with `--noop` mode:
|
7
|
+
|
8
|
+
codebuild deploy --noop # see generated CloudFormation template
|