cody 0.7.3 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1523d8ce4c22cf41cecba80623b9c473e49ff97d4b981972d5e277dde195da05
4
- data.tar.gz: 6deb1ea47229b7471c0f7de73f5d7f21d40aabb64560297b6e320e4a3e85fe9b
3
+ metadata.gz: d8ae54a008252e6ce83388bea8b82a78b6f3fff32724fc822b63d02baa39fdee
4
+ data.tar.gz: 717b8030c9046966f909eef2b64487482e1a8e1819d6e12d43747520499de642
5
5
  SHA512:
6
- metadata.gz: 6051044570a30f31b94ce57bd6a2a514ffd669cf0371ef30c8e14e4b50f57a6f6cc02d126a74d34a0aa2048b43f11f4370419fbaed93ee955cc61a973200227c
7
- data.tar.gz: a45a69611e76dd64d4dd9aac1c11598c1629c666a403f630f095f49cf6d84d407d556d32bf57912d4d487e2b2d58894cc1452b2b1b9976bc22f4bb90fd76d7ce
6
+ metadata.gz: 6a340b073735c12b2166ef78a43d79851c047780074a46f638021c7a0d7c60d8f380e4674ae2be09587f6b00400ced580391af72970cc96236869c108539fafe
7
+ data.tar.gz: 503328e1e3feb629877eb1dc901da9e2e3a52ed1a450b2da299ed662bb3cf38d9506d09ede8a8fccbb470186ebddaceeb4110ce37554d69a3146dc0b7dc17433
data/.cody/project.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  github_url("https://github.com/tongueroo/cody")
2
2
  linux_image("aws/codebuild/ruby:2.5.3-1.7.0")
3
- triggers(webhook: true)
3
+ triggers(
4
+ webhook: true,
5
+ filter_groups: [[{type: "EVENT", pattern: "PUSH"}]]
6
+ )
4
7
  local_cache(false)
data/.cody/role.rb ADDED
@@ -0,0 +1,14 @@
1
+ iam_policy(
2
+ action: [
3
+ "logs:CreateLogGroup",
4
+ "logs:CreateLogStream",
5
+ "logs:PutLogEvents",
6
+ "ssm:DescribeDocumentParameters",
7
+ "ssm:DescribeParameters",
8
+ "ssm:GetParameter*",
9
+ ],
10
+ effect: "Allow",
11
+ resource: "*"
12
+ )
13
+
14
+ managed_iam_policy("AWSCloudFormationReadOnlyAccess")
data/CHANGELOG.md CHANGED
@@ -3,6 +3,9 @@
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.8.0]
7
+ - #7 add cody logs command and automatically tail logs after a cody start
8
+
6
9
  ## [0.7.3]
7
10
  - cleanup starter buildspec.yml
8
11
 
data/README.md CHANGED
@@ -9,15 +9,14 @@
9
9
 
