capsulecd 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|