buildkite-builder 3.9.0 → 4.0.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: 38dd50aa0554deb37552ff778d49fd94bd4e22e242ae72ccf179fdcf3460cf25
4
- data.tar.gz: a134a4f33462478c35b965c4dbbdb4451cfd4b383817150fc192301fada635af
3
+ metadata.gz: 3d9385a6b39f83697f501167fac9988d2e0b351a3e1b877b24e6c93670959d27
4
+ data.tar.gz: d5fe308edf2e426eb4c7be9bf9bf5996056533eb70724e18d438109732101492
5
5
  SHA512:
6
- metadata.gz: '02599590709a1ca3f7e19da232889b3bf26ff316ff48dc10b8ec3751efc1e08c39a3bf05c6eee21bc2d6463b296d8d777d1d89f5b55abd6ad1667ec89925fa8f'
7
- data.tar.gz: a8b4e2b45030b631e1bbb9da80954a7debc9d056945e1e57f36b1df51e88fa68812bb3c99e3826536df356a0520d3e0fe830aa98fd7bea7f88a02dece853253e
6
+ metadata.gz: c406b7822bd571773bc3e2f29bf71b1067cacf1cf434b92457c8936a64757efdc48c8f8a63f9f56fc7885d5505d2505bd6f9ac8c9447f1f90d992b263508b3cb
7
+ data.tar.gz: ddfc34afe276f2716b86d5db4fe07a6854ef0135dd93f8e4b0bd8d5fb14aa07ffcd8c892661823bad17b90e6bcea3b977a7d5ca46694429250e7c9f818ea9baa
data/README.md CHANGED
@@ -135,36 +135,6 @@ Buildkite::Builder.pipeline do
135
135
  end
136
136
  ```
137
137
 
138
- ### Subpipeline
139
-
140
- While triggering another pipeline, you can predefine subpipeline's steps using `pipeline(NAME_OF_SUBPIPELINE)` in the main pipeline's `pipeline.rb` file and share with main pipeline's plugins and templates definition.
141
-
142
- `.buildkite/pipelines/pipeline-triggerer/pipeline.rb`
143
-
144
- ```ruby
145
- Buildkite::Builder.pipeline do
146
- pipeline('rspec-pipeline') do
147
- command do
148
- label "Run RSpec in separate pipeline"
149
- end
150
- end
151
- end
152
- ```
153
-
154
- Inside your Buildkite pipeline setup, you can do the following:
155
-
156
- In `https://buildkite.com/your-org/rspec-pipeline/steps`
157
-
158
- ```yaml
159
- steps:
160
- - label: ":pipeline:"
161
- commands:
162
- - buildkite-agent artifact download $BKB_SUBPIPELINE_FILE . --build $BUILDKITE_TRIGGERED_FROM_BUILD_ID
163
- - buildkite-agent pipeline upload $BKB_SUBPIPELINE_FILE
164
- ```
165
-
166
- This will upload the pregenerated `pipeline.yml` to `rspec-pipeline`.
167
-
168
138
  ## Development
169
139
 
170
140
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.9.0
1
+ 4.0.0
@@ -8,7 +8,7 @@ module Buildkite
8
8
  @context = context
9
9
  @extensions = {}
10
10
 
11
- @loader = Loaders::Extensions.load(@context.root)
11
+ Loaders::Extensions.load(@context.root)
12
12
  end
13
13
 
14
14
  def use(extension, native: false, **args, &block)
@@ -34,6 +34,10 @@ module Buildkite
34
34
  @extensions.fetch(klass)
35
35
  end
36
36
 
37
+ def all
38
+ @extensions.keys
39
+ end
40
+
37
41
  private
38
42
 
39
43
  def log
@@ -23,17 +23,6 @@ module Buildkite
23
23
  resource.is_a?(Symbol) ? manager.build(resource, attributes) : plugin
24
24
  end
25
25
  end
26
-
27
- context.data.pipelines.each do |pipeline|
28
- pipeline.data.steps.each(:command) do |step|
29
- next unless step.has?(:plugins)
30
-
31
- step.get(:plugins).map! do |plugin|
32
- resource, attributes = extract_resource_and_attributes(plugin)
33
- resource.is_a?(Symbol) ? manager.build(resource, attributes) : plugin
34
- end
35
- end
36
- end
37
26
  end
38
27
 
39
28
  private
@@ -2,54 +2,76 @@ module Buildkite
2
2
  module Builder
3
3
  module Extensions
4
4
  class Steps < Extension
5
+ attr_reader :templates
6
+
5
7
  def prepare
