concourse 0.21.0 → 0.22.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: 4dbaa8912766aa4a943e923a480f29d28e48c6a1cd685441a8a9032c674416e5
4
- data.tar.gz: 609eda21fa25d678fc45bcb271ac9899040caaa074dbd748a9f68f1b8b84b5bd
3
+ metadata.gz: b0107e8ffc49ba8bd8ad43183da66ecb29d89478440fd0cb70b9eb2e1305c427
4
+ data.tar.gz: 40fa32805af4c9d08d2b2b4f0ebcde942bd6e1135a98b491bba6f148cea1c1ee
5
5
  SHA512:
6
- metadata.gz: 7c1cb37c152205f1b1d4e7ff0d84908323156564bc0bdb20f47d6cd346e02ad1f60dfd3b3182f153a8b6f560fd73a8f64d5dcba856becc9ee8a909f1d052116c
7
- data.tar.gz: c4c72d86aad43c6ff3ef0557820d8f8481c27a7e856fe71eb5557aa24220b9fbc30edc8317193d9c59024793371008800185ba1d7c3a971a429820cf0131fa20
6
+ metadata.gz: 5e9e9633794c23f7306688fd979167def21e3f2efd5ab4ad3de73ba18f64ee87c3fe45accf0d19c4d3afb7cac8a54e198304e2b023b39bc3db40f1d65ffe26b9
7
+ data.tar.gz: af0504712cfbef8764296617f523eea2d1f97171857c58ea4b85d8e3da70a2e855f3baed3cffebff6af9f7e379711cba2d69d6c9fe2c63d7b68a2b31acddba81
@@ -1,5 +1,20 @@
1
1
  # concourse-gem changelog
2
2
 
