capsulecd 1.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 +7 -0
- data/.coveralls.yml +2 -0
- data/.dockerignore +5 -0
- data/.gitignore +95 -0
- data/.rspec +3 -0
- data/.simplecov +9 -0
- data/Dockerfile +16 -0
- data/Dockerfile.chef +26 -0
- data/Dockerfile.javascript +7 -0
- data/Dockerfile.node +7 -0
- data/Dockerfile.python +7 -0
- data/Dockerfile.ruby +4 -0
- data/FEATURES.md +12 -0
- data/Gemfile +26 -0
- data/LICENSE.md +22 -0
- data/README.md +227 -0
- data/Rakefile +43 -0
- data/bin/capsulecd +4 -0
- data/capsulecd.gemspec +27 -0
- data/circle.yml +24 -0
- data/lib/capsulecd/base/common/git_utils.rb +90 -0
- data/lib/capsulecd/base/common/validation_utils.rb +22 -0
- data/lib/capsulecd/base/configuration.rb +151 -0
- data/lib/capsulecd/base/engine.rb +163 -0
- data/lib/capsulecd/base/runner/circleci.rb +37 -0
- data/lib/capsulecd/base/runner/default.rb +38 -0
- data/lib/capsulecd/base/source/github.rb +183 -0
- data/lib/capsulecd/base/transform_engine.rb +62 -0
- data/lib/capsulecd/chef/chef_engine.rb +172 -0
- data/lib/capsulecd/chef/chef_helper.rb +29 -0
- data/lib/capsulecd/cli.rb +64 -0
- data/lib/capsulecd/error.rb +51 -0
- data/lib/capsulecd/javascript/javascript_engine.rb +213 -0
- data/lib/capsulecd/node/node_engine.rb +141 -0
- data/lib/capsulecd/python/python_engine.rb +157 -0
- data/lib/capsulecd/ruby/ruby_engine.rb +191 -0
- data/lib/capsulecd/ruby/ruby_helper.rb +60 -0
- data/lib/capsulecd/version.rb +3 -0
- data/lib/capsulecd.rb +16 -0
- data/logo.svg +1 -0
- data/spec/fixtures/chef/cookbook_analogj_test/CHANGELOG.md +3 -0
- data/spec/fixtures/chef/cookbook_analogj_test/Gemfile +18 -0
- data/spec/fixtures/chef/cookbook_analogj_test/LICENSE +21 -0
- data/spec/fixtures/chef/cookbook_analogj_test/README.md +13 -0
- data/spec/fixtures/chef/cookbook_analogj_test/Rakefile +1 -0
- data/spec/fixtures/chef/cookbook_analogj_test/Thorfile +12 -0
- data/spec/fixtures/chef/cookbook_analogj_test/chefignore +94 -0
- data/spec/fixtures/chef/cookbook_analogj_test/metadata.rb +5 -0
- data/spec/fixtures/chef/cookbook_analogj_test/recipes/default.rb +6 -0
- data/spec/fixtures/incorrect_configuration.yml +4 -0
- data/spec/fixtures/javascript/javascript_analogj_test/LICENSE +21 -0
- data/spec/fixtures/javascript/javascript_analogj_test/README.md +2 -0
- data/spec/fixtures/javascript/javascript_analogj_test/package.json +19 -0
- data/spec/fixtures/node/npm_analogj_test/LICENSE +21 -0
- data/spec/fixtures/node/npm_analogj_test/README.md +2 -0
- data/spec/fixtures/node/npm_analogj_test/package.json +19 -0
- data/spec/fixtures/python/pip_analogj_test/LICENSE +21 -0
- data/spec/fixtures/python/pip_analogj_test/MANIFEST.in +1 -0
- data/spec/fixtures/python/pip_analogj_test/README.md +1 -0
- data/spec/fixtures/python/pip_analogj_test/VERSION +1 -0
- data/spec/fixtures/python/pip_analogj_test/setup.cfg +5 -0
- data/spec/fixtures/python/pip_analogj_test/setup.py +80 -0
- data/spec/fixtures/python/pip_analogj_test/tox.ini +14 -0
- data/spec/fixtures/ruby/gem_analogj_test/Gemfile +4 -0
- data/spec/fixtures/ruby/gem_analogj_test/LICENSE.txt +21 -0
- data/spec/fixtures/ruby/gem_analogj_test/README.md +41 -0
- data/spec/fixtures/ruby/gem_analogj_test/Rakefile +6 -0
- data/spec/fixtures/ruby/gem_analogj_test/bin/console +14 -0
- data/spec/fixtures/ruby/gem_analogj_test/bin/setup +8 -0
- data/spec/fixtures/ruby/gem_analogj_test/gem_analogj_test.gemspec +25 -0
- data/spec/fixtures/ruby/gem_analogj_test/lib/gem_analogj_test/version.rb +3 -0
- data/spec/fixtures/ruby/gem_analogj_test/lib/gem_analogj_test.rb +5 -0
- data/spec/fixtures/ruby/gem_analogj_test/spec/gem_analogj_test_spec.rb +7 -0
- data/spec/fixtures/ruby/gem_analogj_test/spec/spec_helper.rb +2 -0
- data/spec/fixtures/ruby/gem_analogj_test-0.1.4.gem +0 -0
- data/spec/fixtures/sample_chef_configuration.yml +8 -0
- data/spec/fixtures/sample_configuration.yml +7 -0
- data/spec/fixtures/sample_global_configuration.yml +23 -0
- data/spec/fixtures/sample_node_configuration.yml +7 -0
- data/spec/fixtures/sample_python_configuration.yml +8 -0
- data/spec/fixtures/sample_repo_configuration.yml +22 -0
- data/spec/fixtures/sample_ruby_configuration.yml +5 -0
- data/spec/fixtures/vcr_cassettes/chef_build_step.yml +636 -0
- data/spec/fixtures/vcr_cassettes/gem_build_step.yml +653 -0
- data/spec/fixtures/vcr_cassettes/gem_build_step_without_version_rb.yml +653 -0
- data/spec/fixtures/vcr_cassettes/integration_chef.yml +1399 -0
- data/spec/fixtures/vcr_cassettes/integration_node.yml +1388 -0
- data/spec/fixtures/vcr_cassettes/integration_python.yml +1388 -0
- data/spec/fixtures/vcr_cassettes/integration_ruby.yml +1377 -0
- data/spec/fixtures/vcr_cassettes/node_build_step.yml +647 -0
- data/spec/fixtures/vcr_cassettes/pip_build_step.yml +653 -0
- data/spec/lib/capsulecd/base/configuration_spec.rb +75 -0
- data/spec/lib/capsulecd/base/engine_spec.rb +51 -0
- data/spec/lib/capsulecd/base/source/github_spec.rb +253 -0
- data/spec/lib/capsulecd/base/transform_engine_spec.rb +55 -0
- data/spec/lib/capsulecd/chef/chef_engine_spec.rb +114 -0
- data/spec/lib/capsulecd/cli_spec.rb +57 -0
- data/spec/lib/capsulecd/node/node_engine_spec.rb +113 -0
- data/spec/lib/capsulecd/python/python_engine_spec.rb +118 -0
- data/spec/lib/capsulecd/ruby/ruby_engine_spec.rb +128 -0
- data/spec/spec_helper.rb +105 -0
- data/spec/support/file_system.rb +21 -0
- data/spec/support/package_types.rb +11 -0
- metadata +281 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require 'git'
|
|
2
|
+
require 'mkgitignore'
|
|
3
|
+
|
|
4
|
+
module CapsuleCD
|
|
5
|
+
class GitUtils
|
|
6
|
+
def self.clone(parent_path, repository_name, git_remote)
|
|
7
|
+
repo_path = File.expand_path("#{parent_path}/#{repository_name}/")
|
|
8
|
+
if !File.directory?(repo_path)
|
|
9
|
+
FileUtils.mkdir_p(repo_path)
|
|
10
|
+
else
|
|
11
|
+
fail 'the repository path already exists, this should never happen'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
repo = Git.clone(git_remote, '', path: repo_path)
|
|
15
|
+
repo.config('user.name', 'CapsuleCD')
|
|
16
|
+
repo.config('user.email', 'CapsuleCD@users.noreply.github.com')
|
|
17
|
+
repo.dir.to_s
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.fetch(repo_path, remote_ref, local_branch)
|
|
21
|
+
repo = Git.open(repo_path)
|
|
22
|
+
repo.fetch(['origin', "#{remote_ref}:#{local_branch}"])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.checkout(repo_path, branch)
|
|
26
|
+
repo = Git.open(repo_path)
|
|
27
|
+
repo.checkout(branch)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.commit(repo_path, message, _all = true)
|
|
31
|
+
repo = Git.open(repo_path)
|
|
32
|
+
repo.add(all: true)
|
|
33
|
+
repo.commit_all(message)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.tag(repo_path, version)
|
|
37
|
+
repo = Git.open(repo_path)
|
|
38
|
+
repo.add_tag(version)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.push(repo_path, local_branch, remote_branch)
|
|
42
|
+
repo = Git.open(repo_path)
|
|
43
|
+
repo.push('origin', "#{local_branch}:#{remote_branch}", tags: true)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.pull(repo_path)
|
|
47
|
+
repo = Git.open(repo_path)
|
|
48
|
+
repo.pull
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# gets the commit of the latest tag on current branch
|
|
52
|
+
def self.get_latest_tag_commit(repo_path)
|
|
53
|
+
repo = Git.open(repo_path)
|
|
54
|
+
tag_name = repo.describe(nil,:abbrev => 0, :exact_match => true)
|
|
55
|
+
|
|
56
|
+
#we're dealing with annotated tags, which have thier own git commit, which causes issues with the github release api
|
|
57
|
+
# so we're manually creating a Git Object with the data we need (.sha and .name)
|
|
58
|
+
tag_sha = repo.tag(tag_name).log.first.sha
|
|
59
|
+
|
|
60
|
+
Git::Object::Tag.new(repo,tag_sha, tag_name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.generate_changelog(repo_path, base_sha, head_sha, full_name)
|
|
64
|
+
repo = Git.open(repo_path)
|
|
65
|
+
markdown = "Timestamp | SHA | Message | Author \n"
|
|
66
|
+
markdown += "------------- | ------------- | ------------- | ------------- \n"
|
|
67
|
+
repo.log.between(base_sha, head_sha).each do |commit|
|
|
68
|
+
markdown += "#{commit.date.strftime('%Y-%m-%dT%H:%M:%SZ')} | [`#{commit.sha.slice 0..8}`](https://github.com/#{full_name}/commit/#{commit.sha}) | #{commit.message.gsub('|', '!').gsub(/[\n]+/,' ') || '--'} | #{commit.author.name} \n"
|
|
69
|
+
end
|
|
70
|
+
markdown
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.create_gitignore(repo_path, ignore_types)
|
|
74
|
+
#store current working directory, and change to the cookbook
|
|
75
|
+
wd = Dir.getwd
|
|
76
|
+
Dir.chdir(repo_path)
|
|
77
|
+
|
|
78
|
+
begin
|
|
79
|
+
#download gitignore templates and write them
|
|
80
|
+
templates = Mkgitignore::searchForTemplatesWithNames(ignore_types)
|
|
81
|
+
gitignore = String.new
|
|
82
|
+
templates.each { |t| gitignore += Mkgitignore::downloadFromURL(t["url"], t["name"]) }
|
|
83
|
+
Mkgitignore::writeGitignore(gitignore, true)
|
|
84
|
+
ensure
|
|
85
|
+
#restore previous working dir
|
|
86
|
+
Dir.chdir(wd)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'capsulecd'
|
|
2
|
+
module CapsuleCD
|
|
3
|
+
class ValidationUtils
|
|
4
|
+
def self.validate_repo_payload(repo_payload)
|
|
5
|
+
unless repo_payload['sha']
|
|
6
|
+
fail CapsuleCD::Error::SourcePayloadFormatError, 'Incorrectly formatted payload, missing "sha1" key'
|
|
7
|
+
end
|
|
8
|
+
unless repo_payload['ref']
|
|
9
|
+
fail CapsuleCD::Error::SourcePayloadFormatError, 'Incorrectly formatted payload, missing "ref" key'
|
|
10
|
+
end
|
|
11
|
+
unless repo_payload['repo']
|
|
12
|
+
fail CapsuleCD::Error::SourcePayloadFormatError, 'Incorrectly formatted payload, missing "repo" key'
|
|
13
|
+
end
|
|
14
|
+
unless repo_payload['repo']['clone_url']
|
|
15
|
+
fail CapsuleCD::Error::SourcePayloadFormatError, 'Incorrectly formatted payload, missing "clone_url" key'
|
|
16
|
+
end
|
|
17
|
+
unless repo_payload['repo']['name']
|
|
18
|
+
fail CapsuleCD::Error::SourcePayloadFormatError, 'Incorrectly formatted payload, missing "name" key'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require 'erb'
|
|
3
|
+
require 'base64'
|
|
4
|
+
module CapsuleCD
|
|
5
|
+
class Configuration
|
|
6
|
+
# Order of inheritance: file <- environment <- cli options
|
|
7
|
+
# <- means 'overridden by', eg. file overridden by environment vars
|
|
8
|
+
# @param [String] config_path The path to the configuration file
|
|
9
|
+
def initialize(options={})
|
|
10
|
+
@options = options
|
|
11
|
+
@config_path = @options[:config_file]
|
|
12
|
+
|
|
13
|
+
populate_defaults
|
|
14
|
+
populate_system_config_file
|
|
15
|
+
populate_runner_overrides
|
|
16
|
+
populate_env_overrides
|
|
17
|
+
populate_cli_overrides
|
|
18
|
+
standardize_settings
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Cli config, shouldnt be set via environmental variables (will be overridden)
|
|
22
|
+
attr_reader :package_type
|
|
23
|
+
attr_reader :source
|
|
24
|
+
attr_reader :runner
|
|
25
|
+
attr_reader :dry_run
|
|
26
|
+
|
|
27
|
+
# General config
|
|
28
|
+
attr_reader :config_path
|
|
29
|
+
attr_reader :configuration
|
|
30
|
+
|
|
31
|
+
# Source config (any credentials added here should also be added to the spec_helper.rb VCR config)
|
|
32
|
+
attr_reader :source_git_parent_path
|
|
33
|
+
attr_reader :source_github_api_endpoint
|
|
34
|
+
attr_reader :source_github_web_endpoint
|
|
35
|
+
attr_reader :source_github_access_token
|
|
36
|
+
|
|
37
|
+
# Runner config
|
|
38
|
+
attr_reader :runner_pull_request
|
|
39
|
+
attr_reader :runner_sha
|
|
40
|
+
attr_reader :runner_branch
|
|
41
|
+
attr_reader :runner_clone_url
|
|
42
|
+
attr_reader :runner_repo_full_name
|
|
43
|
+
attr_reader :runner_repo_name
|
|
44
|
+
|
|
45
|
+
# Package auth/config (any credentials added here should also be added to the spec_helper.rb VCR config)
|
|
46
|
+
attr_reader :chef_supermarket_username
|
|
47
|
+
attr_reader :npm_auth_token
|
|
48
|
+
attr_reader :pypi_username
|
|
49
|
+
attr_reader :pypi_password
|
|
50
|
+
attr_reader :chef_supermarket_type
|
|
51
|
+
attr_reader :rubygems_api_key
|
|
52
|
+
def chef_supermarket_key
|
|
53
|
+
@chef_supermarket_key.to_s.empty? ? nil : Base64.strict_decode64(@chef_supermarket_key)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Engine config
|
|
57
|
+
attr_reader :engine_disable_test
|
|
58
|
+
attr_reader :engine_disable_minification
|
|
59
|
+
attr_reader :engine_disable_lint
|
|
60
|
+
attr_reader :engine_disable_coverage
|
|
61
|
+
attr_reader :engine_cmd_test
|
|
62
|
+
attr_reader :engine_cmd_minification
|
|
63
|
+
attr_reader :engine_cmd_lint
|
|
64
|
+
attr_reader :engine_cmd_coverage
|
|
65
|
+
attr_reader :engine_version_bump_type
|
|
66
|
+
|
|
67
|
+
def populate_repo_config_file(repo_local_path)
|
|
68
|
+
repo_config_file_path = repo_local_path + '/capsule.yml'
|
|
69
|
+
load_config_file(repo_config_file_path)
|
|
70
|
+
populate_runner_overrides
|
|
71
|
+
populate_env_overrides
|
|
72
|
+
populate_cli_overrides
|
|
73
|
+
standardize_settings
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# The raw parsed configuration file, system level, a repo level configuration file will override settings in this file.
|
|
77
|
+
def populate_system_config_file
|
|
78
|
+
load_config_file(@config_path)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
# These are defaults for engine settings. They can be overridden via configuration files or env variables
|
|
83
|
+
def populate_defaults
|
|
84
|
+
@engine_version_bump_type = :patch # can be :major, :minor, :patch
|
|
85
|
+
@chef_supermarket_type = 'Other'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def load_config_file(path)
|
|
89
|
+
if !path || !File.exist?(path)
|
|
90
|
+
puts 'The configuration file could not be found. Using defaults'
|
|
91
|
+
return
|
|
92
|
+
end
|
|
93
|
+
file = File.open(path).read
|
|
94
|
+
unserialize(file)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def populate_runner_overrides
|
|
99
|
+
@runner = :circleci unless ENV['CIRCLECI'].to_s.empty?
|
|
100
|
+
populate_runner
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def populate_runner
|
|
104
|
+
if (@runner == :circleci)
|
|
105
|
+
# parse the PR# from the environment variable, eg. https://github.com/AnalogJ/cookbook_analogj_test/pull/9
|
|
106
|
+
@runner_pull_request ||= File.basename(URI.parse(ENV['CI_PULL_REQUEST']).path).to_i # => baz
|
|
107
|
+
@runner_sha ||= ENV['CIRCLE_SHA1']
|
|
108
|
+
@runner_branch ||= ENV['CIRCLE_BRANCH']
|
|
109
|
+
@runner_clone_url ||= 'https://github.com/' + ENV['CIRCLE_PROJECT_USERNAME'] + '/' + ENV['CIRCLE_PROJECT_REPONAME'] + '.git'
|
|
110
|
+
@runner_repo_name ||= ENV['CIRCLE_PROJECT_REPONAME']
|
|
111
|
+
@runner_repo_full_name ||= ENV['CIRCLE_PROJECT_USERNAME'] + '/' + ENV['CIRCLE_PROJECT_REPONAME']
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def populate_env_overrides
|
|
116
|
+
# override config file with env variables.
|
|
117
|
+
ENV.each do|key, value|
|
|
118
|
+
config_key = key.dup
|
|
119
|
+
if config_key.start_with?('CAPSULE_') && !value.to_s.empty?
|
|
120
|
+
config_key.slice!('CAPSULE_')
|
|
121
|
+
config_key.downcase!
|
|
122
|
+
|
|
123
|
+
# override instance variable
|
|
124
|
+
instance_variable_set('@' + config_key, value)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def populate_cli_overrides
|
|
130
|
+
# then override with cli options
|
|
131
|
+
@options.each do|key, value|
|
|
132
|
+
instance_variable_set('@' + key.to_s, value)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# certain settings are symbols, so make sure that any settings that are specified via a string are converted to the correct type.
|
|
137
|
+
def standardize_settings
|
|
138
|
+
# set types if missing
|
|
139
|
+
@engine_version_bump_type = @engine_version_bump_type.to_sym if @engine_version_bump_type.is_a? String
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def unserialize(string)
|
|
143
|
+
obj = YAML.load(string)
|
|
144
|
+
obj.keys.each do |key|
|
|
145
|
+
next if %w(source_configure source_process_pull_request_payload source_process_push_payload runner_retrieve_payload build_step test_step package_step source_release release_step).include?(key)
|
|
146
|
+
instance_variable_set('@' + key, obj[key])
|
|
147
|
+
end
|
|
148
|
+
obj
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
require_relative 'runner/default'
|
|
2
|
+
require_relative 'configuration'
|
|
3
|
+
require 'pp'
|
|
4
|
+
module CapsuleCD
|
|
5
|
+
class Engine
|
|
6
|
+
attr_reader :config
|
|
7
|
+
|
|
8
|
+
def initialize(options)
|
|
9
|
+
@config = CapsuleCD::Configuration.new(options)
|
|
10
|
+
if @config.source == :github
|
|
11
|
+
require_relative 'source/github'
|
|
12
|
+
self.class.send(:include, CapsuleCD::Source::Github)
|
|
13
|
+
else
|
|
14
|
+
fail CapsuleCD::Error::SourceUnspecifiedError, 'No source defined.'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
if @config.runner == :circleci
|
|
18
|
+
require_relative 'runner/circleci'
|
|
19
|
+
self.class.send(:include, CapsuleCD::Runner::Circleci)
|
|
20
|
+
else
|
|
21
|
+
self.class.send(:include, CapsuleCD::Runner::Default)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def start
|
|
26
|
+
# start the source, and whatever work needs to be done there.
|
|
27
|
+
# MUST set @source_git_parent_path
|
|
28
|
+
# MUST set @source_client
|
|
29
|
+
pre_source_configure
|
|
30
|
+
source_configure
|
|
31
|
+
post_source_configure
|
|
32
|
+
|
|
33
|
+
# runner must determine if this is a pull request or a push.
|
|
34
|
+
# if it's a pull request the runner must retrieve the pull request payload and return it
|
|
35
|
+
# if its a push, the runner must retrieve the push payload and return it
|
|
36
|
+
# the variable @runner_is_pullrequest will be true if a pull request was created.
|
|
37
|
+
# MUST set runner_is_pullrequest
|
|
38
|
+
# REQUIRES source_client
|
|
39
|
+
pre_runner_retrieve_payload
|
|
40
|
+
payload = runner_retrieve_payload(@options)
|
|
41
|
+
post_runner_retrieve_payload
|
|
42
|
+
|
|
43
|
+
if @runner_is_pullrequest
|
|
44
|
+
# all capsule CD processing will be kicked off via a payload. In this case the payload is the pull request data.
|
|
45
|
+
# should check if the pull request opener even has permissions to create a release.
|
|
46
|
+
# all sources should process the payload by downloading a git repository that contains the master branch merged with the test branch
|
|
47
|
+
# MUST set source_git_local_path
|
|
48
|
+
# MUST set source_git_local_branch
|
|
49
|
+
# MUST set source_git_base_info
|
|
50
|
+
# MUST set source_git_head_info
|
|
51
|
+
# REQUIRES source_client
|
|
52
|
+
pre_source_process_pull_request_payload
|
|
53
|
+
source_process_pull_request_payload(payload)
|
|
54
|
+
post_source_process_pull_request_payload
|
|
55
|
+
else
|
|
56
|
+
# start processing the payload, which should result in a local git repository that we
|
|
57
|
+
# can begin to test. Since this is a push, no packaging is required
|
|
58
|
+
# MUST set source_git_local_path
|
|
59
|
+
# MUST set source_git_local_branch
|
|
60
|
+
# MUST set source_git_head_info
|
|
61
|
+
# REQUIRES source_client
|
|
62
|
+
pre_source_process_push_payload
|
|
63
|
+
source_process_push_payload(payload)
|
|
64
|
+
post_source_process_push_payload
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# now that the payload has been processed we can begin by building the code.
|
|
68
|
+
# this may be creating missing files/default structure, compilation, version bumping, etc.
|
|
69
|
+
|
|
70
|
+
source_notify('build') do
|
|
71
|
+
pre_build_step
|
|
72
|
+
build_step
|
|
73
|
+
post_build_step
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# this step should download dependencies, run the package test runner(s) (eg. npm test, rake test, kitchen test)
|
|
77
|
+
# REQUIRES @config.engine_cmd_test
|
|
78
|
+
# REQUIRES @config.engine_disable_test
|
|
79
|
+
source_notify('test') do
|
|
80
|
+
pre_test_step
|
|
81
|
+
test_step
|
|
82
|
+
post_test_step
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# this step should commit any local changes and create a git tag. Nothing should be pushed to remote repository
|
|
86
|
+
source_notify('package') do
|
|
87
|
+
pre_package_step
|
|
88
|
+
package_step
|
|
89
|
+
post_package_step
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
if @runner_is_pullrequest
|
|
93
|
+
# this step should push the release to the package repository (ie. npm, chef supermarket, rubygems)
|
|
94
|
+
source_notify('release') do
|
|
95
|
+
pre_release_step
|
|
96
|
+
release_step
|
|
97
|
+
post_release_step
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# this step should push the merged, tested and version updated code up to the source code repository
|
|
101
|
+
# this step should also do any source specific releases (github release, asset uploading, etc)
|
|
102
|
+
source_notify('source release') do
|
|
103
|
+
pre_source_release
|
|
104
|
+
source_release
|
|
105
|
+
post_source_release
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# rescue => ex #TODO if you enable this rescue block, hooks stop working.
|
|
110
|
+
# TODO: it shouldnt be required anylonger because source_notify will handle rescueing the failures.
|
|
111
|
+
# puts ex
|
|
112
|
+
#
|
|
113
|
+
# self.run_hook :pre_source_process_failure, ex
|
|
114
|
+
# source_process_failure(ex)
|
|
115
|
+
# self.run_hook :post_source_process_failure, ex
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# base methods
|
|
119
|
+
def pre_source_configure; puts 'pre_source_configure'; end
|
|
120
|
+
def post_source_configure; puts 'post_source_configure'; end
|
|
121
|
+
def pre_source_process_pull_request_payload; puts 'pre_source_process_pull_request_payload'; end
|
|
122
|
+
def post_source_process_pull_request_payload; puts 'post_source_process_pull_request_payload'; end
|
|
123
|
+
def pre_source_process_push_payload; puts 'pre_source_process_push_payload'; end
|
|
124
|
+
def post_source_process_push_payload; puts 'post_source_process_push_payload'; end
|
|
125
|
+
def pre_source_release; puts 'pre_source_release'; end
|
|
126
|
+
def post_source_release; puts 'post_source_release'; end
|
|
127
|
+
|
|
128
|
+
def pre_runner_retrieve_payload; puts 'pre_runner_retrieve_payload'; end
|
|
129
|
+
def post_runner_retrieve_payload; puts 'post_runner_retrieve_payload'; end
|
|
130
|
+
|
|
131
|
+
def pre_build_step; puts 'pre_build_step'; end
|
|
132
|
+
def build_step; puts 'build_step'; end
|
|
133
|
+
def post_build_step; puts 'post_build_step'; end
|
|
134
|
+
def pre_test_step; puts 'pre_test_step'; end
|
|
135
|
+
def test_step; puts 'test_step'; end
|
|
136
|
+
def post_test_step; puts 'post_test_step'; end
|
|
137
|
+
def pre_package_step; puts 'pre_package_step'; end
|
|
138
|
+
def package_step; puts 'package_step'; end
|
|
139
|
+
def post_package_step; puts 'post_package_step'; end
|
|
140
|
+
def pre_release_step; puts 'pre_release_step'; end
|
|
141
|
+
def release_step; puts 'release_step'; end
|
|
142
|
+
def post_release_step; puts 'post_release_step'; end
|
|
143
|
+
|
|
144
|
+
protected
|
|
145
|
+
|
|
146
|
+
# determine which segment of the semvar version to bump/increment. The default (as specified in CapsuleCD::Configuration is :patch)
|
|
147
|
+
def bump_version(current_version)
|
|
148
|
+
next_version = current_version
|
|
149
|
+
|
|
150
|
+
if @config.engine_version_bump_type == :major
|
|
151
|
+
next_version.major = next_version.major + 1
|
|
152
|
+
next_version.minor = 0
|
|
153
|
+
next_version.patch = 0
|
|
154
|
+
elsif @config.engine_version_bump_type == :minor
|
|
155
|
+
next_version.minor = next_version.minor + 1
|
|
156
|
+
next_version.patch = 0
|
|
157
|
+
else
|
|
158
|
+
next_version.patch = next_version.patch + 1
|
|
159
|
+
end
|
|
160
|
+
return next_version
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
module CapsuleCD
|
|
3
|
+
module Runner
|
|
4
|
+
module Circleci
|
|
5
|
+
def runner_retrieve_payload(_options)
|
|
6
|
+
puts 'circleci runner_retrieve_payload'
|
|
7
|
+
|
|
8
|
+
# circleci only works with github, no need to parse @options[:source]
|
|
9
|
+
# here are the environmental variables we need to handle:
|
|
10
|
+
# https://circleci.com/docs/environment-variables
|
|
11
|
+
|
|
12
|
+
if @config.runner_pull_request.to_s.empty?
|
|
13
|
+
puts 'This is not a pull request. No automatic continuous deployment processing required. Continuous Integration testing will continue.'
|
|
14
|
+
@runner_is_pullrequest = false
|
|
15
|
+
# make this as similar to the pull request payload as possible.
|
|
16
|
+
payload = {
|
|
17
|
+
'head' => {
|
|
18
|
+
'sha' => @config.runner_sha,
|
|
19
|
+
'ref' => @config.runner_branch,
|
|
20
|
+
'repo' => {
|
|
21
|
+
'clone_url' => @config.runner_clone_url,
|
|
22
|
+
'name' => @config.runner_repo_name,
|
|
23
|
+
'full_name' => @config.runner_repo_full_name
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
payload
|
|
29
|
+
else
|
|
30
|
+
@runner_is_pullrequest = true
|
|
31
|
+
pull_request_number = @config.runner_pull_request.to_i
|
|
32
|
+
@source_client.pull_request(@config.runner_repo_full_name, pull_request_number)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module CapsuleCD
|
|
2
|
+
module Runner
|
|
3
|
+
module Default
|
|
4
|
+
# TODO: this needs to be fleshed out/working. ie. Jenkins, Bamboo, GoCD, Drone, other self hosted services
|
|
5
|
+
def runner_retrieve_payload(_opts)
|
|
6
|
+
puts 'default runner_retrieve_payload'
|
|
7
|
+
|
|
8
|
+
# capsulecd only works with github, no need to parse @options[:source]
|
|
9
|
+
# since we're the default handler, we have to verify that the required configuration options are available
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if @config.runner_pull_request.to_s.empty?
|
|
14
|
+
puts 'This is not a pull request. No automatic continuous deployment processing required. Continuous Integration testing will continue.'
|
|
15
|
+
@runner_is_pullrequest = false
|
|
16
|
+
# make this as similar to the pull request payload as possible.
|
|
17
|
+
payload = {
|
|
18
|
+
'head' => {
|
|
19
|
+
'sha' => @config.runner_sha,
|
|
20
|
+
'ref' => @config.runner_branch,
|
|
21
|
+
'repo' => {
|
|
22
|
+
'clone_url' => @config.runner_clone_url,
|
|
23
|
+
'name' => @config.runner_repo_name,
|
|
24
|
+
'full_name' => @config.runner_repo_full_name
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
payload
|
|
30
|
+
else
|
|
31
|
+
@runner_is_pullrequest = true
|
|
32
|
+
pull_request_number = @config.runner_pull_request.to_i
|
|
33
|
+
@source_client.pull_request(@config.runner_repo_full_name, pull_request_number)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|