buildkite-builder 1.3.0 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/VERSION +1 -1
- data/lib/buildkite/builder.rb +10 -1
- data/lib/buildkite/builder/commands.rb +2 -2
- data/lib/buildkite/builder/commands/abstract.rb +4 -4
- data/lib/buildkite/builder/commands/files.rb +6 -7
- data/lib/buildkite/builder/commands/preview.rb +1 -1
- data/lib/buildkite/builder/commands/run.rb +1 -1
- data/lib/buildkite/builder/data.rb +41 -0
- data/lib/buildkite/builder/dsl.rb +17 -0
- data/lib/buildkite/builder/extension.rb +51 -0
- data/lib/buildkite/builder/extension_manager.rb +55 -0
- data/lib/buildkite/builder/extensions.rb +12 -0
- data/lib/buildkite/builder/extensions/env.rb +21 -0
- data/lib/buildkite/builder/extensions/notify.rb +21 -0
- data/lib/buildkite/builder/extensions/steps.rb +60 -0
- data/lib/buildkite/builder/extensions/use.rb +13 -0
- data/lib/buildkite/builder/github.rb +1 -1
- data/lib/buildkite/builder/group.rb +41 -0
- data/lib/buildkite/builder/loaders.rb +1 -1
- data/lib/buildkite/builder/loaders/{processors.rb → extensions.rb} +9 -9
- data/lib/buildkite/builder/{context.rb → pipeline.rb} +42 -47
- data/lib/buildkite/builder/plugin_registry.rb +27 -0
- data/lib/buildkite/builder/step_collection.rb +43 -0
- data/lib/buildkite/builder/template_registry.rb +27 -0
- data/lib/buildkite/pipelines.rb +0 -1
- data/lib/buildkite/pipelines/attributes.rb +1 -1
- data/lib/buildkite/pipelines/helpers/command.rb +1 -5
- data/lib/buildkite/pipelines/helpers/plugins.rb +1 -1
- data/lib/buildkite/pipelines/step_context.rb +0 -4
- data/lib/buildkite/pipelines/steps/abstract.rb +12 -7
- metadata +19 -9
- data/lib/buildkite/builder/processors.rb +0 -9
- data/lib/buildkite/builder/processors/abstract.rb +0 -76
- data/lib/buildkite/pipelines/pipeline.rb +0 -140
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a9777c2d258caf0ee500fee89d04fe9385a9357f2df66f007b60c88bd361afa
|
4
|
+
data.tar.gz: f8a8e77e07fe770231f00bc7d3a693524cb5495f45c0529313737152dd44be1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 824bb77591ec310cace0138dd32269cd379ba244ec0283b53cd86d1e6001b24bd0a208c5662bf1b4d171c773e85c0053decfe619431cccbe6c38e24e7badb32d
|
7
|
+
data.tar.gz: 30502c1de926f6e48423b4d254dc82b86248f2bf5c7e290f50bd972b63ef9d9702bbdd0dd4c81f3cd37aa0da5b3f4076402d72d3f6eb5531b662a96cfdbfa3a4
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## 1.5.0
|
2
|
+
* Merge `BuildKite::Builder::Context` and `BuildKite::Pipelines::Pipeline` to `BuildKite::Builder::Pipeline` (#37)
|
3
|
+
|
4
|
+
## 1.4.1
|
5
|
+
* Fix the Github API Builder to account for Buildkite having both `.git` and no file exention repository URIs (#33)
|
6
|
+
|
7
|
+
## 1.4.0
|
8
|
+
* Fix the `files` command. You now pass in the manifest with the `--manifest` CLI argument.
|
9
|
+
|
10
|
+
## 1.3.1
|
11
|
+
* Expose `data` from `StepContext` to `Step`
|
12
|
+
|
1
13
|
## 1.3.0
|
2
14
|
* Add ability for step to store data in step context
|
3
15
|
* Move `upload` from `BuildKite::Builder::Commands::Run` to `BuildKite::Builder::Context`
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0.beta1
|
data/lib/buildkite/builder.rb
CHANGED
@@ -5,8 +5,14 @@ require 'pathname'
|
|
5
5
|
module Buildkite
|
6
6
|
module Builder
|
7
7
|
autoload :Commands, File.expand_path('builder/commands', __dir__)
|
8
|
-
autoload :
|
8
|
+
autoload :Group, File.expand_path('builder/group', __dir__)
|
9
|
+
autoload :Pipeline, File.expand_path('builder/pipeline', __dir__)
|
9
10
|
autoload :Definition, File.expand_path('builder/definition', __dir__)
|
11
|
+
autoload :Data, File.expand_path('builder/data', __dir__)
|
12
|
+
autoload :Dsl, File.expand_path('builder/dsl', __dir__)
|
13
|
+
autoload :Extension, File.expand_path('builder/extension', __dir__)
|
14
|
+
autoload :ExtensionManager, File.expand_path('builder/extension_manager', __dir__)
|
15
|
+
autoload :Extensions, File.expand_path('builder/extensions', __dir__)
|
10
16
|
autoload :FileResolver, File.expand_path('builder/file_resolver', __dir__)
|
11
17
|
autoload :Github, File.expand_path('builder/github', __dir__)
|
12
18
|
autoload :Loaders, File.expand_path('builder/loaders', __dir__)
|
@@ -14,6 +20,9 @@ module Buildkite
|
|
14
20
|
autoload :Manifest, File.expand_path('builder/manifest', __dir__)
|
15
21
|
autoload :Processors, File.expand_path('builder/processors', __dir__)
|
16
22
|
autoload :Rainbow, File.expand_path('builder/rainbow', __dir__)
|
23
|
+
autoload :StepCollection, File.expand_path('builder/step_collection', __dir__)
|
24
|
+
autoload :TemplateRegistry, File.expand_path('builder/template_registry', __dir__)
|
25
|
+
autoload :PluginRegistry, File.expand_path('builder/plugin_registry', __dir__)
|
17
26
|
|
18
27
|
BUILDKITE_DIRECTORY_NAME = Pathname.new('.buildkite').freeze
|
19
28
|
|
@@ -32,10 +32,10 @@ module Buildkite
|
|
32
32
|
puts <<~HELP
|
33
33
|
#{'SYNOPSIS'.bright}
|
34
34
|
\t#{'buildkite-builder'.bright} COMMAND [OPTIONS] [PIPELINE]
|
35
|
-
|
35
|
+
|
36
36
|
\t#{'To see available options for specific commands:'.color(:dimgray)}
|
37
37
|
\t#{'buildkite-builder'.bright} COMMAND --help
|
38
|
-
|
38
|
+
|
39
39
|
#{'COMMANDS'.bright}
|
40
40
|
HELP
|
41
41
|
COMMANDS.each do |command, klass|
|
@@ -8,9 +8,9 @@ module Buildkite
|
|
8
8
|
class Abstract
|
9
9
|
PIPELINES_DIRECTORY = 'pipelines'
|
10
10
|
POSSIBLE_PIPELINE_PATHS = [
|
11
|
-
File.join('.buildkite',
|
12
|
-
File.join('buildkite',
|
13
|
-
File.join(
|
11
|
+
File.join('.buildkite', Pipeline::PIPELINE_DEFINITION_FILE),
|
12
|
+
File.join('buildkite', Pipeline::PIPELINE_DEFINITION_FILE),
|
13
|
+
File.join(Pipeline::PIPELINE_DEFINITION_FILE)
|
14
14
|
].freeze
|
15
15
|
POSSIBLE_PIPELINES_PATHS = [
|
16
16
|
File.join('.buildkite', PIPELINES_DIRECTORY),
|
@@ -91,7 +91,7 @@ module Buildkite
|
|
91
91
|
|
92
92
|
def find_root_by_multi_pipeline
|
93
93
|
pipelines_path = POSSIBLE_PIPELINES_PATHS.map { |path| Builder.root.join(path) }.find(&:directory?)
|
94
|
-
|
94
|
+
|
95
95
|
if pipelines_path
|
96
96
|
if pipeline_slug
|
97
97
|
path = pipelines_path.join(pipeline_slug)
|
@@ -9,14 +9,13 @@ module Buildkite
|
|
9
9
|
self.description = 'Outputs files that match the specified manifest.'
|
10
10
|
|
11
11
|
def run
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
12
|
+
manifests = Loaders::Manifests.load(pipeline_path)
|
13
|
+
puts manifests[options[:manifest]].files.sort.join("\n")
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def parse_options(opts)
|
17
|
+
opts.on('--manifest MANIFEST', 'The manifest to use') do |manifest|
|
18
|
+
options[:manifest] = manifest
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
@@ -16,7 +16,7 @@ module Buildkite
|
|
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
18
|
log.info "#{'+++ ' if Buildkite.env}🧰 " + 'Buildkite Builder'.color(:springgreen) + " ─ #{relative_pipeline_path.to_s.yellow}"
|
19
|
-
|
19
|
+
Pipeline.new(pipeline_path, logger: log).upload
|
20
20
|
end
|
21
21
|
|
22
22
|
private
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Buildkite
|
2
|
+
module Builder
|
3
|
+
class Data
|
4
|
+
def initialize
|
5
|
+
@data = Hash.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_definition
|
9
|
+
@data.each_with_object({}) do |(key, value), hash|
|
10
|
+
value = value.respond_to?(:to_definition) ? value.to_definition : value
|
11
|
+
|
12
|
+
next if value.empty?
|
13
|
+
|
14
|
+
hash[key] = value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def method_missing(name, *args, &block)
|
21
|
+
if name.end_with?('=')
|
22
|
+
name = name.to_s.delete_suffix('=').to_sym
|
23
|
+
|
24
|
+
if respond_to_missing?(name)
|
25
|
+
raise ArgumentError, "Data already contains key '#{name}'"
|
26
|
+
else
|
27
|
+
return @data[name] = args.first
|
28
|
+
end
|
29
|
+
elsif respond_to_missing?(name)
|
30
|
+
return @data[name]
|
31
|
+
end
|
32
|
+
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def respond_to_missing?(name, *)
|
37
|
+
@data.key?(name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Buildkite
|
4
|
+
module Builder
|
5
|
+
class Dsl
|
6
|
+
attr_reader :context
|
7
|
+
|
8
|
+
def extend(mod)
|
9
|
+
mod < Extension ? super(mod.dsl) : super
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(context)
|
13
|
+
@context = context
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Buildkite
|
4
|
+
module Builder
|
5
|
+
class Extension
|
6
|
+
class << self
|
7
|
+
attr_reader :dsl
|
8
|
+
|
9
|
+
def dsl(&block)
|
10
|
+
@dsl = Module.new(&block) if block_given?
|
11
|
+
@dsl
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :context
|
16
|
+
attr_reader :options
|
17
|
+
|
18
|
+
def initialize(context, **options)
|
19
|
+
@context = context
|
20
|
+
@options = options
|
21
|
+
|
22
|
+
prepare
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
# Override to provide extra functionality.
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def buildkite
|
32
|
+
@buildkite ||= begin
|
33
|
+
unless Buildkite.env
|
34
|
+
raise 'Must be in Buildkite environment to access the Buildkite API'
|
35
|
+
end
|
36
|
+
|
37
|
+
Buildkite::Pipelines::Api.new(Buildkite.env.api_token)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def prepare
|
42
|
+
# Override to provide extra functionality.
|
43
|
+
end
|
44
|
+
|
45
|
+
def pipeline(&block)
|
46
|
+
context.dsl.instance_eval(&block) if block_given?
|
47
|
+
context
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Buildkite
|
2
|
+
module Builder
|
3
|
+
class ExtensionManager
|
4
|
+
include LoggingUtils
|
5
|
+
using Rainbow
|
6
|
+
|
7
|
+
def initialize(context)
|
8
|
+
@context = context
|
9
|
+
@extensions = []
|
10
|
+
|
11
|
+
Loaders::Extensions.load(@context.root)
|
12
|
+
end
|
13
|
+
|
14
|
+
def use(extension, **args)
|
15
|
+
unless extension < Buildkite::Builder::Extension
|
16
|
+
raise "#{extension} must subclass Buildkite::Builder::Extension"
|
17
|
+
end
|
18
|
+
|
19
|
+
@extensions.push(extension.new(@context, **args))
|
20
|
+
@context.dsl.extend(extension)
|
21
|
+
end
|
22
|
+
|
23
|
+
def build
|
24
|
+
@extensions.each do |extension|
|
25
|
+
log_build(extension.class.name) { extension.build }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def log
|
32
|
+
@context.logger
|
33
|
+
end
|
34
|
+
|
35
|
+
def log_build(name)
|
36
|
+
log.info "\nProcessing ".color(:dimgray) + name.color(:springgreen)
|
37
|
+
|
38
|
+
results = benchmark('└──'.color(:springgreen) + ' Finished in %s'.color(:dimgray)) do
|
39
|
+
formatter = log.formatter
|
40
|
+
log.formatter = proc do |_severity, _datetime, _progname, msg|
|
41
|
+
'│'.color(:springgreen) + " #{msg}\n"
|
42
|
+
end
|
43
|
+
|
44
|
+
begin
|
45
|
+
yield
|
46
|
+
ensure
|
47
|
+
log.formatter = formatter
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
log.info results
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Buildkite
|
4
|
+
module Builder
|
5
|
+
module Extensions
|
6
|
+
autoload :Env, File.expand_path('extensions/env', __dir__)
|
7
|
+
autoload :Notify, File.expand_path('extensions/notify', __dir__)
|
8
|
+
autoload :Steps, File.expand_path('extensions/steps', __dir__)
|
9
|
+
autoload :Use, File.expand_path('extensions/use', __dir__)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Buildkite
|
2
|
+
module Builder
|
3
|
+
module Extensions
|
4
|
+
class Env < Extension
|
5
|
+
def prepare
|
6
|
+
context.data.env = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
dsl do
|
10
|
+
def env(*args)
|
11
|
+
if args.first.is_a?(Hash)
|
12
|
+
context.data.env.merge!(args.first.transform_keys(&:to_s))
|
13
|
+
else
|
14
|
+
raise ArgumentError, 'value must be hash'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Buildkite
|
2
|
+
module Builder
|
3
|
+
module Extensions
|
4
|
+
class Notify < Extension
|
5
|
+
def prepare
|
6
|
+
context.data.notify = []
|
7
|
+
end
|
8
|
+
|
9
|
+
dsl do
|
10
|
+
def notify(*args)
|
11
|
+
if args.first.is_a?(Hash)
|
12
|
+
context.data.notify.push(args.first.transform_keys(&:to_s))
|
13
|
+
else
|
14
|
+
raise ArgumentError, 'value must be hash'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Buildkite
|
2
|
+
module Builder
|
3
|
+
module Extensions
|
4
|
+
class Steps < Extension
|
5
|
+
def prepare
|
6
|
+
context.data.steps = StepCollection.new(
|
7
|
+
TemplateRegistry.new(context.root),
|
8
|
+
PluginRegistry.new
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
dsl do
|
13
|
+
def group(label = nil, &block)
|
14
|
+
raise "Group does not allow nested in another Group" if context.is_a?(Group)
|
15
|
+
|
16
|
+
context.data.steps.push(Buildkite::Builder::Group.new(label, context.data.steps, &block))
|
17
|
+
end
|
18
|
+
|
19
|
+
def plugin(name, uri, version)
|
20
|
+
context.data.steps.plugins.add(name, uri, version)
|
21
|
+
end
|
22
|
+
|
23
|
+
def block(template = nil, **args, &block)
|
24
|
+
context.data.steps.add(Pipelines::Steps::Block, template, **args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def command(template = nil, **args, &block)
|
28
|
+
context.data.steps.add(Pipelines::Steps::Command, template, **args, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def input(template = nil, **args, &block)
|
32
|
+
context.data.steps.add(Pipelines::Steps::Input, template, **args, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def trigger(template = nil, **args, &block)
|
36
|
+
context.data.steps.add(Pipelines::Steps::Trigger, template, **args, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def skip(template = nil, **args, &block)
|
40
|
+
step = context.data.steps.add(Pipelines::Steps::Skip, template, **args, &block)
|
41
|
+
# A skip step has a nil/noop command.
|
42
|
+
step.command(nil)
|
43
|
+
# Always set the skip attribute if it's in a falsey state.
|
44
|
+
step.skip(true) if !step.get(:skip) || step.skip.empty?
|
45
|
+
step
|
46
|
+
end
|
47
|
+
|
48
|
+
def wait(attributes = {}, &block)
|
49
|
+
step = context.data.steps.add(Pipelines::Steps::Wait, &block)
|
50
|
+
step.wait(nil)
|
51
|
+
attributes.each do |key, value|
|
52
|
+
step.set(key, value)
|
53
|
+
end
|
54
|
+
step
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -11,7 +11,7 @@ module Buildkite
|
|
11
11
|
ACCEPT_HEADER = 'application/vnd.github.v3+json'
|
12
12
|
LINK_HEADER = 'link'
|
13
13
|
NEXT_LINK_REGEX = /<(?<uri>.+)>; rel="next"/.freeze
|
14
|
-
REPO_REGEX = /github\.com(?::|\/)(
|
14
|
+
REPO_REGEX = /github\.com(?::|\/)(.*?)(?:\.git)?\z/.freeze
|
15
15
|
PER_PAGE = 100
|
16
16
|
|
17
17
|
def self.pull_request_files
|
@@ -0,0 +1,41 @@
|
|
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, steps, &block)
|
17
|
+
@label = label
|
18
|
+
@data = Data.new
|
19
|
+
@data.steps = StepCollection.new(
|
20
|
+
steps.templates,
|
21
|
+
steps.plugins
|
22
|
+
)
|
23
|
+
@data.notify = []
|
24
|
+
|
25
|
+
@dsl = Dsl.new(self)
|
26
|
+
@dsl.extend(Extensions::Steps)
|
27
|
+
@dsl.extend(Extensions::Notify)
|
28
|
+
instance_eval(&block)
|
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, &_block)
|
37
|
+
@dsl.public_send(method_name, *_args, &_block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -6,7 +6,7 @@ module Buildkite
|
|
6
6
|
autoload :Abstract, File.expand_path('loaders/abstract', __dir__)
|
7
7
|
autoload :Manifests, File.expand_path('loaders/manifests', __dir__)
|
8
8
|
autoload :Templates, File.expand_path('loaders/templates', __dir__)
|
9
|
-
autoload :
|
9
|
+
autoload :Extensions, File.expand_path('loaders/extensions', __dir__)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -5,17 +5,17 @@ require 'pathname'
|
|
5
5
|
module Buildkite
|
6
6
|
module Builder
|
7
7
|
module Loaders
|
8
|
-
class
|
9
|
-
|
8
|
+
class Extensions < Abstract
|
9
|
+
EXTENSIONS_PATH = Pathname.new('extensions').freeze
|
10
10
|
|
11
11
|
def load
|
12
|
-
|
13
|
-
|
12
|
+
load_extensions_from_path(global_extensions_path)
|
13
|
+
load_extensions_from_path(pipeline_extensions_path)
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
17
17
|
|
18
|
-
def
|
18
|
+
def load_extensions_from_path(path)
|
19
19
|
return unless path.directory?
|
20
20
|
|
21
21
|
path.children.map do |file|
|
@@ -24,12 +24,12 @@ module Buildkite
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
buildkite_path.join(
|
27
|
+
def global_extensions_path
|
28
|
+
buildkite_path.join(EXTENSIONS_PATH)
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
32
|
-
root.join(
|
31
|
+
def pipeline_extensions_path
|
32
|
+
root.join(EXTENSIONS_PATH)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -1,59 +1,56 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'tempfile'
|
3
|
+
require 'yaml'
|
4
|
+
require 'pathname'
|
5
|
+
require 'forwardable'
|
3
6
|
|
4
7
|
module Buildkite
|
5
8
|
module Builder
|
6
|
-
class
|
9
|
+
class Pipeline
|
10
|
+
extend Forwardable
|
7
11
|
include Definition::Helper
|
8
12
|
include LoggingUtils
|
9
13
|
using Rainbow
|
10
14
|
|
11
15
|
PIPELINE_DEFINITION_FILE = Pathname.new('pipeline.rb').freeze
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
attr_reader :
|
16
|
-
|
17
|
+
def_delegator :@extensions, :use
|
18
|
+
|
19
|
+
attr_reader :logger,
|
20
|
+
:root,
|
21
|
+
:artifacts,
|
22
|
+
:plugins,
|
23
|
+
:dsl,
|
24
|
+
:data
|
17
25
|
|
18
26
|
def self.build(root, logger: nil)
|
19
|
-
|
20
|
-
context.build
|
21
|
-
context
|
27
|
+
new(root, logger: logger)
|
22
28
|
end
|
23
29
|
|
24
30
|
def initialize(root, logger: nil)
|
25
31
|
@root = root
|
26
32
|
@logger = logger || Logger.new(File::NULL)
|
27
33
|
@artifacts = []
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
load_pipeline
|
39
|
-
run_processors
|
40
|
-
end
|
41
|
-
end
|
42
|
-
logger.info(results)
|
43
|
-
|
44
|
-
@pipeline
|
34
|
+
@plugins = {}
|
35
|
+
@dsl = Dsl.new(self)
|
36
|
+
@extensions = ExtensionManager.new(self)
|
37
|
+
@data = Data.new
|
38
|
+
|
39
|
+
use(Extensions::Use)
|
40
|
+
use(Extensions::Env)
|
41
|
+
use(Extensions::Notify)
|
42
|
+
use(Extensions::Steps)
|
43
|
+
load_manifests
|
45
44
|
end
|
46
45
|
|
47
46
|
def upload
|
48
|
-
build unless @pipeline
|
49
|
-
|
50
47
|
logger.info '+++ :paperclip: Uploading artifacts'
|
51
48
|
upload_artifacts
|
52
49
|
|
53
50
|
# Upload the pipeline.
|
54
51
|
Tempfile.create(['pipeline', '.yml']) do |file|
|
55
52
|
file.sync = true
|
56
|
-
file.write(
|
53
|
+
file.write(to_yaml)
|
57
54
|
|
58
55
|
logger.info '+++ :paperclip: Uploading pipeline.yml as artifact'
|
59
56
|
Buildkite::Pipelines::Command.artifact!(:upload, file.path)
|
@@ -62,27 +59,29 @@ module Buildkite
|
|
62
59
|
end
|
63
60
|
end
|
64
61
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
62
|
+
def to_h
|
63
|
+
@pipeline_hash ||= begin
|
64
|
+
results = benchmark("\nDone (%s)".color(:springgreen)) do
|
65
|
+
dsl.instance_eval(&pipeline_definition)
|
66
|
+
extensions.build
|
67
|
+
end
|
68
|
+
logger.info(results)
|
69
|
+
# Build the pipeline definition from pipeline data.
|
70
|
+
Pipelines::Helpers.sanitize(data.to_definition)
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
|
-
def
|
74
|
-
|
75
|
-
pipeline.template(name, &asset)
|
76
|
-
end
|
74
|
+
def to_yaml
|
75
|
+
YAML.dump(to_h)
|
77
76
|
end
|
78
77
|
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
private
|
79
|
+
|
80
|
+
attr_reader :extensions
|
82
81
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
82
|
+
def load_manifests
|
83
|
+
Loaders::Manifests.load(root).each do |name, asset|
|
84
|
+
Manifest[name] = asset
|
86
85
|
end
|
87
86
|
end
|
88
87
|
|
@@ -96,10 +95,6 @@ module Buildkite
|
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
99
|
-
def load_pipeline
|
100
|
-
pipeline.instance_eval(&pipeline_definition)
|
101
|
-
end
|
102
|
-
|
103
98
|
def pipeline_definition
|
104
99
|
@pipeline_definition ||= load_definition(root.join(PIPELINE_DEFINITION_FILE), Definition::Pipeline)
|
105
100
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Buildkite
|
2
|
+
module Builder
|
3
|
+
class PluginRegistry
|
4
|
+
def initialize
|
5
|
+
@plugins = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(name, uri, version)
|
9
|
+
name = name.to_s
|
10
|
+
|
11
|
+
if @plugins.key?(name)
|
12
|
+
raise ArgumentError, "Plugin already defined: #{name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
@plugins[name] = [uri, version]
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch(name)
|
19
|
+
@plugins[name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_definition
|
23
|
+
# No-op
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Buildkite
|
2
|
+
module Builder
|
3
|
+
class StepCollection
|
4
|
+
attr_reader :templates
|
5
|
+
attr_reader :plugins
|
6
|
+
attr_reader :steps
|
7
|
+
|
8
|
+
def initialize(templates, plugins)
|
9
|
+
@templates = templates
|
10
|
+
@plugins = plugins
|
11
|
+
@steps = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(*types)
|
15
|
+
types = types.flatten
|
16
|
+
|
17
|
+
@steps.each do |step|
|
18
|
+
if types.include?(step.class.to_sym)
|
19
|
+
yield step
|
20
|
+
end
|
21
|
+
|
22
|
+
if step.is_a?(Group)
|
23
|
+
step.data.steps.each(*types) do |step|
|
24
|
+
yield step
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def add(step_class, template = nil, **args, &block)
|
31
|
+
@steps.push(step_class.new(self, template, **args, &block)).last
|
32
|
+
end
|
33
|
+
|
34
|
+
def push(step)
|
35
|
+
@steps.push(step)
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_definition
|
39
|
+
@steps.map(&:to_h)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Buildkite
|
2
|
+
module Builder
|
3
|
+
class TemplateRegistry
|
4
|
+
def initialize(root)
|
5
|
+
@templates = {}
|
6
|
+
|
7
|
+
Loaders::Templates.load(root).each do |name, asset|
|
8
|
+
@templates[name.to_s] = asset
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(name)
|
13
|
+
return unless name
|
14
|
+
|
15
|
+
unless definition = @templates[name.to_s]
|
16
|
+
raise ArgumentError, "Template not defined: #{name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
definition
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_definition
|
23
|
+
# No-op
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/buildkite/pipelines.rb
CHANGED
@@ -6,7 +6,6 @@ module Buildkite
|
|
6
6
|
autoload :Attributes, File.expand_path('pipelines/attributes', __dir__)
|
7
7
|
autoload :Command, File.expand_path('pipelines/command', __dir__)
|
8
8
|
autoload :Helpers, File.expand_path('pipelines/helpers', __dir__)
|
9
|
-
autoload :Pipeline, File.expand_path('pipelines/pipeline', __dir__)
|
10
9
|
autoload :Plugin, File.expand_path('pipelines/plugin', __dir__)
|
11
10
|
autoload :StepContext, File.expand_path('pipelines/step_context', __dir__)
|
12
11
|
autoload :Steps, File.expand_path('pipelines/steps', __dir__)
|
@@ -84,7 +84,7 @@ module Buildkite
|
|
84
84
|
end
|
85
85
|
|
86
86
|
# Define a helper method that is equivalent to `||=` or `Set#add?`. It will
|
87
|
-
# set the attribute
|
87
|
+
# set the attribute if it hasn't been already set. It will return true/false
|
88
88
|
# for whether or not the value was set.
|
89
89
|
define_method("#{method_name}?") do |*args|
|
90
90
|
if args.empty?
|
@@ -12,7 +12,7 @@ module Buildkite
|
|
12
12
|
raise ArgumentError, "Plugin already used for command step: #{plugin_name}"
|
13
13
|
end
|
14
14
|
|
15
|
-
uri, version =
|
15
|
+
uri, version = step_collection.plugins.fetch(plugin_name)
|
16
16
|
new_plugin = Plugin.new(uri, version, options)
|
17
17
|
@plugins[plugin_name] = new_plugin
|
18
18
|
|
@@ -1,25 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "forwardable"
|
4
|
+
|
3
5
|
module Buildkite
|
4
6
|
module Pipelines
|
5
7
|
module Steps
|
6
8
|
class Abstract
|
9
|
+
extend Forwardable
|
7
10
|
include Attributes
|
8
11
|
|
9
|
-
|
12
|
+
def_delegator :@context, :data
|
13
|
+
|
10
14
|
attr_reader :template
|
15
|
+
attr_reader :step_collection
|
11
16
|
|
12
17
|
def self.to_sym
|
13
18
|
name.split('::').last.downcase.to_sym
|
14
19
|
end
|
15
20
|
|
16
|
-
def initialize(
|
17
|
-
@
|
18
|
-
@template =
|
19
|
-
context = StepContext.new(self, **args)
|
21
|
+
def initialize(step_collection, template_name, **args, &block)
|
22
|
+
@step_collection = step_collection
|
23
|
+
@template = step_collection.templates.find(template_name)
|
24
|
+
@context = StepContext.new(self, **args)
|
20
25
|
|
21
|
-
instance_exec(context, &template) if template
|
22
|
-
instance_exec(context, &block) if block_given?
|
26
|
+
instance_exec(@context, &template) if template
|
27
|
+
instance_exec(@context, &block) if block_given?
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
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:
|
4
|
+
version: 2.0.0.beta1
|
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: 2021-
|
12
|
+
date: 2021-08-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sorted_set
|
@@ -133,21 +133,32 @@ files:
|
|
133
133
|
- lib/buildkite/builder/commands/files.rb
|
134
134
|
- lib/buildkite/builder/commands/preview.rb
|
135
135
|
- lib/buildkite/builder/commands/run.rb
|
136
|
-
- lib/buildkite/builder/
|
136
|
+
- lib/buildkite/builder/data.rb
|
137
137
|
- lib/buildkite/builder/definition.rb
|
138
|
+
- lib/buildkite/builder/dsl.rb
|
139
|
+
- lib/buildkite/builder/extension.rb
|
140
|
+
- lib/buildkite/builder/extension_manager.rb
|
141
|
+
- lib/buildkite/builder/extensions.rb
|
142
|
+
- lib/buildkite/builder/extensions/env.rb
|
143
|
+
- lib/buildkite/builder/extensions/notify.rb
|
144
|
+
- lib/buildkite/builder/extensions/steps.rb
|
145
|
+
- lib/buildkite/builder/extensions/use.rb
|
138
146
|
- lib/buildkite/builder/file_resolver.rb
|
139
147
|
- lib/buildkite/builder/github.rb
|
148
|
+
- lib/buildkite/builder/group.rb
|
140
149
|
- lib/buildkite/builder/loaders.rb
|
141
150
|
- lib/buildkite/builder/loaders/abstract.rb
|
151
|
+
- lib/buildkite/builder/loaders/extensions.rb
|
142
152
|
- lib/buildkite/builder/loaders/manifests.rb
|
143
|
-
- lib/buildkite/builder/loaders/processors.rb
|
144
153
|
- lib/buildkite/builder/loaders/templates.rb
|
145
154
|
- lib/buildkite/builder/logging_utils.rb
|
146
155
|
- lib/buildkite/builder/manifest.rb
|
147
156
|
- lib/buildkite/builder/manifest/rule.rb
|
148
|
-
- lib/buildkite/builder/
|
149
|
-
- lib/buildkite/builder/
|
157
|
+
- lib/buildkite/builder/pipeline.rb
|
158
|
+
- lib/buildkite/builder/plugin_registry.rb
|
150
159
|
- lib/buildkite/builder/rainbow.rb
|
160
|
+
- lib/buildkite/builder/step_collection.rb
|
161
|
+
- lib/buildkite/builder/template_registry.rb
|
151
162
|
- lib/buildkite/env.rb
|
152
163
|
- lib/buildkite/pipelines.rb
|
153
164
|
- lib/buildkite/pipelines/api.rb
|
@@ -164,7 +175,6 @@ files:
|
|
164
175
|
- lib/buildkite/pipelines/helpers/skip.rb
|
165
176
|
- lib/buildkite/pipelines/helpers/soft_fail.rb
|
166
177
|
- lib/buildkite/pipelines/helpers/timeout_in_minutes.rb
|
167
|
-
- lib/buildkite/pipelines/pipeline.rb
|
168
178
|
- lib/buildkite/pipelines/plugin.rb
|
169
179
|
- lib/buildkite/pipelines/step_context.rb
|
170
180
|
- lib/buildkite/pipelines/steps.rb
|
@@ -194,9 +204,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
194
204
|
version: 2.3.0
|
195
205
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
206
|
requirements:
|
197
|
-
- - "
|
207
|
+
- - ">"
|
198
208
|
- !ruby/object:Gem::Version
|
199
|
-
version:
|
209
|
+
version: 1.3.1
|
200
210
|
requirements: []
|
201
211
|
rubygems_version: 3.2.2
|
202
212
|
signing_key:
|
@@ -1,76 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Buildkite
|
4
|
-
module Builder
|
5
|
-
module Processors
|
6
|
-
class Abstract
|
7
|
-
include LoggingUtils
|
8
|
-
using Rainbow
|
9
|
-
|
10
|
-
def self.process(context)
|
11
|
-
new(context).run
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(context)
|
15
|
-
@context = context
|
16
|
-
end
|
17
|
-
|
18
|
-
def run
|
19
|
-
_log_run { process }
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
attr_reader :context
|
25
|
-
|
26
|
-
def process
|
27
|
-
raise NotImplementedError
|
28
|
-
end
|
29
|
-
|
30
|
-
def log
|
31
|
-
context.logger
|
32
|
-
end
|
33
|
-
|
34
|
-
def pipeline
|
35
|
-
context.pipeline
|
36
|
-
end
|
37
|
-
|
38
|
-
def buildkite
|
39
|
-
@buildkite ||= begin
|
40
|
-
unless Buildkite.env
|
41
|
-
raise 'Must be in Buildkite environment to access the Buildkite API'
|
42
|
-
end
|
43
|
-
|
44
|
-
Buildkite::Pipelines::Api.new(Buildkite.env.api_token)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def pipeline_steps(*types)
|
49
|
-
steps = pipeline.steps
|
50
|
-
types = types.flatten
|
51
|
-
steps = steps.select { |step| types.include?(step.class.to_sym) } if types.any?
|
52
|
-
steps
|
53
|
-
end
|
54
|
-
|
55
|
-
def _log_run
|
56
|
-
log.info "\nProcessing ".color(:dimgray) + self.class.name.color(:springgreen)
|
57
|
-
|
58
|
-
results = benchmark('└──'.color(:springgreen) + ' Finished in %s'.color(:dimgray)) do
|
59
|
-
formatter = log.formatter
|
60
|
-
log.formatter = proc do |_severity, _datetime, _progname, msg|
|
61
|
-
'│'.color(:springgreen) + " #{msg}\n"
|
62
|
-
end
|
63
|
-
|
64
|
-
begin
|
65
|
-
yield
|
66
|
-
ensure
|
67
|
-
log.formatter = formatter
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
log.info results
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,140 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'yaml'
|
4
|
-
require 'pathname'
|
5
|
-
|
6
|
-
module Buildkite
|
7
|
-
module Pipelines
|
8
|
-
class Pipeline
|
9
|
-
attr_reader :steps
|
10
|
-
attr_reader :plugins
|
11
|
-
attr_reader :templates
|
12
|
-
|
13
|
-
def initialize(definition = nil, &block)
|
14
|
-
@env = {}
|
15
|
-
@steps = []
|
16
|
-
@plugins = {}
|
17
|
-
@templates = {}
|
18
|
-
@processors = []
|
19
|
-
@notify = []
|
20
|
-
|
21
|
-
instance_eval(&definition) if definition
|
22
|
-
instance_eval(&block) if block_given?
|
23
|
-
end
|
24
|
-
|
25
|
-
[
|
26
|
-
Steps::Block,
|
27
|
-
Steps::Command,
|
28
|
-
Steps::Input,
|
29
|
-
Steps::Trigger,
|
30
|
-
].each do |type|
|
31
|
-
define_method(type.to_sym) do |template = nil, **args, &block|
|
32
|
-
add(type, template, **args, &block)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def notify(*args)
|
37
|
-
if args.empty?
|
38
|
-
@notify
|
39
|
-
elsif args.first.is_a?(Hash)
|
40
|
-
@notify.push(args.first.transform_keys(&:to_s))
|
41
|
-
else
|
42
|
-
raise ArgumentError, 'value must be hash'
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def env(*args)
|
47
|
-
if args.empty?
|
48
|
-
@env
|
49
|
-
elsif args.first.is_a?(Hash)
|
50
|
-
@env.merge!(args.first.transform_keys(&:to_s))
|
51
|
-
else
|
52
|
-
raise ArgumentError, 'value must be hash'
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def skip(template = nil, **args, &block)
|
57
|
-
step = add(Steps::Skip, template, **args, &block)
|
58
|
-
# A skip step has a nil/noop command.
|
59
|
-
step.command(nil)
|
60
|
-
# Always set the skip attribute if it's in a falsey state.
|
61
|
-
step.skip(true) if !step.get(:skip) || step.skip.empty?
|
62
|
-
step
|
63
|
-
end
|
64
|
-
|
65
|
-
def wait(attributes = {}, &block)
|
66
|
-
step = add(Steps::Wait, &block)
|
67
|
-
step.wait(nil)
|
68
|
-
attributes.each do |key, value|
|
69
|
-
step.set(key, value)
|
70
|
-
end
|
71
|
-
step
|
72
|
-
end
|
73
|
-
|
74
|
-
def plugin(name, uri, version)
|
75
|
-
name = name.to_s
|
76
|
-
|
77
|
-
if plugins.key?(name)
|
78
|
-
raise ArgumentError, "Plugin already defined: #{name}"
|
79
|
-
end
|
80
|
-
|
81
|
-
@plugins[name] = [uri, version]
|
82
|
-
end
|
83
|
-
|
84
|
-
def template(name, &definition)
|
85
|
-
name = name.to_s
|
86
|
-
|
87
|
-
if templates.key?(name)
|
88
|
-
raise ArgumentError, "Template already defined: #{name}"
|
89
|
-
elsif !block_given?
|
90
|
-
raise ArgumentError, 'Template definition block must be given'
|
91
|
-
end
|
92
|
-
|
93
|
-
@templates[name.to_s] = definition
|
94
|
-
end
|
95
|
-
|
96
|
-
def processors(*processor_classes)
|
97
|
-
unless processor_classes.empty?
|
98
|
-
@processors.clear
|
99
|
-
|
100
|
-
processor_classes.flatten.each do |processor|
|
101
|
-
unless processor < Buildkite::Builder::Processors::Abstract
|
102
|
-
raise "#{processor} must inherit from Buildkite::Builder::Processors::Abstract"
|
103
|
-
end
|
104
|
-
|
105
|
-
@processors << processor
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
@processors
|
110
|
-
end
|
111
|
-
|
112
|
-
def to_h
|
113
|
-
pipeline = {}
|
114
|
-
pipeline[:env] = env if env.any?
|
115
|
-
pipeline[:notify] = notify if notify.any?
|
116
|
-
pipeline[:steps] = steps.map(&:to_h)
|
117
|
-
|
118
|
-
Helpers.sanitize(pipeline)
|
119
|
-
end
|
120
|
-
|
121
|
-
def to_yaml
|
122
|
-
YAML.dump(to_h)
|
123
|
-
end
|
124
|
-
|
125
|
-
private
|
126
|
-
|
127
|
-
def add(step_class, template = nil, **args, &block)
|
128
|
-
steps.push(step_class.new(self, find_template(template), **args, &block)).last
|
129
|
-
end
|
130
|
-
|
131
|
-
def find_template(name)
|
132
|
-
return unless name
|
133
|
-
|
134
|
-
templates[name.to_s] || begin
|
135
|
-
raise ArgumentError, "Template not defined: #{name}"
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|