6
- context.data.steps = StepCollection.new(TemplateManager.new(context.root))
8
+ @templates = TemplateManager.new(context.root)
9
+ context.data.steps = StepCollection.new
7
10
  end
8
11
 
9
- dsl do
10
- def group(label = nil, emoji: nil, &block)
11
- raise "Group does not allow nested in another Group" if context.is_a?(Group)
12
+ def build_step(step_class, template_name, **args, &block)
13
+ template = @templates.find(template_name)
14
+
15
+ step_class.new(**args).tap do |step|
16
+ step.process(template) if template
17
+ step.process(block) if block_given?
12
18
 
13
- if emoji
14
- emoji = Array(emoji).map { |name| ":#{name}:" }.join
15
- label = [emoji, label].compact.join(' ')
19
+ if @current_group
20
+ @current_group.steps.push(step)
21
+ else
22
+ context.data.steps.push(step)
16
23
  end
24
+ end
25
+ end
26
+
27
+ def with_group(group, &block)
28
+ raise "Group cannot be nested" if @current_group
17
29
 
18
- context.data.steps.push(Buildkite::Builder::Group.new(label, context, &block))
30
+ @current_group = group
31
+
32
+ group.process(block)
33
+ context.data.steps.push(group).last
34
+ ensure
35
+ @current_group = nil
36
+ end
37
+
38
+ dsl do
39
+ def group(&block)
40
+ context.extensions.find(Steps).with_group(Pipelines::Steps::Group.new(context), &block)
19
41
  end
20
42
 
21
43
  def block(template = nil, **args, &block)
22
- context.data.steps.add(Pipelines::Steps::Block, template, **args, &block)
44
+ context.extensions.find(Steps).build_step(Pipelines::Steps::Block, template, **args, &block)
23
45
  end
24
46
 
25
47
  def command(template = nil, **args, &block)
26
- context.data.steps.add(Pipelines::Steps::Command, template, **args, &block)
48
+ context.extensions.find(Steps).build_step(Pipelines::Steps::Command, template, **args, &block)
27
49
  end
28
50
 
29
51
  def input(template = nil, **args, &block)
30
- context.data.steps.add(Pipelines::Steps::Input, template, **args, &block)
52
+ context.extensions.find(Steps).build_step(Pipelines::Steps::Input, template, **args, &block)
31
53
  end
32
54
 
33
55
  def trigger(template = nil, **args, &block)
34
- context.data.steps.add(Pipelines::Steps::Trigger, template, **args, &block)
56
+ context.extensions.find(Steps).build_step(Pipelines::Steps::Trigger, template, **args, &block)
35
57
  end
36
58
 
37
59
  def skip(template = nil, **args, &block)
38
- step = context.data.steps.add(Pipelines::Steps::Skip, template, **args, &block)
39
- # A skip step has a nil/noop command.
40
- step.command(nil)
41
- # Always set the skip attribute if it's in a falsey state.
42
- step.skip(true) if !step.get(:skip) || step.skip.empty?
43
- step
60
+ context.extensions.find(Steps).build_step(Pipelines::Steps::Skip, template, **args, &block).tap do |step|
61
+ # A skip step has a nil/noop command.
62
+ step.command(nil)
63
+ # Always set the skip attribute if it's in a falsey state.
64
+ step.skip(true) if !step.get(:skip) || step.skip.empty?
65
+ end
44
66
  end
45
67
 
46
68
  def wait(attributes = {}, &block)
47
- step = context.data.steps.add(Pipelines::Steps::Wait, &block)
48
- step.wait(nil)
49
- attributes.each do |key, value|
50
- step.set(key, value)
69
+ context.extensions.find(Steps).build_step(Pipelines::Steps::Wait, nil, &block).tap do |step|
70
+ step.wait(nil)
71
+ attributes.each do |key, value|
72
+ step.set(key, value)
73
+ end
51
74
  end
52
- step
53
75
  end
54
76
  end
55
77
  end
@@ -6,7 +6,6 @@ module Buildkite
6
6
  autoload :Env, File.expand_path('extensions/env', __dir__)
7
7
  autoload :Lib, File.expand_path('extensions/lib', __dir__)
8
8
  autoload :Notify, File.expand_path('extensions/notify', __dir__)
9
- autoload :SubPipelines, File.expand_path('extensions/sub_pipelines', __dir__)
10
9
  autoload :Steps, File.expand_path('extensions/steps', __dir__)
11
10
  autoload :Plugins, File.expand_path('extensions/plugins', __dir__)