10
10
  [![BoltOps Badge](https://img.boltops.com/boltops/badges/boltops-badge.png)](https://www.boltops.com)
11
11
 
12
- Cody lets you create a AWS CodeBuild projects with a beautiful DSL.
13
-
14
- The documentation site is at: [cody.run](https://cody.run/)
12
+ Cody is an AWS CodeBuild Management Tool. Cody lets you create AWS CodeBuild projects with a beautiful DSL. The documentation site is at: [cody.run](https://cody.run/)
15
13
 
16
14
  ## Quick Start
17
15
 
18
16
  cody init
19
17
  cody deploy
20
18
  cody start
19
+ cody logs
21
20
 
22
21
  ## Private Repo
23
22
 
@@ -66,13 +65,19 @@ For more help:
66
65
 
67
66
  ### Start
68
67
 
69
- When you are ready to start a codebuild project run, you can use `codebuild start`. Examples:
68
+ When you are ready to start a codebuild project run, you can use [codebuild start](https://cody.run/reference/cody-start/). Examples:
70
69
 
71
70
  cody start # infers the name from the parent folder
72
71
  cody start PROJECT_NAME # looks up project via CodeBuild project name
73
72
 
74
73
  The `cody start` command understands multiple identifiers. It will look up the codebuild project either via CloudFormation or the CodeBuild project name.
75
74
 
75
+ The start command continuously polls the CodeBuild project and prints out the logs until the build completes. To disable this, use the `--no-wait` option.
76
+
77
+ cody start PROJECT_NAME --no-wait
78
+
79
+ The logs from the Phase Details and CloudWatch Logs are both displayed. Because they come from 2 different sources, the logs can interlace.
80
+
76
81
  ## Project DSL
77
82
 
78
83
  The tool provides a DSL to create a codebuild project. Here's an example.
data/cody.gemspec CHANGED
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
22
22
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.add_dependency "activesupport"
25
+ spec.add_dependency "activesupport", "~> 6.0.0"
26
+ spec.add_dependency "aws-logs"
26
27
  spec.add_dependency "aws-mfa-secure"
27
28
  spec.add_dependency "aws-sdk-cloudformation"
28
29
  spec.add_dependency "aws-sdk-codebuild"
data/lib/cody/cli.rb CHANGED
@@ -41,6 +41,15 @@ module Cody
41
41
  Start.new(options.merge(project_name: project_name)).run
42
42
  end
43
43
 
44
+ desc "logs", "Prints out logs for codebuild project."
45
+ long_desc Help.text(:logs)
46
+ option :build_id, desc: "Project build id. Defaults to most recent."
47
+ option :since, desc: "From what time to begin displaying logs. By default, logs will be displayed starting from 7 days in the past. The value provided can be an ISO 8601 timestamp or a relative time."
48
+ common_options.call
49
+ def logs(project_name=nil)
50
+ Logs.new(options.merge(project_name: project_name)).run
51
+ end
52
+
44
53
  desc "completion *PARAMS", "Prints words for auto-completion."
45
54
  long_desc Help.text(:completion)
46
55
  def completion(*params)
@@ -0,0 +1,62 @@
1
+ ## Examples
2
+
3
+ cody logs # project name inferred
4
+ cody logs PROJECT # project name explicit
5
+
6
+ ## Examples with Output
7
+
8
+ $ cody logs
9
+ Showing logs for build demo:ada202f1-6b30-4eb9-8625-7371a9911b7d
10
+ Phase: SUBMITTED Status: SUCCEEDED Duration: 0
11
+ Phase: QUEUED Status: SUCCEEDED Duration: 1
12
+ Phase: PROVISIONING Status: SUCCEEDED Duration: 40
13
+ Phase: DOWNLOAD_SOURCE Status: SUCCEEDED Duration: 0
14
+ Phase: INSTALL Status: SUCCEEDED Duration: 20
15
+ Phase: PRE_BUILD Status: SUCCEEDED Duration: 20
16
+ Phase: BUILD Status: SUCCEEDED Duration: 20
17
+ Phase: POST_BUILD Status: SUCCEEDED Duration: 20
18
+ Phase: UPLOAD_ARTIFACTS Status: SUCCEEDED Duration: 0
19
+ Phase: FINALIZING Status: SUCCEEDED Duration: 2
20
+ Phase: COMPLETED Status: Duration:
21
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:06 Waiting for agent ping
22
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Waiting for DOWNLOAD_SOURCE
23
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Phase is DOWNLOAD_SOURCE
24
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 CODEBUILD_SRC_DIR=/codebuild/output/src088335237/src/github.com/tongueroo/cody-demo
25
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 YAML location is /codebuild/output/src088335237/src/github.com/tongueroo/cody-demo/.cody/buildspec.yml
26
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Processing environment variables
27
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Moving to directory /codebuild/output/src088335237/src/github.com/tongueroo/cody-demo
28
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Registering with agent
29
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Phases found in YAML: 4
30
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 PRE_BUILD: 2 commands
31
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 BUILD: 2 commands
32
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 POST_BUILD: 2 commands
33
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 INSTALL: 2 commands
34
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Phase complete: DOWNLOAD_SOURCE State: SUCCEEDED
35
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Phase context status code: Message:
36
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Entering phase INSTALL
37
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Running command pwd
38
+ 2019-11-28 05:15:12 UTC /codebuild/output/src088335237/src/github.com/tongueroo/cody-demo
39
+ 2019-11-28 05:15:12 UTC
40
+ 2019-11-28 05:15:12 UTC [Container] 2019/11/28 05:15:08 Running command .cody/sleep.sh install
41
+ 2019-11-28 05:15:12 UTC 0: install
42
+ 2019-11-28 05:15:12 UTC Thu Nov 28 05:15:08 UTC 2019
43
+ ...
44
+ 19-11-28 05:16:29 UTC [Container] 2019/11/28 05:16:29 Phase complete: POST_BUILD State: SUCCEEDED
45
+ 2019-11-28 05:16:29 UTC [Container] 2019/11/28 05:16:29 Phase context status code: Message:
46
+ $
47
+
48
+ ## Since Option
49
+
50
+ By default, Cody logs searches only 7 days in the past. This is done for speed. If you have an older build and would like to search further in the past. You can use the `--since option`. Example:
51
+
52
+ cody logs --since 1m # 1 month ago
53
+
54
+ The since format is from the [aws-logs gem](https://github.com/tongueroo/aws-logs). Since formats:
55
+
56
+ * s - seconds
57
+ * m - minutes
58
+ * h - hours
59
+ * d - days
60
+ * w - weeks
61
+
62
+ Since does not support combining the formats. IE: 5m30s.
data/lib/cody/logs.rb ADDED
@@ -0,0 +1,27 @@
1
+ module Cody
2
+ class Logs
3
+ include AwsServices
4
+
5
+ def initialize(options)
6
+ @options = options
7
+ @project_name = options[:project_name] || inferred_project_name
8
+ @full_project_name = project_name_convention(@project_name)
9
+ end
10
+
11
+ def run
12
+ Tailer.new(@options, build_id).run
13
+ rescue Aws::CodeBuild::Errors::ResourceNotFoundException => e
14
+ puts "ERROR: #{e.class}: #{e.message}".color(:red)
15
+ puts "CodeBuild project #{@full_project_name} not found."
16
+ rescue Aws::CodeBuild::Errors::InvalidInputException => e
17
+ puts "ERROR: #{e.class}: #{e.message}".color(:red)
18
+ end
19
+
20
+ def build_id
21
+ return @options[:build_id] if @options[:build_id]
22
+
23
+ resp = codebuild.list_builds_for_project(project_name: @full_project_name)
24
+ resp.ids.first # most recent build_id
25
+ end
26
+ end
27
+ end
data/lib/cody/start.rb CHANGED
@@ -16,10 +16,15 @@ module Cody
16
16
  }
17
17
  params[:environment_variables_override] = environment_variables_override if @options[:env_vars]
18
18
  resp = codebuild.start_build(params)
19
+
19
20
  puts "Build started for project: #{project_name}"
20
- puts "Please check the CodeBuild console for the status."
21
- puts "CodeBuild Log Url:"
21
+ puts "Here's the CodeBuild Console Log url:"
22
22
  puts codebuild_log_url(resp.build.id)
23
+ tail_logs(resp.build.id) if @options[:wait]
24
+ end
25
+
26
+ def tail_logs(build_id)
27
+ Tailer.new(@options, build_id).run
23
28
  end
24
29
 
25
30
  def environment_variables_override
@@ -0,0 +1,119 @@
1
+ require "aws-logs"
2
+
3
+ module Cody
4
+ class Tailer
5
+ include AwsServices
6
+
7
+ def initialize(options, build_id)
8
+ @options, @build_id = options, build_id
9
+
10
+ @output = [] # for specs
11
+ @shown_phases = []
12
+ @thread = nil
13
+ set_trap
14
+ end
15
+
16
+ def find_build
17
+ resp = codebuild.batch_get_builds(ids: [@build_id])
18
+ resp.builds.first
19
+ end
20
+
21
+ def run
22
+ puts "Showing logs for build #{@build_id}"
23
+ complete = false
24
+ until complete do
25
+ build = find_build
26
+ unless build
27
+ puts "ERROR: Build id not found: #{@build_id}".color(:red)
28
+ return
29
+ end
30
+ print_phases(build)
31
+ set_log_group_name(build)
32
+
33
+ complete = build.build_complete
34
+ start_cloudwatch_tail unless ENV["CODY_TEST"]
35
+ sleep 5 if !@@end_loop_signal && !complete && !ENV["CODY_TEST"]
36
+ end
37
+ AwsLogs::Tail.stop_follow!
38
+ @thread.join if @thread
39
+ end
40
+
41
+ def start_cloudwatch_tail
42
+ return if @cloudwatch_tail_started
43
+ return unless @log_group_name && @log_stream_name
44
+
45
+ @thread = Thread.new do
46
+ cloudwatch_tail
47
+ end
48
+ @cloudwatch_tail_started = true
49
+ end
50
+
51
+ def cloudwatch_tail
52
+ since = @options[:since] || "7d" # by default, search only 7 days in the past
53
+ cw_tail = AwsLogs::Tail.new(
54
+ log_group_name: @log_group_name,
55
+ log_stream_names: [@log_stream_name],
56
+ since: since,
57
+ follow: true,
58
+ format: "simple",
59
+ )
60
+ cw_tail.run
61
+ end
62
+
63
+ # Setting enables start_cloudwatch_tail
64
+ def set_log_group_name(build)
65
+ logs = build.logs
66
+ @log_group_name = logs.group_name if logs.group_name
67
+ @log_stream_name = logs.stream_name if logs.stream_name
68
+ end
69
+
70
+ def print_phases(build)
71
+ build.phases.each do |phase|
72
+ details = {
73
+ phase_type: phase.phase_type,
74
+ phase_status: phase.phase_status,
75
+ start_time: phase.start_time,
76
+ duration_in_seconds: phase.duration_in_seconds,
77
+ }
78
+ display_phase(details)
79
+ @shown_phases << details
80
+ end
81
+ end
82
+
83
+ def display_phase(details)
84
+ already_shown = @shown_phases.detect do |p|
85
+ p[:phase_type] == details[:phase_type] &&
86
+ p[:phase_status] == details[:phase_status] &&
87
+ p[:start_time] == details[:start_time] &&
88
+ p[:duration_in_seconds] == details[:duration_in_seconds]
89
+ end
90
+ return if already_shown
91
+
92
+ status = details[:phase_status]
93
+ status = status&.include?("FAILED") ? status.color(:red) : status
94
+ say [
95
+ "Phase:".color(:green), details[:phase_type],
96
+ "Status:".color(:purple), status,
97
+ # "Time: ".color(:purple), details[:start_time],
98
+ "Duration:".color(:purple), details[:duration_in_seconds],
99
+ ].join(" ")
100
+ end
101
+
102
+ def say(text)
103
+ ENV["CODY_TEST"] ? @output << text : puts(text)
104
+ end
105
+
106
+ def output
107
+ @output.join("\n") + "\n"
108
+ end
109
+
110
+ @@end_loop_signal = false
111
+ def set_trap
112
+ Signal.trap("INT") {
113
+ puts "\nCtrl-C detected. Exiting..."
114
+ @@end_loop_signal = true # useful to control loop
115
+ exit # immediate exit
116
+ }
117
+ end
118
+ end
119
+ end
data/lib/cody/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Cody
2
- VERSION = "0.7.3"
2
+ VERSION = "0.8.0"
3
3
  end
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cody
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-20 00:00:00.000000000 Z
11
+ date: 2019-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 6.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-logs
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - ">="
@@ -230,6 +244,7 @@ extra_rdoc_files: []
230
244
  files:
231
245
  - ".cody/buildspec.yml"
232
246
  - ".cody/project.rb"
247
+ - ".cody/role.rb"
233
248
  - ".cody/settings.yml"
234
249
  - ".gitignore"
235
250
  - ".gitmodules"
@@ -268,8 +283,10 @@ files:
268
283
  - lib/cody/help/completion_script.md
269
284
  - lib/cody/help/deploy.md
270
285
  - lib/cody/help/init.md
286
+ - lib/cody/help/logs.md
271
287
  - lib/cody/help/start.md
272
288
  - lib/cody/init.rb
289
+ - lib/cody/logs.rb
273
290
  - lib/cody/project.rb
274
291
  - lib/cody/role.rb
275
292
  - lib/cody/schedule.rb
@@ -277,6 +294,7 @@ files:
277
294
  - lib/cody/setting.rb
278
295
  - lib/cody/stack.rb
279
296
  - lib/cody/start.rb
297
+ - lib/cody/tailer.rb
280
298
  - lib/cody/update.rb
281
299
  - lib/cody/variables.rb
282
300
  - lib/cody/version.rb