codebuild 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.codebuild/buildspec.yml +8 -0
  3. data/.codebuild/project.rb +16 -0
  4. data/.gitignore +2 -0
  5. data/.rspec +1 -0
  6. data/CHANGELOG.md +7 -0
  7. data/README.md +118 -4
  8. data/codebuild.gemspec +5 -2
  9. data/lib/codebuild/aws_services/helpers.rb +52 -0
  10. data/lib/codebuild/aws_services.rb +17 -0
  11. data/lib/codebuild/cli.rb +50 -4
  12. data/lib/codebuild/create.rb +12 -0
  13. data/lib/codebuild/delete.rb +26 -0
  14. data/lib/codebuild/deploy.rb +11 -0
  15. data/lib/codebuild/dsl/project/ssm.rb +22 -0
  16. data/lib/codebuild/dsl/project.rb +116 -0
  17. data/lib/codebuild/dsl/role.rb +40 -0
  18. data/lib/codebuild/dsl.rb +8 -0
  19. data/lib/codebuild/evaluate.rb +52 -0
  20. data/lib/codebuild/help/deploy.md +8 -0
  21. data/lib/codebuild/help/init.md +24 -0
  22. data/lib/codebuild/help/start.md +6 -0
  23. data/lib/codebuild/init.rb +75 -0
  24. data/lib/codebuild/project.rb +62 -0
  25. data/lib/codebuild/role.rb +73 -0
  26. data/lib/codebuild/sequence.rb +60 -0
  27. data/lib/codebuild/stack.rb +34 -0
  28. data/lib/codebuild/start.rb +39 -0
  29. data/lib/codebuild/update.rb +12 -0
  30. data/lib/codebuild/version.rb +1 -1
  31. data/lib/codebuild.rb +14 -2
  32. data/lib/template/.codebuild/buildspec.yml +12 -4
  33. data/lib/template/.codebuild/project.rb.tt +17 -0
  34. data/lib/template/.codebuild/role.rb +1 -0
  35. data/readme/full_dsl.md +84 -0
  36. data/readme/github_oauth.md +37 -0
  37. data/readme/lookup.md +34 -0
  38. data/spec/fixtures/app/.codebuild/project.rb +2 -0
  39. data/spec/fixtures/app/.codebuild/role.rb +1 -0
  40. data/spec/lib/cli_spec.rb +10 -30
  41. data/spec/lib/project_spec.rb +12 -0
  42. data/spec/lib/role_spec.rb +12 -0
  43. metadata +83 -10
  44. data/Gemfile.lock +0 -80
  45. data/lib/codebuild/help/hello.md +0 -5
  46. data/lib/template/.codebuild/buildspec-example.yml +0 -37
  47. data/lib/template/.codebuild/project.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eddc827d24d5707f612e5fc445c838a5ff90293e21518ecb3b65f33211601788
4
- data.tar.gz: ee1885f87b9a060622957287f4d35f772d02924acb3de20ad9e08faa442063e9
3
+ metadata.gz: 57f656279e8afad7619113d3834b6af34c1dd7d583934b2829f7a621e8a07c60
4
+ data.tar.gz: e72dcd6f7db6f3b9569074e41f0c478aaf808def00360a00eabf7eea4aeee4fc
5
5
  SHA512:
6
- metadata.gz: 8f49961753e2106d88252b038bfdc268517be497f2a4361f7edc8a1694bcc4c2c146ec872ae8fa94ac1d42168f250c92b4aa2e41f812ae3cf4cde3b9c6bc9710
7
- data.tar.gz: 98133343e44e59f1dcb33db2136995a4caf121c865b51eb2ac978e2277984bbd930bcd8565bbe6c7673608810d00568f98e6febf4e3f47a6c158f125b446b32b
6
+ metadata.gz: 64c0580f8f1dfdfefc7494cdb33a4d7805d2867158b76334f5725cc5f5fdf1103e116b160b912c1a60a8da6dcec39a2a8e6a8fd0d372e57e367e55c073028378
7
+ data.tar.gz: 856cf81c1c5c6eda69a87933727c9924ae9548c398adefed1c12503fd6f92bcc67518dfaa23b0f9c04ba80d269a75db3f800297cd9bf1258133c0e67f41dafe7
@@ -0,0 +1,8 @@
1
+ version: 0.2
2
+
3
+ phases:
4
+ build:
5
+ commands:
6
+ - echo Build started on `date`
7
+ - bundle
8
+ - bundle exec rspec
@@ -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
@@ -14,3 +14,5 @@ spec/reports
14
14
  test/tmp
15
15
  test/version_tmp
16
16
  tmp
17
+
18
+ Gemfile.lock
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
2
  --format documentation
3
+ --require spec_helper
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
- CodeBuild tool.
3
+ ![Build Status](https://codebuild.us-west-2.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoidHFFaithL1pLZWFEUzBXbk5LY05Mc0FrZW56NDVJWTArbUlOdzBUalVPWWZ5a1ZYUEFtTkhlbFBjeURRZEd1Q292WTI1RUJwWkcvdEgxUXhSYnBqVU9VPSIsIml2UGFyYW1ldGVyU3BlYyI6IjJ0dnpqMC9XMzQ4VExCMGgiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master)
4
4
 
5
- ## Usage
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 create
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 = "Codebuild tool"
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
- def init
9
- puts "init called"
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("completion")
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("completion_script")
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,11 @@
1
+ module Codebuild
2
+ class Deploy < Stack
3
+ def run
4
+ if stack_exists?(@stack_name)
5
+ Update.new(@options).run
6
+ else
7
+ Create.new(@options).run
8
+ end
9
+ end
10
+ end
11
+ 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,8 @@
1
+ require "yaml"
2
+
3
+ module Codebuild
4
+ module Dsl
5
+ autoload :Project, "codebuild/dsl/project"
6
+ autoload :Role, "codebuild/dsl/role"
7
+ end
8
+ 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