12
11
  autoload :Use, File.expand_path('extensions/use', __dir__)
@@ -19,7 +19,6 @@ module Buildkite
19
19
  attr_reader :logger,
20
20
  :root,
21
21
  :artifacts,
22
- :plugins,
23
22
  :dsl,
24
23
  :data,
25
24
  :extensions
@@ -28,7 +27,6 @@ module Buildkite
28
27
  @root = root
29
28
  @logger = logger || Logger.new(File::NULL)
30
29
  @artifacts = []
31
- @plugins = {}
32
30
  @dsl = Dsl.new(self)
33
31
  @extensions = ExtensionManager.new(self)
34
32
  @data = Data.new
@@ -39,7 +37,6 @@ module Buildkite
39
37
  use(Extensions::Notify)
40
38
  use(Extensions::Steps)
41
39
  use(Extensions::Plugins)
42
- use(Extensions::SubPipelines)
43
40
  end
44
41
 
45
42
  def upload
@@ -1,11 +1,9 @@
1
1
  module Buildkite
2
2
  module Builder
3
3
  class StepCollection
4
- attr_reader :templates
5
4
  attr_reader :steps
6
5
 
7
- def initialize(templates)
8
- @templates = templates
6
+ def initialize
9
7
  @steps = []
10
8
  end
11
9
 
@@ -13,12 +11,12 @@ module Buildkite
13
11
  types = types.flatten
14
12
 
15
13
  @steps.each do |step|
16
- if types.include?(step.class.to_sym)
17
- yield step
18
- elsif step.is_a?(Group)
19
- step.data.steps.each(*types) do |step|
14
+ if step.class.to_sym == :group
15
+ step.steps.each(*types) do |step|
20
16
  yield step
21
17
  end
18
+ elsif types.include?(step.class.to_sym)
19
+ yield step
22
20
  elsif types.empty?
23
21
  yield step
24
22
  end
@@ -33,10 +31,6 @@ module Buildkite
33
31
  find(key) || raise(ArgumentError, "Can't find step with key: #{key}")
34
32
  end
35
33
 
36
- def add(step_class, template = nil, **args, &block)
37
- @steps.push(step_class.new(self, template, **args, &block)).last
38
- end
39
-
40
34
  def push(step)
41
35
  @steps.push(step)
42
36
  end
@@ -5,7 +5,6 @@ require 'pathname'
5
5
  module Buildkite
6
6
  module Builder
7
7
  autoload :Commands, File.expand_path('builder/commands', __dir__)
8
- autoload :Group, File.expand_path('builder/group', __dir__)
9
8
  autoload :Pipeline, File.expand_path('builder/pipeline', __dir__)
10
9
  autoload :Definition, File.expand_path('builder/definition', __dir__)
11
10
  autoload :Data, File.expand_path('builder/data', __dir__)
@@ -11,20 +11,16 @@ module Buildkite
11
11
 
12
12
  def_delegator :@context, :data
13
13
 
14
- attr_reader :template
15
- attr_reader :step_collection
16
-
17
14
  def self.to_sym
18
15
  name.split('::').last.downcase.to_sym
19
16
  end
20
17
 
21
- def initialize(step_collection, template_name, **args, &block)
22
- @step_collection = step_collection
23
- @template = step_collection.templates.find(template_name)
18
+ def initialize(**args)
24
19
  @context = StepContext.new(self, **args)
20
+ end
25
21
 
26
- instance_exec(@context, &template) if template
27
- instance_exec(@context, &block) if block_given?
22
+ def process(block)
23
+ instance_exec(@context, &block)
28
24
  end
29
25
  end
30
26
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buildkite
4
+ module Pipelines
5
+ module Steps
6
+ class Group < Abstract
7
+ attribute :depends_on, append: true
8
+ attribute :key
9
+ attribute :label
10
+
11
+ attr_reader :steps
12
+
13
+ def initialize(pipeline, **args)
14
+ @pipeline = pipeline
15
+ @context = StepContext.new(self, **args)
16
+ @steps = Buildkite::Builder::StepCollection.new
17
+ end
18
+
19
+ def method_missing(method_name, ...)
20
+ if @pipeline.dsl.respond_to?(method_name)
21
+ @pipeline.dsl.public_send(method_name, ...)
22
+ else
23
+ super
24
+ end
25
+ end
26
+
27
+ def respond_to_missing?(...)
28
+ @pipeline.dsl.respond_to?(...) || super
29
+ end
30
+
31
+ def to_h
32
+ super.merge(group: nil, steps: steps.to_definition)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -6,6 +6,7 @@ module Buildkite
6
6
  autoload :Abstract, File.expand_path('steps/abstract', __dir__)
