buildkite-builder 2.0.0.beta4 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41faf27b8584ef0a615dfafb727dcac55254a4a2d95107518f550130bc470e0a
4
- data.tar.gz: 2e778aca984b052a3b4be40c015a969b9fc7d329ad0ca8a28ef9eb605d42457b
3
+ metadata.gz: 2c6eaf580c5dea018a834cf11f76e5d1d1aa13792fda9b9d513993e53f56f0a7
4
+ data.tar.gz: 5958862296476f8421ccb62fb0f23e7fef86302fdf354b00c8db9885f71691f0
5
5
  SHA512:
6
- metadata.gz: 638f4fe0bf8638a2525b6eea0cc778bb078cdc44d81b23b73dd8c29364404cb0a70bc08441b04ab5eb10f670de33cc1d55ff8e2136684679f4499326b9d77c27
7
- data.tar.gz: 4408c929ec57aaef0159a1966d7d6dd10d33bc05ce43b382f94a29c12a4eb719418360e4a18717c4324377a424e73b9840186a6b1cc894c368d5ba21e389e59f
6
+ metadata.gz: 42719a13b6515e91edd391ea18e3f3e18b8db49ec4e4b36d81d0388a701a7567c63992b72860c20f1041b378c6b7a5475c2f5c33a2e454886c3f8a8a678d0b75
7
+ data.tar.gz: f19d241a0507f434f778560bb4bf5b10dacbe1f8e743718257ac235b433cffd69f472b4d8eb30f9b3ceb28401cb241bda022743a29ffa8f72449964b3a091fa2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## 2.3.0
2
+ * Improve BKB step idempotency.
3
+
4
+ ## 2.2.0
5
+ * Add `.buildkite/lib` directory to $LOAD_PATH if it exists.
6
+
7
+ ## 2.1.0
8
+ * Fix a bug introduced in 2.0.0 where artifacts were being uploaded before extensions had a chance to do work.
9
+ * Remove `SortedSet` dependency.
10
+ * Add `annotate` pipeline command helper.
11
+ * Add `StepCollection#find` and `StepCollection#find!` for ease of finding a step by its key in extensions.
12
+ * `group` now supports the `emoji:` helper. (Eg. `group "foobar", emoji: :smile`)
13
+
14
+ ## 2.0.0
15
+ * Add support for `group`.
16
+ * `Processor`s has been renamed to `Extension`. Extensions add more capabilities (will document separately).
17
+ * `plugin` no longer takes 2 arguments (source, version). It's simply 1 arg that is both source and version, separated by a `#`. This is more akin to Buildkite's usage.
18
+ * Full refactor of pipeline code allowing for extensions to extend DSL methods.
19
+
1
20
  ## 1.5.0
