codebuild 0.1.0 → 0.2.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/.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
|
+

|
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
|