7
7
  autoload :Block, File.expand_path('steps/block', __dir__)
8
8
  autoload :Command, File.expand_path('steps/command', __dir__)
9
+ autoload :Group, File.expand_path('steps/group', __dir__)
9
10
  autoload :Input, File.expand_path('steps/input', __dir__)
10
11
  autoload :Skip, File.expand_path('steps/skip', __dir__)
11
12
  autoload :Trigger, File.expand_path('steps/trigger', __dir__)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: buildkite-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.9.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ngan Pham
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-12-12 00:00:00.000000000 Z
12
+ date: 2022-12-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rainbow
@@ -115,16 +115,13 @@ files:
115
115
  - lib/buildkite/builder/extensions/notify.rb
116
116
  - lib/buildkite/builder/extensions/plugins.rb
117
117
  - lib/buildkite/builder/extensions/steps.rb
118
- - lib/buildkite/builder/extensions/sub_pipelines.rb
119
118
  - lib/buildkite/builder/extensions/use.rb
120
- - lib/buildkite/builder/group.rb
121
119
  - lib/buildkite/builder/loaders.rb
122
120
  - lib/buildkite/builder/loaders/abstract.rb
123
121
  - lib/buildkite/builder/loaders/extensions.rb
124
122
  - lib/buildkite/builder/loaders/templates.rb
125
123
  - lib/buildkite/builder/logging_utils.rb
126
124
  - lib/buildkite/builder/pipeline.rb
127
- - lib/buildkite/builder/pipeline_collection.rb
128
125
  - lib/buildkite/builder/plugin.rb
129
126
  - lib/buildkite/builder/plugin_manager.rb
130
127
  - lib/buildkite/builder/rainbow.rb
@@ -150,6 +147,7 @@ files:
150
147
  - lib/buildkite/pipelines/steps/abstract.rb
151
148
  - lib/buildkite/pipelines/steps/block.rb
152
149
  - lib/buildkite/pipelines/steps/command.rb
150
+ - lib/buildkite/pipelines/steps/group.rb
153
151
  - lib/buildkite/pipelines/steps/input.rb
154
152
  - lib/buildkite/pipelines/steps/skip.rb
155
153
  - lib/buildkite/pipelines/steps/trigger.rb