2
21
  * Merge `BuildKite::Builder::Context` and `BuildKite::Pipelines::Pipeline` to `BuildKite::Builder::Pipeline` (#37)
3
22
 
data/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # Buildkite Builder [![Build status](https://badge.buildkite.com/a26bf804e9a93fb118d29824d5695a601a248ceec51591be23.svg?branch=main)](https://buildkite.com/gusto-open-source/buildkite-builder/builds?branch=main)
2
2
 
3
3
  ## Introduction
4
+
4
5
  Buildkite Builder (BKB) is a Buildkite pipeline builder written in Ruby. It allows you to build your pipeline with a Ruby DSL for dynamically generated pipeline steps.
5
6
 
6
7
  ## Gem Installation (optional)
7
8
 
8
- There are 2 components to this toolkit. The `buildkite-builder` Rubygem and the `buildkite-builder` Docker image. You technically only need the image to use Buildkite Builder, but installing the gem in your repo helps you preview your pipeline during development.
9
+ There are 2 components to this toolkit. The `buildkite-builder` RubyGem and the `buildkite-builder` Docker image. You technically only need the image to use Buildkite Builder, but installing the gem in your repo helps you preview your pipeline during development.
9
10
 
10
11
  To install the gem, add this line to your application's Gemfile:
11
12
 
@@ -16,7 +17,7 @@ gem 'buildkite-builder'
16
17
  The gem provides a command line tool that lets you perform various operations on your pipelines:
17
18
 
18
19
  ```shell
19
- $ buildkite-builder help
20
+ buildkite-builder help
20
21
  ```
21
22
 
22
23
  ## Pipeline Installation
@@ -28,28 +29,31 @@ steps:
28
29
  - label: ":toolbox:"
29
30
  plugins:
30
31
  - docker#v3.7.0:
31
- image: gusto/buildkite-builder:1.2.0
32
+ image: gusto/buildkite-builder:2.1.0
32
33
  propagate-environment: true
33
34
  ```
34
35
 
35
36
  Some things to note:
36
- - The `label` can be whatever you like.
37
- - You'll want to update the `docker` plugin version from time to time.
38
- - You can update the `buildkite-builder` version by bumping the Docker image tag.
37
+
38
+ - The `label` can be whatever you like.
39
+ - You'll want to update the `docker` plugin version from time to time.
40
+ - You can update the `buildkite-builder` version by bumping the Docker image tag.
39
41
 
40
42
  ## Usage
41
43
 
42
44
  💡 We have a [Showcase pipeline](https://buildkite.com/gusto-open-source/showcase/builds/latest?branch=main) (defined in [`.buildkite/pipelines/showcase/pipeline.rb`](https://github.com/Gusto/buildkite-builder/blob/main/.buildkite/pipelines/showcase/pipeline.rb)) that, well, showcases some of the features and possibilities with Buildkite Builder. Sometimes the best way to learning something is seeing how it's used.
43
45
 
44
46
  At its core, BKB is really just a YAML builder. This tool allows you to scale your needs when it comes to building a Buildkite pipeline. Your pipeline can be as straight forward as you'd like, or as complex as you need. Since you have Ruby at your disposal, you can do some cool things like:
45
- - Perform pre-build code/diff analysis to determine whether or not to to add a step to the pipeline.
46
- - Reorder pipeline steps dynamically.
47
- - Augment your pipeline steps with BKB processors.
47
+
48
+ - Perform pre-build code/diff analysis to determine whether or not to to add a step to the pipeline.
49
+ - Reorder pipeline steps dynamically.
50
+ - Augment your pipeline steps with BKB processors.
48
51
 
49
52
  ### Pipeline Files
53
+
50
54
  Your repo can contain as many pipeline definitions as you'd like. By convention, pipeline file structure are as such:
51
55
 
52
- ```
56
+ ```console
53
57
  .buildkite/
54
58
  pipelines/
55
59
  <your-pipeline1-slug>/
@@ -95,7 +99,7 @@ If the step type or attribute exists in Buildkite docs, then it should exist in
95
99
 
96
100
  If your pipeline has a lot of steps, you should consider using Step Templates. Templates allow you to break out your build steps into reusable template files.
97
101
 
98
- ```
102
+ ```console
99
103
  .buildkite/
100
104
  pipelines/
101
105
  foobar-widget/
@@ -108,6 +112,7 @@ If your pipeline has a lot of steps, you should consider using Step Templates. T
108
112
  A template is basically a step that was extracted from the pipeline:
109
113
 
110
114
  `.buildkite/pipelines/foobar-widget/templates/rspec.rb`
115
+
111
116
  ```ruby
112
117
  Buildkite::Builder.template do
113
118
  label "Rspec", emoji: :rspec
@@ -118,6 +123,7 @@ end
118
123
  You can then include the template into the the pipeline once or as many time as you need. The template name will be the name of the file (without the extension).
119
124
 
120
125
  `.buildkite/pipelines/foobar-widget/pipeline.rb`
126
+
121
127
  ```ruby
122
128
  Buildkite::Builder.pipeline do
123
129
  command(:rspec)
@@ -137,7 +143,7 @@ To install this gem onto your local machine, run `bundle exec rake install`.
137
143
 
138
144
  ## Contributing
139
145
 
140
- Bug reports and pull requests are welcome on GitHub at https://github.com/gusto/buildkite-builder. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/gusto/buildkite-builder/blob/main/CODE_OF_CONDUCT.md).
146
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/gusto/buildkite-builder>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/gusto/buildkite-builder/blob/main/CODE_OF_CONDUCT.md).
141
147
 
142
148
  ## License
143
149
 
@@ -145,4 +151,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
145
151
 
146
152
  ## Code of Conduct
147
153
 
148
- Everyone interacting in the Buildkite::Builder project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/gusto/buildkite-builder/blob/main/CODE_OF_CONDUCT.md).
154
+ Everyone interacting in the `Buildkite::Builder` project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/gusto/buildkite-builder/blob/main/CODE_OF_CONDUCT.md).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0.beta4
1
+ 2.3.0
@@ -15,8 +15,13 @@ module Buildkite
15
15
 
16
16
  # This entrypoint is for running on CI. It expects certain environment
17
17
  # variables to be set. It also uploads the pipeline to Buildkite.
18
- log.info "#{'+++ ' if Buildkite.env}🧰 " + 'Buildkite Builder'.color(:springgreen) + " ─ #{relative_pipeline_path.to_s.yellow}"
19
- Pipeline.new(pipeline_path, logger: log).upload
18
+ log.info "+++ 🧰 #{'Buildkite Builder'.color(:springgreen)} ─ #{relative_pipeline_path.to_s.yellow}"
19
+
20
+ if Buildkite::Pipelines::Command.meta_data(:exists, Builder::META_DATA.fetch(:job))
21
+ log.info 'Pipeline already uploaded'.color(:dimgray)
22
+ else
23
+ Pipeline.new(pipeline_path, logger: log).upload
24
+ end
20
25
  end
21
26
 
22
27
  private
@@ -0,0 +1,15 @@
1
+ module Buildkite
2
+ module Builder
3
+ module Extensions
4
+ class Lib < Extension
5
+ def prepare
6
+ lib_dir = Buildkite::Builder.root.join(Buildkite::Builder::BUILDKITE_DIRECTORY_NAME, 'lib')
7
+
8
+ if lib_dir.directory? && !$LOAD_PATH.include?(lib_dir)
9
+ $LOAD_PATH.unshift(lib_dir)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -10,9 +10,14 @@ module Buildkite
10
10
  end
11
11
 
12
12
  dsl do
13
- def group(label = nil, &block)
13
+ def group(label = nil, emoji: nil, &block)
14
14
  raise "Group does not allow nested in another Group" if context.is_a?(Group)
15
15
 
16
+ if emoji
17
+ emoji = Array(emoji).map { |name| ":#{name}:" }.join
18
+ label = [emoji, label].compact.join(' ')
19
+ end
20
+
16
21
  context.data.steps.push(Buildkite::Builder::Group.new(label, context.data.steps, &block))
17
22
  end
18
23
 
@@ -4,6 +4,7 @@ module Buildkite
4
4
  module Builder
5
5
  module Extensions
6
6
  autoload :Env, File.expand_path('extensions/env', __dir__)
7
+ autoload :Lib, File.expand_path('extensions/lib', __dir__)
7
8
  autoload :Notify, File.expand_path('extensions/notify', __dir__)
8
9
  autoload :Steps, File.expand_path('extensions/steps', __dir__)
9
10
  autoload :Use, File.expand_path('extensions/use', __dir__)
@@ -20,7 +20,7 @@ module Buildkite
20
20
  end
21
21
 
22
22
  def initialize
23
- @modified_files = SortedSet.new(pull_request? ? files_from_pull_request : files_from_git)
23
+ @modified_files = Set.new(pull_request? ? files_from_pull_request.sort! : files_from_git.sort!)
24
24
  end
25
25
 
26
26
  private
@@ -36,7 +36,7 @@ module Buildkite
36
36
  matched.map! { |file| Pathname.new(file) }
37
37
  matched.reject!(&:directory?)
38
38
  matched.map! { |file| file.relative_path_from(Builder.root) }
39
- SortedSet.new(matched)
39
+ Set.new(matched.sort!)
40
40
  end
41
41
  end
42
42
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'digest/md5'
4
4
  require 'pathname'
5
- require 'sorted_set'
6
5
 
7
6
  module Buildkite
8
7
  module Builder
@@ -56,7 +55,7 @@ module Buildkite
56
55
  end
57
56
 
58
57
  def files
59
- @files ||= inclusion_rules.map(&:files).reduce(SortedSet.new, :merge) - exclusion_rules.map(&:files).reduce(SortedSet.new, :merge)
58
+ @files ||= (inclusion_rules.map(&:files).reduce(Set.new, :merge) - exclusion_rules.map(&:files).reduce(Set.new, :merge)).sort.to_set
60
59
  end
61
60
 
62
61
  def digest
@@ -33,6 +33,7 @@ module Buildkite
33
33
  @data = Data.new
34
34
 
35
35
  use(Extensions::Use)
36
+ use(Extensions::Lib)
36
37
  use(Extensions::Env)
37
38
  use(Extensions::Notify)
38
39
  use(Extensions::Steps)
@@ -40,18 +41,22 @@ module Buildkite
40
41
  end
41
42
 
42
43
  def upload
43
- logger.info '+++ :paperclip: Uploading artifacts'
44
+ # Generate the pipeline YAML first.
45
+ contents = to_yaml
46
+
44
47
  upload_artifacts
45
48
 
46
49
  # Upload the pipeline.
47
50
  Tempfile.create(['pipeline', '.yml']) do |file|
48
51
  file.sync = true
49
- file.write(to_yaml)
52
+ file.write(contents)
50
53
 
51
54
  logger.info '+++ :paperclip: Uploading pipeline.yml as artifact'
52
55
  Buildkite::Pipelines::Command.artifact!(:upload, file.path)
53
56
  logger.info '+++ :pipeline: Uploading pipeline'
54
57
  Buildkite::Pipelines::Command.pipeline!(:upload, file.path)
58
+ logger.info "+++ :toolbox: Setting job meta-data to #{Buildkite.env.job_id.color(:yellow)}"
59
+ Buildkite::Pipelines::Command.meta_data!(:set, Builder::META_DATA.fetch(:job), Buildkite.env.job_id)
55
60
  end
56
61
  end
57
62
 
@@ -84,6 +89,8 @@ module Buildkite
84
89
  def upload_artifacts
85
90
  return if artifacts.empty?
86
91
 
92
+ logger.info "+++ :paperclip: Uploading #{artifacts.size.to_s.color(:yellow)} artifact#{'s' if artifacts.size != 1}"
93
+
87
94
  artifacts.each do |path|
88
95
  if File.exist?(path)
89
96
  Buildkite::Pipelines::Command.artifact!(:upload, path)
@@ -27,6 +27,14 @@ module Buildkite
27
27
  end
28
28
  end
29
29
 
30
+ def find(key)
31
+ @steps.find { |step| step.has?(:key) && step.key == key.to_s }
32
+ end
33
+
34
+ def find!(key)
35
+ find(key) || raise(ArgumentError, "Can't find step with key: #{key}")
36
+ end
37
+
30
38
  def add(step_class, template = nil, **args, &block)
31
39
  @steps.push(step_class.new(self, template, **args, &block)).last
32
40
  end
@@ -27,6 +27,9 @@ module Buildkite
27
27
  autoload :PluginManager, File.expand_path('builder/plugin_manager', __dir__)
28
28
 
29
29
  BUILDKITE_DIRECTORY_NAME = Pathname.new('.buildkite').freeze
30
+ META_DATA = {
31
+ job: 'buildkite-builder:job'
32
+ }.freeze
30
33
 
31
34
  class << self
32
35
  def root(start_path: Dir.pwd, reset: false)
@@ -46,7 +49,7 @@ module Buildkite
46
49
 
47
50
  def find_buildkite_directory(start_path)
48
51
  path = Pathname.new(start_path)
49
- until path.join(BUILDKITE_DIRECTORY_NAME).exist? && path.join(BUILDKITE_DIRECTORY_NAME).directory?
52
+ until path.join(BUILDKITE_DIRECTORY_NAME).directory?
50
53
  raise "Unable to find #{BUILDKITE_DIRECTORY_NAME} from #{start_path}" if path == path.parent
51
54
 
52
55
  path = path.parent
@@ -4,21 +4,35 @@ module Buildkite
4
4
  module Pipelines
5
5
  class Command
6
6
  BIN_PATH = 'buildkite-agent'
7
+ COMMANDS = %w(
8
+ pipeline
9
+ artifact
10
+ annotate
11
+ meta_data
12
+ )
7
13
 
8
- def self.pipeline!(*args)
9
- abort unless pipeline(*args)
10
- end
14
+ class << self
15
+ def pipeline(subcommand, *args)
16
+ new(:pipeline, subcommand, *args).run
17
+ end
11
18
 
12
- def self.pipeline(subcommand, *args)
13
- new(:pipeline, subcommand, *args).run
14
- end
19
+ def artifact(subcommand, *args)
20
+ new(:artifact, subcommand, *args).run
21
+ end
15
22
 
16
- def self.artifact!(*args)
17
- abort unless artifact(*args)
23
+ def annotate(body, *args)
24
+ new(:annotate, body, *args).run
25
+ end
26
+
27
+ def meta_data(subcommand, *args)
28
+ new(:'meta-data', subcommand, *args).run
29
+ end
18
30
  end
19
31
 
20
- def self.artifact(subcommand, *args)
21
- new(:artifact, subcommand, *args).run
32
+ COMMANDS.each do |command|
33
+ define_singleton_method("#{command}!") do |*args|
34
+ abort unless public_send(command, *args)
35
+ end
22
36
  end
23
37
 
24
38
  def initialize(command, subcommand, *args)
metadata CHANGED
@@ -1,30 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: buildkite-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta4
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ngan Pham
8
8
  - Andrew Lee
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-08-25 00:00:00.000000000 Z
12
+ date: 2021-11-12 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: sorted_set
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :runtime
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
14
  - !ruby/object:Gem::Dependency
29
15
  name: rainbow
30
16
  requirement: !ruby/object:Gem::Requirement
@@ -140,6 +126,7 @@ files:
140
126
  - lib/buildkite/builder/extension_manager.rb
141
127
  - lib/buildkite/builder/extensions.rb
142
128
  - lib/buildkite/builder/extensions/env.rb
129
+ - lib/buildkite/builder/extensions/lib.rb
143
130
  - lib/buildkite/builder/extensions/notify.rb
144
131
  - lib/buildkite/builder/extensions/steps.rb
145
132
  - lib/buildkite/builder/extensions/use.rb
@@ -194,7 +181,7 @@ metadata:
194
181
  source_code_uri: https://github.com/Gusto/buildkite-builder
195
182
  changelog_uri: https://github.com/Gusto/buildkite-builder/blob/master/CHANGELOG.md
196
183
  bug_tracker_uri: https://github.com/Gusto/buildkite-builder/issues
197
- post_install_message:
184
+ post_install_message:
198
185
  rdoc_options: []
199
186
  require_paths:
200
187
  - lib
@@ -205,12 +192,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
205
192
  version: 2.3.0
206
193
  required_rubygems_version: !ruby/object:Gem::Requirement
207
194
  requirements:
208
- - - ">"
195
+ - - ">="
209
196
  - !ruby/object:Gem::Version
210
- version: 1.3.1
197
+ version: '0'
211
198
  requirements: []
212
- rubygems_version: 3.2.2
213
- signing_key:
199
+ rubygems_version: 3.1.6
200
+ signing_key:
214
201
  specification_version: 4
215
202
  summary: A gem for programmatically creating Buildkite pipelines.
216
203
  test_files: []