concourse 0.22.0 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/CHANGELOG.md +7 -0
- data/README.md +180 -89
- data/Rakefile +11 -0
- data/lib/concourse.rb +75 -93
- data/lib/concourse/pipeline.rb +12 -0
- data/lib/concourse/util.rb +64 -0
- data/lib/concourse/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50517da26e0d7eb88bb231814b9a664ee17bc5e08c278eb2724e472797832867
|
4
|
+
data.tar.gz: 7c0ce4a2fc2844bf187ba242d47c62c5b1ab684ef85d6194520c90807b10b8c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c19043e491bd57cfc3f57babcc494ac0eee2e35e501f3a45e076af6655c8b94940f89ece2d7b067f762039a0723031e3329c2b635525927bf0a40202158727be
|
7
|
+
data.tar.gz: fb3024061b013b796d65e68757cb9aade22126868d7c3c29be367c0ac39142da96c3024575c7753f5c3909f67d53104cb25c5eb1fd85a8a283c99b8ddc41c7f2
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,72 +1,120 @@
|
|
1
|
-
#
|
1
|
+
# concourse (the rubygem)
|
2
2
|
|
3
|
-
The `
|
3
|
+
The `concourse` gem provides rake tasks to help you manage Concourse pipelines, jobs, and workers, and to assist in running tasks with `fly execute`.
|
4
4
|
|
5
5
|
If you're not familiar with Concourse CI, you can read up on it at https://concourse.ci
|
6
6
|
|
7
7
|
|
8
|
-
##
|
8
|
+
## Contents
|
9
9
|
|
10
|
-
|
10
|
+
<!-- to update this TOC run `rake readme_toc` -->
|
11
11
|
|
12
|
-
|
13
|
-
require 'concourse'
|
12
|
+
<!-- toc -->
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
- [Basic Usage](#basic-usage)
|
15
|
+
* [Install](#install)
|
16
|
+
* [Add to your `Rakefile`](#add-to-your-rakefile)
|
17
|
+
* [Set up your Concourse pipeline](#set-up-your-concourse-pipeline)
|
18
|
+
- [Concourse pipeline configuration](#concourse-pipeline-configuration)
|
19
|
+
* [ERB Templating and `RUBIES`](#erb-templating-and-rubies)
|
20
|
+
* [Secrets](#secrets)
|
21
|
+
* [Multiple pipelines](#multiple-pipelines)
|
22
|
+
- [Configuration](#configuration)
|
23
|
+
* [`directory`: Concourse subdirectory name](#directory-concourse-subdirectory-name)
|
24
|
+
* [`fly_target`: Concourse `fly` target name](#fly_target-concourse-fly-target-name)
|
25
|
+
* [`pipeline_erb_filename`: Pipeline filename](#pipeline_erb_filename-pipeline-filename)
|
26
|
+
* [`secrets_filename`: Secrets filename](#secrets_filename-secrets-filename)
|
27
|
+
- [Rake Tasks](#rake-tasks)
|
28
|
+
* [Manage your Concourse pipeline](#manage-your-concourse-pipeline)
|
29
|
+
* [List pipeline tasks](#list-pipeline-tasks)
|
30
|
+
* [Run a Concourse task with `fly execute`](#run-a-concourse-task-with-fly-execute)
|
31
|
+
* [Abort running builds](#abort-running-builds)
|
32
|
+
* [Prune stalled concourse workers](#prune-stalled-concourse-workers)
|
33
|
+
- [Contributing](#contributing)
|
34
|
+
- [License](#license)
|
17
35
|
|
18
|
-
|
36
|
+
<!-- tocstop -->
|
19
37
|
|
20
|
-
|
21
|
-
rake concourse:init
|
22
|
-
```
|
38
|
+
## Basic Usage
|
23
39
|
|
24
|
-
|
40
|
+
### Install
|
25
41
|
|
42
|
+
Add this line to your application's Gemfile:
|
26
43
|
|
27
|
-
|
44
|
+
```ruby
|
45
|
+
gem 'concourse'
|
46
|
+
```
|
28
47
|
|
29
|
-
|
48
|
+
and then run `bundle`.
|
30
49
|
|
31
|
-
|
32
|
-
Concourse.new("myproject", directory: "ci").create_tasks!
|
33
|
-
```
|
50
|
+
You can also install it via `gem install concourse`.
|
34
51
|
|
35
52
|
|
36
|
-
###
|
53
|
+
### Add to your `Rakefile`
|
37
54
|
|
38
|
-
|
55
|
+
The primary functionality of the Concourse gem is to provide rake tasks. So, in your Rakefile:
|
39
56
|
|
40
57
|
``` ruby
|
41
|
-
|
58
|
+
require 'concourse'
|
59
|
+
|
60
|
+
Concourse.new("myproject").create_tasks!
|
42
61
|
```
|
43
62
|
|
44
|
-
|
63
|
+
### Set up your Concourse pipeline
|
45
64
|
|
46
|
-
```
|
47
|
-
|
65
|
+
``` sh
|
66
|
+
rake concourse:init
|
48
67
|
```
|
49
68
|
|
69
|
+
The `concourse:init` task will do a few different things for you:
|
50
70
|
|
51
|
-
|
71
|
+
1. create a subdirectory named `concourse` (or whatever you've configured with the `:directory` parameter)
|
72
|
+
2. create an empty Concourse pipeline file in that subdirectory named `<myproject>.yml` (or whatever you've configured with the `:pipeline_erb_filename` parameter)
|
73
|
+
3. ensure git will ignore your secrets file named `private.yml` (or whatever you've configured with the `:secrets_filename` parameter)
|
74
|
+
4. ensure git will ignore the generated pipeline file (named after your ERB pipeline file as `<pipeline_erb_filename>.generated`)
|
52
75
|
|
53
|
-
|
76
|
+
|
77
|
+
## Concourse pipeline configuration
|
78
|
+
|
79
|
+
### ERB Templating and `RUBIES`
|
80
|
+
|
81
|
+
Your Concourse pipeline configuration file, `<myproject>.yml` (or whatever you've configured with the `:pipeline_erb_filename` parameter), will be treated like an ERB template.
|
82
|
+
|
83
|
+
(If you're unfamiliar with ERB and how you can mix Ruby into the document, you can [read about it here](https://www.stuartellis.name/articles/erb/).)
|
84
|
+
|
85
|
+
The ruby variable `RUBIES` is defined in the ERB binding during pipeline file generation. This variable looks like:
|
54
86
|
|
55
87
|
``` ruby
|
56
|
-
|
88
|
+
# these numbers/names align with public docker image names
|
89
|
+
RUBIES = {
|
90
|
+
mri: %w[2.1 2.2 2.3 2.4], # docker repository: "ruby"
|
91
|
+
jruby: %w[1.7 9.1], # docker repository: "jruby"
|
92
|
+
rbx: %w[latest], # docker repository: "rubinius/docker"
|
93
|
+
windows: %w[2.3 2.4] # windows-ruby-dev-tools-release
|
94
|
+
}
|
57
95
|
```
|
58
96
|
|
59
|
-
|
97
|
+
and allows you to write a pipeline like this to get coverage on all the supported rubies:
|
60
98
|
|
99
|
+
``` yaml
|
100
|
+
# myproject.yml
|
101
|
+
jobs:
|
102
|
+
<% for ruby_version in RUBIES[:mri] %>
|
103
|
+
- name: "ruby-<%= ruby_version %>"
|
104
|
+
plan:
|
105
|
+
- get: git-master
|
106
|
+
trigger: true
|
107
|
+
- task: rake-test
|
108
|
+
...
|
109
|
+
<% end %>
|
110
|
+
```
|
61
111
|
|
112
|
+
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
|
62
113
|
|
63
|
-
### Keeping credentials private
|
64
114
|
|
65
|
-
|
115
|
+
### Secrets
|
66
116
|
|
67
|
-
|
68
|
-
Concourse.new("myproject", secrets_filename: "secrets.yml").create_tasks!
|
69
|
-
```
|
117
|
+
You can use a separate file to keep your pipeline variables secret. By default, `concourse/private.yml` will be used. This filename can also be configured (see below)
|
70
118
|
|
71
119
|
If the secrets file exists, it will be passed to the `fly` commandline with the `-l` option to fill in template values.
|
72
120
|
|
@@ -91,128 +139,171 @@ github-repo-status-access-token: "your-token-here"
|
|
91
139
|
and the final generate template will substitute your credentials into the appropriate place.
|
92
140
|
|
93
141
|
|
94
|
-
###
|
142
|
+
### Multiple pipelines
|
95
143
|
|
96
|
-
|
144
|
+
Setting up multiple pipelines might be useful for you, for example one pipeline for running tests against `master` and another for pull requests; or a pipeline for tests and a pipeline for deployments.
|
145
|
+
|
146
|
+
If you'd like to set up multiple pipelines, invoke Concourse in your Rakefile like this:
|
97
147
|
|
98
148
|
``` ruby
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
149
|
+
require 'concourse'
|
150
|
+
|
151
|
+
Concourse.new("myproject") do |c|
|
152
|
+
c.add_pipeline "master", "myproject.yml"
|
153
|
+
c.add_pipeline "pull-requests", "pr.yml"
|
154
|
+
c.add_pipeline "deploy", "big-red-button.yml"
|
155
|
+
end
|
106
156
|
```
|
107
157
|
|
108
|
-
|
158
|
+
Note that when you use the block form:
|
109
159
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
160
|
+
* it's not necessary to explicitly call `#create_tasks!`
|
161
|
+
* only the pipelines declared via `#add_pipeline` will be managed
|
162
|
+
|
163
|
+
|
164
|
+
## Configuration
|
165
|
+
|
166
|
+
### `directory`: Concourse subdirectory name
|
167
|
+
|
168
|
+
You can choose a directory name other than the default `concourse`:
|
169
|
+
|
170
|
+
``` ruby
|
171
|
+
Concourse.new("myproject", directory: "ci").create_tasks!
|
121
172
|
```
|
122
173
|
|
123
|
-
|
174
|
+
|
175
|
+
### `fly_target`: Concourse `fly` target name
|
176
|
+
|
177
|
+
If the initializer is given no additional parameters, your fly target is assumed to be named "default". But this is likely an inappropriate default, and so you can specify your target name:
|
178
|
+
|
179
|
+
``` ruby
|
180
|
+
Concourse.new("myproject", fly_target: "myci").create_tasks! # `fly -t myci <command>`
|
181
|
+
```
|
182
|
+
|
183
|
+
|
184
|
+
### `pipeline_erb_filename`: Pipeline filename
|
185
|
+
|
186
|
+
By default the pipeline file will be named `<myproject>.yml`, but can be set to something else:
|
187
|
+
|
188
|
+
``` ruby
|
189
|
+
Concourse.new("myproject", pipeline_erb_filename: "pipeline.yml").create_tasks!
|
190
|
+
```
|
191
|
+
|
192
|
+
Note that the generated, final pipeline file is always named `<pipeline_erb_filename>.generated`.
|
193
|
+
|
124
194
|
|
125
195
|
|
126
|
-
###
|
196
|
+
### `secrets_filename`: Secrets filename
|
197
|
+
|
198
|
+
You can use a separate file to keep your pipeline variables secret. By default, `concourse/private.yml` will be used. You can specify a different filename:
|
199
|
+
|
200
|
+
``` ruby
|
201
|
+
Concourse.new("myproject", secrets_filename: "secrets.yml").create_tasks!
|
202
|
+
```
|
203
|
+
|
204
|
+
|
205
|
+
## Rake Tasks
|
206
|
+
|
207
|
+
|
208
|
+
### Manage your Concourse pipeline
|
127
209
|
|
128
210
|
Tasks to manage a local pipeline file, generated from an ERB template:
|
129
211
|
|
130
212
|
```
|
131
|
-
rake concourse:clean
|
132
|
-
rake concourse:generate
|
213
|
+
rake concourse:clean # remove generated pipeline files
|
214
|
+
rake concourse:generate # generate and validate the pipeline files for myproject
|
133
215
|
```
|
134
216
|
|
135
217
|
A task to update your pipeline configuration:
|
136
218
|
|
137
219
|
```
|
138
|
-
rake concourse:set
|
220
|
+
rake concourse:set # upload the pipeline files for myproject
|
139
221
|
```
|
140
222
|
|
141
223
|
Tasks to publicly expose or hide your pipeline:
|
142
224
|
|
143
225
|
```
|
144
|
-
rake concourse:expose
|
145
|
-
rake concourse:hide
|
226
|
+
rake concourse:expose # expose the myproject pipelines
|
227
|
+
rake concourse:hide # hide the myproject pipelines
|
146
228
|
```
|
147
229
|
|
148
230
|
Tasks to pause and unpause your pipeline:
|
149
231
|
|
150
232
|
```
|
151
|
-
rake concourse:pause
|
152
|
-
rake concourse:unpause
|
233
|
+
rake concourse:pause # pause the myproject pipelines
|
234
|
+
rake concourse:unpause # unpause the myproject pipelines
|
153
235
|
```
|
154
236
|
|
155
237
|
And, should you ever need to [nuke the site from orbit][ripley], a task to destroy your pipeline:
|
156
238
|
|
157
239
|
```
|
158
|
-
rake concourse:destroy
|
240
|
+
rake concourse:destroy # destroy the myproject pipelines
|
159
241
|
```
|
160
242
|
|
161
|
-
|
162
243
|
[ripley]: https://www.youtube.com/watch?v=aCbfMkh940Q
|
163
244
|
|
164
245
|
|
165
|
-
###
|
246
|
+
### List pipeline tasks
|
247
|
+
|
248
|
+
You can see a list of all the tasks defined in your pipelines:
|
166
249
|
|
167
250
|
```
|
168
|
-
rake concourse:tasks
|
169
|
-
rake concourse:task[job_task,fly_execute_args] # fly execute the specified task
|
251
|
+
rake concourse:tasks # list all the available tasks from the myproject pipelines
|
170
252
|
```
|
171
253
|
|
172
|
-
|
173
|
-
|
174
|
-
* _required_: `job_task` is formatted as `job-name/task-name`, for example, `ruby-2.4/rake-test`. Run the `concourse:tasks` rake task to see all available names.
|
175
|
-
* _optional_: `fly_execute_args` will default to map the project directory to a resource with the project name, e.g. `--input=myproject=.`, so your pipeline must name the input resource appropriately in order to use the default.
|
176
|
-
|
177
|
-
|
178
|
-
### Aborting running builds
|
254
|
+
You'll see output suitable for the `concourse:task` rake task, formatted as `job-name/task-name`, looking something like:
|
179
255
|
|
180
256
|
```
|
181
|
-
|
257
|
+
RUNNING: (in /home/flavorjones/code/oss/nokogiri) fly validate-pipeline -c concourse/nokogiri.yml.generated
|
258
|
+
looks good
|
259
|
+
NOTE: Available Concourse tasks for nokogiri are:
|
260
|
+
* jruby-9.1/rake-test
|
261
|
+
* jruby-9.2-pr/rake-test
|
262
|
+
* jruby-9.2/rake-test
|
263
|
+
* ruby-2.5-system/rake-test
|
264
|
+
* ruby-2.5-vendored/rake-test
|
265
|
+
* ruby-2.6-system-pr/rake-test
|
266
|
+
* ruby-2.6-system/rake-test
|
267
|
+
* ruby-2.6-vendored-pr/rake-test
|
268
|
+
* ruby-2.6-vendored/rake-test
|
182
269
|
```
|
183
270
|
|
184
271
|
|
185
|
-
###
|
272
|
+
### Run a Concourse task with `fly execute`
|
186
273
|
|
187
|
-
|
274
|
+
You can `fly execute` a task defined in your pipelines:
|
188
275
|
|
189
276
|
```
|
190
|
-
rake concourse:
|
277
|
+
rake concourse:task[job_task,fly_execute_args] # fly execute the specified task
|
191
278
|
```
|
192
279
|
|
280
|
+
where:
|
193
281
|
|
194
|
-
|
282
|
+
* _required_: `job_task` is formatted as `job-name/task-name`, for example, `ruby-2.4/rake-test`. (See `concourse:tasks` for a list of all available task names.)
|
283
|
+
* _optional_: `fly_execute_args` will default to map the project directory to a resource with the project name, e.g. `--input=myproject=.`, so your pipeline must name the input resource appropriately in order to use the default.
|
195
284
|
|
196
|
-
Add this line to your application's Gemfile:
|
197
285
|
|
198
|
-
|
199
|
-
|
286
|
+
### Abort running builds
|
287
|
+
|
288
|
+
```
|
289
|
+
rake concourse:abort-builds # abort all running builds for this pipeline
|
200
290
|
```
|
201
291
|
|
202
|
-
And then execute:
|
203
292
|
|
204
|
-
|
293
|
+
### Prune stalled concourse workers
|
205
294
|
|
206
|
-
|
295
|
+
Especially useful if you're deploying via BOSH, which often results in stalled workers;
|
207
296
|
|
208
|
-
|
297
|
+
```
|
298
|
+
rake concourse:prune-stalled-workers # prune any stalled workers
|
299
|
+
```
|
209
300
|
|
210
301
|
|
211
302
|
## Contributing
|
212
303
|
|
213
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/flavorjones/concourse-gem. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
304
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/flavorjones/concourse-gem. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. See [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md).
|
214
305
|
|
215
306
|
|
216
307
|
## License
|
217
308
|
|
218
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
309
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). See [`LICENSE.txt`](LICENSE.txt).
|
data/Rakefile
CHANGED
@@ -4,3 +4,14 @@ require "rspec/core/rake_task"
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
6
|
task :default => :spec
|
7
|
+
|
8
|
+
desc "update README table of contents"
|
9
|
+
task :readme_toc => :install_markdown_utils do
|
10
|
+
system "node_modules/.bin/markdown-toc -i --maxdepth 3 README.md"
|
11
|
+
end
|
12
|
+
|
13
|
+
task :install_markdown_utils do
|
14
|
+
if ! File.exist?("node_modules/.bin/markdown-toc")
|
15
|
+
system "npm install markdown-toc"
|
16
|
+
end
|
17
|
+
end
|
data/lib/concourse.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
require "concourse/version"
|
2
|
+
require "concourse/util"
|
3
|
+
require "concourse/pipeline"
|
2
4
|
require "yaml"
|
3
5
|
require "tempfile"
|
4
|
-
require 'term/ansicolor'
|
5
6
|
|
6
7
|
class Concourse
|
7
8
|
include Rake::DSL
|
8
|
-
include
|
9
|
-
|
10
|
-
GITIGNORE_FILE = ".gitignore"
|
11
|
-
GITATTRIBUTES_FILE = ".gitattributes"
|
9
|
+
include Concourse::Util
|
12
10
|
|
13
11
|
# these numbers/names align with public docker image names
|
14
12
|
RUBIES = {
|
@@ -22,7 +20,7 @@ class Concourse
|
|
22
20
|
|
23
21
|
attr_reader :project_name
|
24
22
|
attr_reader :directory
|
25
|
-
attr_reader :
|
23
|
+
attr_reader :pipelines
|
26
24
|
attr_reader :fly_target
|
27
25
|
attr_reader :secrets_filename
|
28
26
|
|
@@ -48,52 +46,39 @@ class Concourse
|
|
48
46
|
RUBIES[:mri].select { |r| r =~ /rc/ }
|
49
47
|
end
|
50
48
|
|
51
|
-
def initialize project_name, options={}
|
49
|
+
def initialize project_name, options={}, &block
|
52
50
|
@project_name = project_name
|
53
51
|
|
54
52
|
@directory = options[:directory] || DEFAULT_DIRECTORY
|
55
53
|
@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
54
|
|
59
|
-
|
60
|
-
@pipeline_erb_filename = File.join(@directory, base_pipeline_erb_filename)
|
55
|
+
base_secrets_filename = options[:secrets_filename] || "private.yml"
|
61
56
|
@secrets_filename = File.join(@directory, base_secrets_filename)
|
62
|
-
end
|
63
|
-
|
64
|
-
def erbify document_string, *args
|
65
|
-
ERB.new(document_string, nil, "%-").result(binding)
|
66
|
-
end
|
67
|
-
|
68
|
-
def rake_init
|
69
|
-
FileUtils.mkdir_p File.join(directory, "tasks")
|
70
|
-
FileUtils.touch pipeline_erb_filename
|
71
|
-
ensure_in_gitignore secrets_filename
|
72
|
-
ensure_in_gitignore pipeline_filename
|
73
|
-
end
|
74
57
|
|
75
|
-
|
76
|
-
if
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
58
|
+
@pipelines = []
|
59
|
+
if block
|
60
|
+
block.call(self)
|
61
|
+
create_tasks!
|
62
|
+
else
|
63
|
+
add_pipeline(@project_name, (options[:pipeline_erb_filename] || "#{project_name}.yml"))
|
81
64
|
end
|
82
|
-
note "adding '#{file_glob}' to #{GITIGNORE_FILE}"
|
83
|
-
File.open(GITIGNORE_FILE, "a") { |f| f.puts file_glob }
|
84
65
|
end
|
85
66
|
|
86
|
-
def
|
87
|
-
|
88
|
-
super command, verbose: false
|
67
|
+
def add_pipeline name, erb_filename
|
68
|
+
@pipelines << Concourse::Pipeline.new(name, @directory, erb_filename)
|
89
69
|
end
|
90
70
|
|
91
|
-
def
|
92
|
-
|
71
|
+
def pipeline_subcommands command
|
72
|
+
pipelines.collect { |p| "#{command}:#{p.name}" }
|
93
73
|
end
|
94
74
|
|
95
|
-
def
|
96
|
-
|
75
|
+
def rake_init
|
76
|
+
FileUtils.mkdir_p File.join(directory, "tasks")
|
77
|
+
pipelines.each do |pipeline|
|
78
|
+
FileUtils.touch pipeline.erb_filename
|
79
|
+
ensure_in_gitignore pipeline.filename
|
80
|
+
end
|
81
|
+
ensure_in_gitignore secrets_filename
|
97
82
|
end
|
98
83
|
|
99
84
|
def create_tasks!
|
@@ -101,11 +86,13 @@ class Concourse
|
|
101
86
|
mkdir_p directory
|
102
87
|
end
|
103
88
|
|
104
|
-
|
105
|
-
|
106
|
-
end
|
89
|
+
pipelines.each do |pipeline|
|
90
|
+
CLOBBER.include pipeline.filename if defined?(CLOBBER)
|
107
91
|
|
108
|
-
|
92
|
+
unless File.exist? pipeline.erb_filename
|
93
|
+
warn "WARNING: concourse template #{pipeline.erb_filename.inspect} does not exist, run `rake concourse:init`"
|
94
|
+
end
|
95
|
+
end
|
109
96
|
|
110
97
|
namespace :concourse do
|
111
98
|
#
|
@@ -119,48 +106,67 @@ class Concourse
|
|
119
106
|
#
|
120
107
|
# pipeline commands
|
121
108
|
#
|
122
|
-
desc "generate and validate
|
123
|
-
task "generate"
|
124
|
-
|
125
|
-
|
109
|
+
desc "generate and validate all pipeline files"
|
110
|
+
task "generate" => pipeline_subcommands("generate")
|
111
|
+
|
112
|
+
pipelines.each do |pipeline|
|
113
|
+
desc "generate and validate the #{pipeline.name} pipeline file"
|
114
|
+
task "generate:#{pipeline.name}" do
|
115
|
+
File.open pipeline.filename, "w" do |f|
|
116
|
+
f.write erbify(File.read(pipeline.erb_filename))
|
117
|
+
end
|
118
|
+
sh "fly validate-pipeline -c #{pipeline.filename}"
|
126
119
|
end
|
127
|
-
sh "fly validate-pipeline -c #{pipeline_filename}"
|
128
120
|
end
|
129
121
|
|
130
|
-
desc "upload
|
131
|
-
task "set" =>
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
122
|
+
desc "upload all pipeline files"
|
123
|
+
task "set" => pipeline_subcommands("set")
|
124
|
+
|
125
|
+
pipelines.each do |pipeline|
|
126
|
+
desc "upload the #{pipeline.name} pipeline file"
|
127
|
+
task "set:#{pipeline.name}" => "generate:#{pipeline.name}" do
|
128
|
+
options = [
|
129
|
+
"-p '#{pipeline.name}'",
|
130
|
+
"-c '#{pipeline.filename}'",
|
131
|
+
]
|
132
|
+
if File.exist? secrets_filename
|
133
|
+
note "using #{secrets_filename} to resolve template vars in #{pipeline.filename}"
|
134
|
+
options << "-l '#{secrets_filename}'"
|
135
|
+
end
|
136
|
+
sh "fly -t #{fly_target} set-pipeline #{options.join(" ")}"
|
139
137
|
end
|
140
|
-
sh "fly -t #{fly_target} set-pipeline #{options.join(" ")}"
|
141
138
|
end
|
142
139
|
|
143
140
|
%w[expose hide pause unpause destroy].each do |command|
|
144
|
-
desc "#{command}
|
145
|
-
task command
|
146
|
-
|
141
|
+
desc "#{command} all pipelines"
|
142
|
+
task command => pipeline_subcommands(command)
|
143
|
+
|
144
|
+
pipelines.each do |pipeline|
|
145
|
+
desc "#{command} the #{pipeline.name} pipeline"
|
146
|
+
task "#{command}:#{pipeline.name}" do
|
147
|
+
sh "fly -t #{fly_target} #{command}-pipeline -p #{pipeline.name}"
|
148
|
+
end
|
147
149
|
end
|
148
150
|
end
|
149
151
|
|
150
|
-
desc "remove
|
151
|
-
task "clean" do
|
152
|
-
|
152
|
+
desc "remove generated pipeline files"
|
153
|
+
task "clean" do
|
154
|
+
pipelines.each do |pipeline|
|
155
|
+
rm_f pipeline.filename
|
156
|
+
end
|
153
157
|
end
|
154
158
|
|
155
159
|
#
|
156
160
|
# task commands
|
157
161
|
#
|
158
|
-
desc "list all the available tasks from the #{project_name}
|
162
|
+
desc "list all the available tasks from the #{project_name} pipelines"
|
159
163
|
task "tasks" => "generate" do
|
160
164
|
tasks = []
|
161
165
|
|
162
|
-
|
163
|
-
|
166
|
+
pipelines.each do |pipeline|
|
167
|
+
each_task(pipeline) do |job, task|
|
168
|
+
tasks << "#{job["name"]}/#{task["task"]}"
|
169
|
+
end
|
164
170
|
end
|
165
171
|
|
166
172
|
note "Available Concourse tasks for #{project_name} are:"
|
@@ -174,7 +180,7 @@ class Concourse
|
|
174
180
|
raise "ERROR: must specify a task name, like `rake #{t.name}[target,taskname]`"
|
175
181
|
end
|
176
182
|
|
177
|
-
concourse_task = find_task
|
183
|
+
concourse_task = find_task(job_task)
|
178
184
|
raise "ERROR: could not find task `#{job_task}`" unless concourse_task
|
179
185
|
|
180
186
|
fly_execute_args = args[:fly_execute_args] || Concourse.default_execute_args(concourse_task)
|
@@ -192,7 +198,7 @@ class Concourse
|
|
192
198
|
#
|
193
199
|
# builds commands
|
194
200
|
#
|
195
|
-
desc "abort all running builds for this
|
201
|
+
desc "abort all running builds for this concourse team"
|
196
202
|
task "abort-builds" do |t, args|
|
197
203
|
`fly -t #{fly_target} builds`.each_line do |line|
|
198
204
|
pipeline_job, build_id, status = *line.split(/\s+/)[1,3]
|
@@ -206,7 +212,7 @@ class Concourse
|
|
206
212
|
# worker commands
|
207
213
|
#
|
208
214
|
desc "prune any stalled workers"
|
209
|
-
task "prune-stalled-workers" do
|
215
|
+
task "prune-stalled-workers" do
|
210
216
|
`fly -t #{fly_target} workers | fgrep stalled`.each_line do |line|
|
211
217
|
worker_id = line.split.first
|
212
218
|
system("fly -t #{fly_target} prune-worker -w #{worker_id}")
|
@@ -214,28 +220,4 @@ class Concourse
|
|
214
220
|
end
|
215
221
|
end
|
216
222
|
end
|
217
|
-
|
218
|
-
def each_job
|
219
|
-
pipeline = YAML.load_file(pipeline_filename)
|
220
|
-
|
221
|
-
pipeline["jobs"].each do |job|
|
222
|
-
yield job
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def each_task
|
227
|
-
each_job do |job|
|
228
|
-
job["plan"].each do |task|
|
229
|
-
yield job, task if task["task"]
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
def find_task job_task
|
235
|
-
job_name, task_name = *job_task.split("/")
|
236
|
-
each_task do |job, task|
|
237
|
-
return task if task["task"] == task_name && job["name"] == job_name
|
238
|
-
end
|
239
|
-
nil
|
240
|
-
end
|
241
223
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Concourse
|
2
|
+
class Pipeline
|
3
|
+
attr_reader :name, :directory, :erb_filename, :filename
|
4
|
+
|
5
|
+
def initialize name, directory, erb_filename
|
6
|
+
@name = name
|
7
|
+
@directory = directory
|
8
|
+
@erb_filename = File.join(@directory, erb_filename)
|
9
|
+
@filename = File.join(@directory, erb_filename + ".generated")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'term/ansicolor'
|
2
|
+
|
3
|
+
class Concourse
|
4
|
+
module Util
|
5
|
+
include Term::ANSIColor
|
6
|
+
|
7
|
+
GITIGNORE_FILE = ".gitignore"
|
8
|
+
GITATTRIBUTES_FILE = ".gitattributes"
|
9
|
+
|
10
|
+
def ensure_in_gitignore file_glob
|
11
|
+
if File.exist?(GITIGNORE_FILE)
|
12
|
+
if File.read(GITIGNORE_FILE).split("\n").include?(file_glob)
|
13
|
+
note "found '#{file_glob}' already present in #{GITIGNORE_FILE}"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
end
|
17
|
+
note "adding '#{file_glob}' to #{GITIGNORE_FILE}"
|
18
|
+
File.open(GITIGNORE_FILE, "a") { |f| f.puts file_glob }
|
19
|
+
end
|
20
|
+
|
21
|
+
def sh command
|
22
|
+
running "(in #{Dir.pwd}) #{command}"
|
23
|
+
super command, verbose: false
|
24
|
+
end
|
25
|
+
|
26
|
+
def running message
|
27
|
+
print bold, red, "RUNNING: ", reset, message, "\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
def note message
|
31
|
+
print bold, green, "NOTE: ", reset, message, "\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
def erbify document_string, *args
|
35
|
+
ERB.new(document_string, nil, "%-").result(binding)
|
36
|
+
end
|
37
|
+
|
38
|
+
def each_job pipeline
|
39
|
+
pdata = YAML.load_file(pipeline.filename)
|
40
|
+
|
41
|
+
pdata["jobs"].each do |job|
|
42
|
+
yield job
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def each_task pipeline
|
47
|
+
each_job(pipeline) do |job|
|
48
|
+
job["plan"].each do |task|
|
49
|
+
yield job, task if task["task"]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def find_task job_task
|
55
|
+
job_name, task_name = *job_task.split("/")
|
56
|
+
pipelines.each do |pipeline|
|
57
|
+
each_task(pipeline) do |job, task|
|
58
|
+
return task if task["task"] == task_name && job["name"] == job_name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/concourse/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: concourse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.23.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: 2019-01-
|
11
|
+
date: 2019-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: term-ansicolor
|
@@ -84,6 +84,8 @@ files:
|
|
84
84
|
- Rakefile
|
85
85
|
- concourse.gemspec
|
86
86
|
- lib/concourse.rb
|
87
|
+
- lib/concourse/pipeline.rb
|
88
|
+
- lib/concourse/util.rb
|
87
89
|
- lib/concourse/version.rb
|
88
90
|
homepage: https://github.com/flavorjones/concourse-gem
|
89
91
|
licenses:
|