@@ -1,104 +0,0 @@
1
- require 'securerandom'
2
-
3
- module Buildkite
4
- module Builder
5
- module Extensions
6
- class SubPipelines < Extension
7
- class Pipeline
8
- include Buildkite::Pipelines::Attributes
9
-
10
- attr_reader :data, :name, :dsl
11
-
12
- # These attributes are for triggered step
13
- attribute :label
14
- attribute :key
15
- attribute :skip
16
- attribute :if, as: :condition
17
- attribute :depends_on, append: true
18
- attribute :allow_dependency_failure
19
- attribute :branches
20
- attribute :async
21
- attribute :build
22
-
23
- def self.to_sym
24
- name.split('::').last.downcase.to_sym
25
- end
26
-
27
- def initialize(name, context, &block)
28
- @context = context
29
- @name = name
30
- @data = Data.new
31
- @data.steps = StepCollection.new(context.data.steps.templates)
32
- @data.notify = []
33
- @data.env = {}
34
-
35
- # Use `clone` to copy over dsl's extended extensions
36
- @dsl = context.dsl.clone
37
- # Override dsl context to current pipeline
38
- @dsl.instance_variable_set(:@context, self)
39
-
40
- instance_eval(&block) if block_given?
41
- self
42
- end
43
-
44
- def to_h
45
- # Merge envs from main pipeline, since ruby does not have `reverse_merge` and
46
- # `data` does not allow keys override, we have to reset the data hash per key.
47
- @context.data.env.merge(data.env).each do |key, value|
48
- data.env[key] = value
49
- end
50
- data.to_definition
51
- end
52
-
53
- def method_missing(method_name, *args, **kwargs, &_block)
54
- @dsl.public_send(method_name, *args, **kwargs, &_block)
55
- end
56
-
57
- def pipeline_yml
58
- @pipeline_yml ||= "tmp/buildkite-builder/#{SecureRandom.urlsafe_base64}.yml"
59
- end
60
- end
61
-
62
- def prepare
63
- context.data.pipelines = PipelineCollection.new(context.artifacts)
64
- end
65
-
66
- dsl do
67
- def pipeline(name, &block)
68
- raise "Subpipeline must have a name" if name.empty?
69
- raise "Subpipeline does not allow nested in another Subpipeline" if context.is_a?(Buildkite::Builder::Extensions::SubPipelines::Pipeline)
70
-
71
- sub_pipeline = Buildkite::Builder::Extensions::SubPipelines::Pipeline.new(name, context, &block)
72
- context.data.pipelines.add(sub_pipeline)
73
-
74
- trigger_step = context.data.steps.add(Pipelines::Steps::Trigger)
75
- trigger_step.trigger(name)
76
-
77
- build_options = {
78
- message: '${BUILDKITE_MESSAGE}',
79
- commit: '${BUILDKITE_COMMIT}',
80
- branch: '${BUILDKITE_BRANCH}',
81
- env: {
82
- BUILDKITE_PULL_REQUEST: '${BUILDKITE_PULL_REQUEST}',
83
- BUILDKITE_PULL_REQUEST_BASE_BRANCH: '${BUILDKITE_PULL_REQUEST_BASE_BRANCH}',
84
- BUILDKITE_PULL_REQUEST_REPO: '${BUILDKITE_PULL_REQUEST_REPO}',
85
- BKB_SUBPIPELINE_FILE: sub_pipeline.pipeline_yml
86
- }
87
- }
88
- build_options.merge!(sub_pipeline.build) if sub_pipeline.build
89
-
90
- trigger_step.build(build_options)
91
- trigger_step.key(sub_pipeline.key || "subpipeline_#{name}_#{context.data.pipelines.count}")
92
- trigger_step.label(sub_pipeline.label || name.capitalize)
93
- trigger_step.async(sub_pipeline.async || false)
94
- trigger_step.branches(sub_pipeline.branches) if sub_pipeline.branches
95
- trigger_step.condition(sub_pipeline.condition) if sub_pipeline.condition
96
- trigger_step.depends_on(*sub_pipeline.get('depends_on')) if sub_pipeline.get('depends_on')
97
- trigger_step.allow_dependency_failure(sub_pipeline.allow_dependency_failure || false)
98
- trigger_step.skip(sub_pipeline.skip || false)
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end
@@ -1,41 +0,0 @@
1
- module Buildkite
2
- module Builder
3
- class Group
4
- include Buildkite::Pipelines::Attributes
5
-
6
- attr_reader :label
7
- attr_reader :data
8
-
9
- attribute :depends_on, append: true
10
- attribute :key
11
-
12
- def self.to_sym
13
- name.split('::').last.downcase.to_sym
14
- end
15
-
16
- def initialize(label, context, &block)
17
- @label = label
18
- @data = Data.new
19
- @data.steps = StepCollection.new(context.data.steps.templates)
20
- @data.notify = []
21
-
22
- # Use `clone` to copy over dsl's extended extensions
23
- @dsl = context.dsl.clone
24
- # Override dsl context to current group
25
- @dsl.instance_variable_set(:@context, self)
26
-
27
- instance_eval(&block) if block_given?
28
- self
29
- end
30
-
31
- def to_h
32
- attributes = super
33
- { group: label }.merge(attributes).merge(data.to_definition)
34
- end
35
-
36
- def method_missing(method_name, *args, **kwargs, &_block)
37
- @dsl.public_send(method_name, *args, **kwargs, &_block)
38
- end
39
- end
40
- end
41
- end
@@ -1,40 +0,0 @@
1
- require "forwardable"
2
-
3
- module Buildkite
4
- module Builder
5
- class PipelineCollection
6
- extend Forwardable
7
-
8
- attr_reader :pipelines
9
-
10
- def_delegator :@pipelines, :count
11
- def_delegator :@pipelines, :each
12
-
13
- def initialize(artifacts)
14
- @artifacts = artifacts
15
- @pipelines = []
16
- end
17
-
18
- def add(pipeline)
19
- unless pipeline.is_a?(Buildkite::Builder::Extensions::SubPipelines::Pipeline)
20
- raise "`#{pipeline}` must be a Buildkite::Builder::Extensions::SubPipelines::Pipeline"
21
- end
22
-
23
- pipelines << pipeline
24
- end
25
-
26
- def to_definition
27
- # Instead of generates pipeline.yml, subpipelines save generated file to artifacts
28
- pipelines.each do |pipeline|
29
- file = Pathname.new(pipeline.pipeline_yml)
30
- file.dirname.mkpath
31
- file.write(YAML.dump(Pipelines::Helpers.sanitize(pipeline.to_h)))
32
-
33
- @artifacts << file
34
- end
35
-
36
- nil
37
- end
38
- end
39
- end
40
- end