3
+ ## 0.22.0 / 2019-01-18
4
+
5
+ ### Breaking changes
6
+
7
+ * The name of the generated, final pipeline file is now `<pipeline_erb_filename>.generated`.
8
+
9
+
10
+ ### Features
11
+
12
+ * Introduce rake task `concourse:prune-stalled-workers`
13
+ * `Concourse.new` now takes an optional `:fly_target` named param to avoid passing this to each task. [#2] (Thanks, @ebmeierj!)
14
+ * `Concourse.new` now takes an optional `:pipeline_erb_filename` named param to set the name of the pipeline file used. [#1] (Thanks, @ebmeierj!)
15
+ * `Concourse.new` now takes an optional `:secrets_filename` named param to set the name of the private variable file used. [#1] (Thanks, @ebmeierj!)
16
+
17
+
3
18
  ## 0.21.0 / 2018-12-26
4
19
 
5
20
  * Introduce ruby 2.6 final (and remove 2.6-rc)
data/README.md CHANGED
@@ -12,7 +12,7 @@ In your Rakefile,
12
12
  ``` ruby
13
13
  require 'concourse'
14
14
 
15
- Concourse.new("myproject").create_tasks!
15
+ Concourse.new("myproject", fly_target: "myci").create_tasks!
16
16
  ```
17
17
 
18
18
  This will create a set of rake tasks for you.
@@ -21,21 +21,54 @@ This will create a set of rake tasks for you.
21
21
  rake concourse:init
22
22
  ```
23
23
 
24
- The `concourse:init` task will create a subdirectory named `concourse`, and create a Concourse pipeline file named `myproject.yml`, which will be interpreted as an ERB template. It will also ensure that files with sensitive data (`concourse/private.yml` and `concourse/myproject.final.yml`) are in `.gitignore`.
24
+ The `concourse:init` task will create a subdirectory named `concourse`, and create a Concourse pipeline file named `<myproject>.yml`, which will be interpreted as an ERB template. It will also ensure that files with sensitive data (`concourse/private.yml` and `concourse/myproject.yml.generated`) are in `.gitignore`.
25
25
 
26
26
 
27
27
  ### Concourse subdirectory name
28
28
 
29
- You can choose a directory name other than `concourse`:
29
+ You can choose a directory name other than the default `concourse`:
30
30
 
31
31
  ``` ruby
32
32
  Concourse.new("myproject", directory: "ci").create_tasks!
33
33
  ```
34
34
 
35
35
 
36
+ ### Concourse `fly` target name
37
+
38
+ If the initializer is given no additional parameters, your fly target is assumed to be named "default":
39
+
40
+ ``` ruby
41
+ Concourse.new("myproject").create_tasks! # `fly -t default <command>`
42
+ ```
43
+
44
+ But this is likely an inappropriate default, and so you can specify your target name:
45
+
46
+ ``` ruby
47
+ Concourse.new("myproject", fly_target: "myci").create_tasks! # `fly -t myci <command>`
48
+ ```
49
+
50
+
51
+ ### Pipeline file
52
+
53
+ By default the pipeline file will be named `<myproject>.yml`, but can be set to something else:
54
+
55
+ ``` ruby
56
+ Concourse.new("myproject", pipeline_erb_filename: "pipeline.yml").create_tasks!
57
+ ```
58
+
59
+ Note that the generated, final pipeline file is always named `<pipeline_erb_filename>.generated`.
60
+
61
+
62
+
36
63
  ### Keeping credentials private
37
64
 
38
- If the file `concourse/private.yml` exists, it will be passed to the `fly` commandline with the `-l` option to fill in template values.
65
+ You can use a separate file to keep your pipeline variables secure. By default, `concourse/private.yml` will be used. You can specify a different filename:
66
+
67
+ ``` ruby
68
+ Concourse.new("myproject", secrets_filename: "secrets.yml").create_tasks!
69
+ ```
70
+
71
+ If the secrets file exists, it will be passed to the `fly` commandline with the `-l` option to fill in template values.
39
72
 
40
73
  For example, I might have a concourse config that looks like this:
41
74
 
@@ -90,54 +123,50 @@ jobs:
90
123
  Note that the `windows` rubies are not Docker images, since Concourse's Houdini backend doesn't use Docker. Instead, these are implicitly referring to the supported ruby versions installed by the BOSH release at https://github.com/flavorjones/windows-ruby-dev-tools-release
91
124
 
92
125
 
93
- ### `fly_target`
94
-
95
- Any rake task that needs to interact with your Concourse ATC requires a `fly_target` argument. The value should be a fly target `name`, and it's assumed that you're already logged in to that target.
96
-
97
-
98
126
  ### Managing your Concourse pipeline
99
127
 
100
128
  Tasks to manage a local pipeline file, generated from an ERB template:
101
129
 
102
130
  ```
103
- rake concourse:clean # remove generate pipeline file
104
- rake concourse:generate # generate and validate the pipeline file for myproject
131
+ rake concourse:clean # remove generate pipeline file
132
+ rake concourse:generate # generate and validate the pipeline file for myproject
105
133
  ```
106
134
 
107
135
  A task to update your pipeline configuration:
108
136
 
109
137
  ```
110
- rake concourse:set[fly_target] # upload the pipeline file for myproject
138
+ rake concourse:set # upload the pipeline file for myproject
111
139
  ```
112
140
 
113
141
  Tasks to publicly expose or hide your pipeline:
114
142
 
115
143
  ```
116
- rake concourse:expose[fly_target] # expose the myproject pipeline
117
- rake concourse:hide[fly_target] # hide the myproject pipeline
144
+ rake concourse:expose # expose the myproject pipeline
145
+ rake concourse:hide # hide the myproject pipeline
118
146
  ```
119
147
 
120
148
  Tasks to pause and unpause your pipeline:
121
149
 
122
150
  ```
123
- rake concourse:pause[fly_target] # pause the myproject pipeline
124
- rake concourse:unpause[fly_target] # unpause the myproject pipeline
151
+ rake concourse:pause # pause the myproject pipeline
152
+ rake concourse:unpause # unpause the myproject pipeline
125
153
  ```
126
154
 
127
155
  And, should you ever need to [nuke the site from orbit][ripley], a task to destroy your pipeline:
128
156
 
129
157
  ```
130
- rake concourse:destroy[fly_target] # destroy the myproject pipeline
158
+ rake concourse:destroy # destroy the myproject pipeline
131
159
  ```
132
160
 
133
161
 
134
162
  [ripley]: https://www.youtube.com/watch?v=aCbfMkh940Q
135
163
 
164
+
136
165
  ### Running tasks with `fly execute`
137
166
 
138
167
  ```
139
- rake concourse:tasks # list all the available tasks from the nokogiri pipeline
140
- rake concourse:task[fly_target,job_task,fly_execute_args] # fly execute the specified task
168
+ rake concourse:tasks # list all the available tasks from the nokogiri pipeline
169
+ rake concourse:task[job_task,fly_execute_args] # fly execute the specified task
141
170
  ```
142
171
 
143
172
  where:
@@ -149,22 +178,18 @@ where:
149
178
  ### Aborting running builds
150
179
 
151
180
  ```
152
- rake concourse:abort-builds[fly_target] # abort all running builds for this pipeline
181
+ rake concourse:abort-builds # abort all running builds for this pipeline
153
182
  ```
154
183
 
155
184
 
156
- ### Generating a sweet set of markdown badges
185
+ ### Pruning stalled concourse workers
157
186
 
158
- Would you like a markdown table of your jobs' passing/failing badges? Of course you would.
187
+ Especially useful if you're deploying via BOSH, which often results in stalled workers;
159
188
 
160
189
  ```
161
- rake concourse:badges[fly_target,team_name] # display a list of jobs and badge urls
190
+ rake concourse:prune-stalled-workers # prune any stalled workers
162
191
  ```
163
192
 
164
- where:
165
-
166
- * _optional_: `team_name` is the name of the pipeline's Concourse Team. Defaults to `main`.
167
-
168
193
 
169
194
  ## Installation
170
195
 
@@ -21,6 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
23
 
24
+ spec.add_dependency "term-ansicolor"
25
+
24
26
  spec.add_development_dependency "bundler", "~> 1.14"
25
27
  spec.add_development_dependency "rake", "~> 12.0"
26
28
  spec.add_development_dependency "rspec", "~> 3.0"
@@ -1,9 +1,14 @@
1
1
  require "concourse/version"
2
2
  require "yaml"
3
3
  require "tempfile"
4
+ require 'term/ansicolor'
4
5
 
5
6
  class Concourse
6
7
  include Rake::DSL
8
+ include Term::ANSIColor
9
+
10
+ GITIGNORE_FILE = ".gitignore"
11
+ GITATTRIBUTES_FILE = ".gitattributes"
7
12
 
8
13
  # these numbers/names align with public docker image names
9
14
  RUBIES = {
@@ -15,14 +20,11 @@ class Concourse
15
20
 
16
21
  DEFAULT_DIRECTORY = "concourse"
17
22
 
18
- attr_reader :project_name, :pipeline_filename, :pipeline_erb_filename, :directory, :private_var_file
19
-
20
- def self.validate_fly_target task, task_args
21
- unless task_args[:fly_target]
22
- raise "ERROR: must specify a fly target, like `rake #{task.name}[targetname]`"
23
- end
24
- return task_args[:fly_target]
25
- end
23
+ attr_reader :project_name
24
+ attr_reader :directory
25
+ attr_reader :pipeline_filename, :pipeline_erb_filename
26
+ attr_reader :fly_target
27
+ attr_reader :secrets_filename
26
28
 
27
29
  def self.url_for fly_target
28
30
  matching_line = `fly targets`.split("\n").grep(/^#{fly_target}/).first
@@ -46,12 +48,17 @@ class Concourse
46
48
  RUBIES[:mri].select { |r| r =~ /rc/ }
47
49
  end
48
50
 
49
- def initialize project_name, args={}
51
+ def initialize project_name, options={}
50
52
  @project_name = project_name
51
- @directory = args[:directory] || DEFAULT_DIRECTORY
52
- @pipeline_filename = File.join(@directory, "#{project_name}.final.yml")
53
- @pipeline_erb_filename = File.join(@directory, "#{project_name}.yml")
54
- @private_var_file = File.join(@directory, "private.yml")
53
+
54
+ @directory = options[:directory] || DEFAULT_DIRECTORY
55
+ @fly_target = options[:fly_target] || "default"
56
+ base_pipeline_erb_filename = options[:pipeline_erb_filename] || "#{project_name}.yml"
57
+ base_secrets_filename = options[:secrets_filename] || "private.yml"
58
+
59
+ @pipeline_filename = File.join(@directory, "#{base_pipeline_erb_filename}.generated")
60
+ @pipeline_erb_filename = File.join(@directory, base_pipeline_erb_filename)
61
+ @secrets_filename = File.join(@directory, base_secrets_filename)
55
62
  end
56
63
 
57
64
  def erbify document_string, *args
@@ -61,10 +68,32 @@ class Concourse
61
68
  def rake_init
62
69
  FileUtils.mkdir_p File.join(directory, "tasks")
63
70
  FileUtils.touch pipeline_erb_filename
64
- File.open ".gitignore", "a" do |f|
65
- f.puts private_var_file
66
- f.puts pipeline_filename
71
+ ensure_in_gitignore secrets_filename
72
+ ensure_in_gitignore pipeline_filename
73
+ end
74
+
75
+ def ensure_in_gitignore file_glob
76
+ if File.exist?(GITIGNORE_FILE)
77
+ if File.read(GITIGNORE_FILE).split("\n").include?(file_glob)
78
+ note "found '#{file_glob}' already present in #{GITIGNORE_FILE}"
79
+ return
80
+ end
67
81
  end
82
+ note "adding '#{file_glob}' to #{GITIGNORE_FILE}"
83
+ File.open(GITIGNORE_FILE, "a") { |f| f.puts file_glob }
84
+ end
85
+
86
+ def sh command
87
+ running "(in #{Dir.pwd}) #{command}"
88
+ super command, verbose: false
89
+ end
90
+
91
+ def running message
92
+ print bold, red, "RUNNING: ", reset, message, "\n"
93
+ end
94
+
95
+ def note message
96
+ print bold, green, "NOTE: ", reset, message, "\n"
68
97
  end
69
98
 
70
99
  def create_tasks!
@@ -99,23 +128,21 @@ class Concourse
99
128
  end
100
129
 
101
130
  desc "upload the pipeline file for #{project_name}"
102
- task "set", [:fly_target] => ["generate"] do |t, args|
103
- fly_target = Concourse.validate_fly_target t, args
131
+ task "set" => ["generate"] do |t, args|
104
132
  options = [
105
133
  "-p '#{project_name}'",
106
134
  "-c '#{pipeline_filename}'",
107
135
  ]
108
- if File.exist? private_var_file
109
- puts "using #{private_var_file} to resolve template vars"
110
- options << "-l '#{private_var_file}'"
136
+ if File.exist? secrets_filename
137
+ note "using #{secrets_filename} to resolve template vars"
138
+ options << "-l '#{secrets_filename}'"
111
139
  end
112
140
  sh "fly -t #{fly_target} set-pipeline #{options.join(" ")}"
113
141
  end
114
142
 
115
143
  %w[expose hide pause unpause destroy].each do |command|
116
144
  desc "#{command} the #{project_name} pipeline"
117
- task "#{command}", [:fly_target] do |t, args|
118
- fly_target = Concourse.validate_fly_target t, args
145
+ task command do |t, args|
119
146
  sh "fly -t #{fly_target} #{command}-pipeline -p #{project_name}"
120
147
  end
121
148
  end
@@ -136,14 +163,12 @@ class Concourse
136
163
  tasks << "#{job["name"]}/#{task["task"]}"
137
164
  end
138
165
 
139
- puts "Available Concourse tasks for #{project_name} are:"
166
+ note "Available Concourse tasks for #{project_name} are:"
140
167
  tasks.sort.each { |task| puts " * #{task}" }
141
168
  end
142
169
 
143
170
  desc "fly execute the specified task"
144
- task "task", [:fly_target, :job_task, :fly_execute_args] => "generate" do |t, args|
145
- fly_target = Concourse.validate_fly_target t, args
146
-
171
+ task "task", [:job_task, :fly_execute_args] => "generate" do |t, args|
147
172
  job_task = args[:job_task]
148
173
  unless job_task
149
174
  raise "ERROR: must specify a task name, like `rake #{t.name}[target,taskname]`"
@@ -168,16 +193,25 @@ class Concourse
168
193
  # builds commands
169
194
  #
170
195
  desc "abort all running builds for this pipeline"
171
- task "abort-builds", [:fly_target] do |t, args|
172
- fly_target = Concourse.validate_fly_target t, args
173
-
174
- `fly -t #{fly_target} builds`.split("\n").each do |line|
196
+ task "abort-builds" do |t, args|
197
+ `fly -t #{fly_target} builds`.each_line do |line|
175
198
  pipeline_job, build_id, status = *line.split(/\s+/)[1,3]
176
199
  next unless status == "started"
177
200
 
178
201
  sh "fly -t #{fly_target} abort-build -j #{pipeline_job} -b #{build_id}"
179
202
  end
180
203
  end
204
+
205
+ #
206
+ # worker commands
207
+ #
208
+ desc "prune any stalled workers"
209
+ task "prune-stalled-workers" do |t, args|
210
+ `fly -t #{fly_target} workers | fgrep stalled`.each_line do |line|
211
+ worker_id = line.split.first
212
+ system("fly -t #{fly_target} prune-worker -w #{worker_id}")
213
+ end
214
+ end
181
215
  end
182
216
  end
183
217
 
@@ -2,5 +2,5 @@ require "rake"
2
2
  require "erb"
3
3
 
4
4
  class Concourse
5
- VERSION = "0.21.0"
5
+ VERSION = "0.22.0"
6
6
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concourse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Dalessio
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-27 00:00:00.000000000 Z
11
+ date: 2019-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: term-ansicolor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -90,8 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
104
  - !ruby/object:Gem::Version
91
105
  version: '0'
92
106
  requirements: []
93
- rubyforge_project:
94
- rubygems_version: 2.7.8
107
+ rubygems_version: 3.0.1
95
108
  signing_key:
96
109
  specification_version: 4
97
110
  summary: Rake tasks for Concourse pipelines.