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