construi 0.35.2 → 0.36.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +0 -1
- data/README.md +2 -124
- data/Rakefile +1 -2
- data/bin/construi +0 -1
- data/construi.gemspec +17 -12
- data/construi.yml +10 -4
- data/construi/release/script.sh +16 -8
- data/construi/site/Dockerfile +6 -0
- data/construi/site/run.sh +35 -0
- data/lib/construi.rb +1 -1
- data/lib/construi/config.rb +90 -82
- data/lib/construi/container.rb +14 -6
- data/lib/construi/image.rb +3 -3
- data/lib/construi/runner.rb +8 -5
- data/lib/construi/target.rb +1 -1
- data/lib/construi/version.rb +1 -1
- data/site/_config.yml +18 -0
- data/site/_layouts/default.html +79 -0
- data/site/css/main.css +11 -0
- data/site/index.md +161 -0
- data/spec/lib/construi/config_spec.rb +42 -0
- data/spec/lib/construi/container_spec.rb +8 -4
- data/spec/lib/construi/image_spec.rb +9 -7
- data/spec/lib/construi/runner_spec.rb +1 -1
- data/spec/spec_helper.rb +10 -10
- metadata +102 -17
- data/spec/lib/container_spec.rb +0 -132
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
[![Gem](https://img.shields.io/gem/v/construi.svg?style=plastic)](https://rubygems.org/gems/construi)
|
4
4
|
[![Build Status](http://jenkins.mylonelybear.org/buildStatus/icon?job=construi-develop&style=plastic)](http://jenkins.mylonelybear.org/job/construi-develop/)
|
5
|
-
[![Gemnasium](https://img.shields.io/gemnasium/mathiasbynens/he.svg?style=plastic)](https://gemnasium.com/lstephen/construi)
|
6
|
-
[![Code Climate](https://img.shields.io/codeclimate/github/lstephen/construi.svg?style=plastic)](https://codeclimate.com/github/lstephen/construi)
|
7
|
-
[![Coveralls](https://img.shields.io/coveralls/lstephen/construi/origin/develop.svg?style=plastic)](https://coveralls.io/r/lstephen/construi)
|
8
5
|
|
9
6
|
Construi allows you to use [Docker](http://www.docker.com) containers as your build environment.
|
10
7
|
This allows a consistent and recreatable build environment on any machine running Construi
|
@@ -23,126 +20,7 @@ It can be installed as a Gem.
|
|
23
20
|
> gem install construi
|
24
21
|
```
|
25
22
|
|
26
|
-
##
|
27
|
-
|
28
|
-
Construi requires that a `construi.yml` file be present in the root directory of your project.
|
29
|
-
Targets can then be run by specifying them on the command line. For example:
|
30
|
-
|
31
|
-
```
|
32
|
-
> construi build
|
33
|
-
> construi build install
|
34
|
-
```
|
35
|
-
|
36
|
-
Construi will create a Docker container with the project directory as a volume.
|
37
|
-
It will then run the commands configured for the given targets.
|
38
|
-
|
39
|
-
## The Construi File
|
40
|
-
|
41
|
-
As a minimal `construi.yml` requires an image and a target to be configured.
|
42
|
-
For example a simple configuration for a Java 8 project built with Maven could be:
|
43
|
-
|
44
|
-
```
|
45
|
-
image: maven:3-jdk-8
|
46
|
-
|
47
|
-
targets:
|
48
|
-
install: mvn install
|
49
|
-
```
|
50
|
-
|
51
|
-
Construi is built using itself, so it's
|
52
|
-
[`construi.yml`](https://github.com/lstephen/construi/blob/develop/construi.yml)
|
53
|
-
can be used as an example also.
|
54
|
-
|
55
|
-
### Image
|
56
|
-
|
57
|
-
Specifies an image to be pulled that will be used as the build environment.
|
58
|
-
It can also be given on a per target basis.
|
59
|
-
|
60
|
-
```
|
61
|
-
image: maven:3-jdk-7
|
62
|
-
|
63
|
-
targets:
|
64
|
-
install: mvn install
|
65
|
-
|
66
|
-
test-java-8:
|
67
|
-
image: maven:3-jdk-8
|
68
|
-
run: mvn verify
|
69
|
-
```
|
70
|
-
|
71
|
-
### Build
|
72
|
-
|
73
|
-
Specifies a directory containing a `Dockerfile`.
|
74
|
-
Construi will build a Docker container based on that `Dockerfile` and use it as the build
|
75
|
-
environment.
|
76
|
-
Can be used as an alternative to providing an image.
|
77
|
-
Can also be given on a per target basis.
|
78
|
-
|
79
|
-
```
|
80
|
-
build: etc/build_environment
|
81
|
-
|
82
|
-
targets:
|
83
|
-
build:
|
84
|
-
- mvn install
|
85
|
-
- /usr/local/bin/custom_installed_command.sh
|
86
|
-
```
|
87
|
-
|
88
|
-
### Environment
|
89
|
-
|
90
|
-
Declares environment variables that will be passed through or set in the build environment.
|
91
|
-
If no value is provided then the value from the host environment will be used.
|
92
|
-
In this example `NEXUS_SERVER_URL` will be set as provided, while `NEXUS_USERNAME` and
|
93
|
-
`NEXUS_PASSWORD` will be retrieved from the host.
|
94
|
-
|
95
|
-
```
|
96
|
-
image: maven:3-jdk-7
|
97
|
-
|
98
|
-
environment:
|
99
|
-
- NEXUS_SERVER_URL=http://nexus.example.com
|
100
|
-
- NEXUS_USERNAME
|
101
|
-
- NEXUS_PASSWORD
|
102
|
-
targets:
|
103
|
-
build: mvn install
|
104
|
-
```
|
105
|
-
|
106
|
-
### Files
|
107
|
-
|
108
|
-
Declares files to be copied into the build environment before the build is run.
|
109
|
-
Also allows setting of permissions.
|
110
|
-
Can be used on a per target basis.
|
111
|
-
|
112
|
-
```
|
113
|
-
image: maven:3-jdk-7
|
114
|
-
|
115
|
-
files:
|
116
|
-
- etc/maven-settings.xml:/home/root/.m2/settings.xml
|
117
|
-
|
118
|
-
targets:
|
119
|
-
deploy:
|
120
|
-
files:
|
121
|
-
- $GIT_SSH_KEY:/home/root/.ssh/id_rsa:0600
|
122
|
-
run: scripts/construi/deploy.sh
|
123
|
-
```
|
124
|
-
|
125
|
-
### Targets
|
126
|
-
|
127
|
-
Any number of targets can be specified.
|
128
|
-
Each must specify at least one command.
|
129
|
-
If additional configuration is required for a target then the commands should be provided
|
130
|
-
under the `run` key.
|
131
|
-
If more than one command is required then a YAML list should be used.
|
132
|
-
|
133
|
-
```
|
134
|
-
image: maven:3-jdk-7
|
135
|
-
|
136
|
-
targets:
|
137
|
-
build: mvn install
|
138
|
-
|
139
|
-
test-java-8:
|
140
|
-
image: maven:3-jdk-8
|
141
|
-
run: mvn verify
|
142
|
-
|
143
|
-
deploy:
|
144
|
-
- mvn deploy
|
145
|
-
- curl http://ci.example.com/deploy/trigger
|
146
|
-
```
|
23
|
+
## Usage
|
147
24
|
|
25
|
+
See the main site at http://lstephen.github.io/construi
|
148
26
|
|
data/Rakefile
CHANGED
data/bin/construi
CHANGED
data/construi.gemspec
CHANGED
@@ -4,29 +4,34 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'construi/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'construi'
|
8
8
|
spec.version = Construi::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
9
|
+
spec.authors = ['Levi Stephen']
|
10
|
+
spec.email = ['levi.stephen@gmail.com']
|
11
|
+
spec.summary = 'Build tool using Docker to specify build environment'
|
12
|
+
spec.description = 'Build tool using Docker to specify build environment'
|
13
|
+
spec.homepage = 'https://github.com/lstephen/construi'
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
21
|
spec.required_ruby_version = '>= 1.9'
|
22
22
|
|
23
23
|
spec.add_dependency 'docker-api', '=1.21.4'
|
24
24
|
spec.add_dependency 'colorize', '=0.7.7'
|
25
25
|
|
26
|
-
spec.add_development_dependency 'bundler', '~> 1.
|
27
|
-
spec.add_development_dependency '
|
28
|
-
spec.add_development_dependency 'coveralls', '~> 0.7'
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.9'
|
27
|
+
spec.add_development_dependency 'execjs', '~> 2.5'
|
29
28
|
spec.add_development_dependency 'gem-release', '~> 0.7'
|
30
|
-
spec.add_development_dependency '
|
29
|
+
spec.add_development_dependency 'jekyll', '~> 2.5'
|
30
|
+
spec.add_development_dependency 'rake', '~> 10.4'
|
31
|
+
spec.add_development_dependency 'redcarpet', '~> 3.2'
|
31
32
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
33
|
+
spec.add_development_dependency 'rubocop', '~> 0.31'
|
34
|
+
spec.add_development_dependency 'simplecov', '~> 0.10'
|
35
|
+
spec.add_development_dependency 'therubyracer', '~> 0.12'
|
36
|
+
spec.add_development_dependency 'yard', '~> 0.8'
|
32
37
|
end
|
data/construi.yml
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
image: ruby:1.9
|
2
2
|
|
3
3
|
environment:
|
4
|
-
-
|
5
|
-
- BUILD_NUMBER
|
6
|
-
- CODECLIMATE_REPO_TOKEN
|
7
|
-
- COVERALLS_REPO_TOKEN
|
4
|
+
- COVERAGE
|
8
5
|
- GIT_COMMIT
|
9
6
|
- GIT_BRANCH
|
10
7
|
- GIT_SSH_KEY
|
11
8
|
- GIT_AUTHOR_NAME
|
12
9
|
- GIT_AUTHOR_EMAIL
|
13
10
|
- RUBYGEMS_API_KEY
|
11
|
+
- SITE_DEPLOY
|
14
12
|
|
15
13
|
targets:
|
16
14
|
build:
|
@@ -21,6 +19,14 @@ targets:
|
|
21
19
|
- bundle install --path=vendor/bundle
|
22
20
|
- bundle exec rake install
|
23
21
|
|
22
|
+
site:
|
23
|
+
build: construi/site
|
24
|
+
files:
|
25
|
+
- $GIT_SSH_KEY:/root/.ssh/id_rsa:0600
|
26
|
+
run:
|
27
|
+
- bundle install --path=vendor/bundle
|
28
|
+
- bash construi/site/run.sh
|
29
|
+
|
24
30
|
release:
|
25
31
|
files:
|
26
32
|
- $GIT_SSH_KEY:/root/.ssh/id_rsa:0600
|
data/construi/release/script.sh
CHANGED
@@ -7,14 +7,22 @@ set -e
|
|
7
7
|
|
8
8
|
printf "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
9
9
|
|
10
|
-
git
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
git
|
16
|
-
|
10
|
+
release_commit=`git rev-parse HEAD`
|
11
|
+
|
12
|
+
echo "Release commit ${release_commit}..."
|
13
|
+
|
14
|
+
echo "Pushing to master..."
|
15
|
+
git push -f origin `git rev-parse HEAD`:master
|
16
|
+
|
17
|
+
echo "Push to master done."
|
18
|
+
|
19
|
+
echo "Updating development version..."
|
17
20
|
bundle install --path vendor/bundle
|
18
21
|
bundle exec gem bump --version minor
|
19
|
-
|
22
|
+
|
23
|
+
echo "Pushing to develop..."
|
24
|
+
git push origin `get rev-parse HEAD`:develop
|
25
|
+
echo "Push to develop done."
|
26
|
+
|
27
|
+
echo "Release done."
|
20
28
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
echo "Generating Site..."
|
6
|
+
|
7
|
+
bundle exec jekyll build --source site --destination target/site
|
8
|
+
|
9
|
+
echo "Generating Reports..."
|
10
|
+
|
11
|
+
echo "Yard..."
|
12
|
+
bundle exec yard --output-dir target/site/yard
|
13
|
+
|
14
|
+
echo "Coverage..."
|
15
|
+
COVERAGE=true bundle exec rake spec
|
16
|
+
|
17
|
+
echo "Rubocop..."
|
18
|
+
bundle exec rubocop --format html -o target/site/rubocop.html || true
|
19
|
+
|
20
|
+
echo "Reports done."
|
21
|
+
|
22
|
+
if [[ -n "$SITE_DEPLOY" ]]
|
23
|
+
then
|
24
|
+
[[ -n "$GIT_AUTHOR_NAME" ]] && git config user.name $GIT_AUTHOR_NAME
|
25
|
+
[[ -n "$GIT_AUTHOR_EMAIL" ]] && git config user.email $GIT_AUTHOR_EMAIL
|
26
|
+
|
27
|
+
printf "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
28
|
+
|
29
|
+
echo "Deploying site to gh-pages..."
|
30
|
+
ghp-import -p target/site
|
31
|
+
echo "Deployment done."
|
32
|
+
fi
|
33
|
+
|
34
|
+
echo "Site done."
|
35
|
+
|
data/lib/construi.rb
CHANGED
data/lib/construi/config.rb
CHANGED
@@ -1,126 +1,134 @@
|
|
1
1
|
|
2
|
-
module Construi
|
2
|
+
module Construi
|
3
|
+
module Config
|
4
|
+
module Image
|
5
|
+
def image
|
6
|
+
image_configured :image
|
7
|
+
end
|
3
8
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
9
|
+
def build
|
10
|
+
image_configured :build
|
11
|
+
end
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
|
13
|
+
def privileged?
|
14
|
+
key?(:privileged) ? yaml['privileged'] : with_parent(false, &:privileged?)
|
15
|
+
end
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
17
|
+
def image_configured?
|
18
|
+
key?(:build) || key?(:image)
|
19
|
+
end
|
16
20
|
|
17
|
-
|
18
|
-
|
21
|
+
def image_configured(what)
|
22
|
+
image_configured? ? yaml[what.to_s] : with_parent(&what)
|
23
|
+
end
|
19
24
|
end
|
20
|
-
end
|
21
25
|
|
22
|
-
|
26
|
+
module Files
|
27
|
+
class File
|
28
|
+
attr_reader :container, :permissions
|
23
29
|
|
24
|
-
|
25
|
-
|
30
|
+
def initialize(host, container, permissions)
|
31
|
+
@host = host
|
32
|
+
@container = container
|
33
|
+
@permissions = permissions
|
34
|
+
end
|
26
35
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
36
|
+
def host
|
37
|
+
@host.gsub(/\$(\w+)/) { ENV[$1] }
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.parse(str)
|
41
|
+
split = str.split(':')
|
42
|
+
File.new split[0], split[1], split[2]
|
43
|
+
end
|
31
44
|
end
|
32
45
|
|
33
|
-
def
|
34
|
-
|
46
|
+
def files_configured?
|
47
|
+
key? :files
|
35
48
|
end
|
36
49
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
50
|
+
def files
|
51
|
+
fs = files_configured? ? yaml['files'].map { |str| File.parse(str) } : []
|
52
|
+
|
53
|
+
with_parent([], &:files).concat fs
|
40
54
|
end
|
41
55
|
end
|
42
56
|
|
43
|
-
|
44
|
-
|
45
|
-
|
57
|
+
module Environment
|
58
|
+
include Image
|
59
|
+
include Files
|
60
|
+
|
61
|
+
def parent
|
62
|
+
nil
|
63
|
+
end
|
46
64
|
|
47
|
-
|
48
|
-
|
65
|
+
def key?(key)
|
66
|
+
yaml.is_a?(Hash) && yaml.key?(key.to_s)
|
67
|
+
end
|
49
68
|
|
50
|
-
with_parent(
|
69
|
+
def with_parent(or_else = nil)
|
70
|
+
parent ? yield(parent) : or_else
|
71
|
+
end
|
51
72
|
end
|
52
|
-
end
|
53
73
|
|
54
|
-
|
55
|
-
|
56
|
-
include Files
|
74
|
+
class Global
|
75
|
+
include Environment
|
57
76
|
|
58
|
-
|
59
|
-
nil
|
60
|
-
end
|
77
|
+
attr_reader :yaml
|
61
78
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
79
|
+
def initialize(yaml)
|
80
|
+
@yaml = yaml
|
81
|
+
end
|
66
82
|
|
67
|
-
|
68
|
-
|
83
|
+
def env
|
84
|
+
return [] if yaml['environment'].nil?
|
69
85
|
|
70
|
-
|
86
|
+
yaml['environment'].reduce([]) do |acc, e|
|
87
|
+
key = e.partition('=').first
|
88
|
+
value = e.partition('=').last
|
71
89
|
|
72
|
-
|
73
|
-
@yaml = yaml
|
74
|
-
end
|
90
|
+
value = ENV[key] if value.empty?
|
75
91
|
|
76
|
-
|
77
|
-
|
92
|
+
acc << "#{key}=#{value}" unless value.nil? or value.empty?
|
93
|
+
acc
|
94
|
+
end
|
95
|
+
end
|
78
96
|
|
79
|
-
|
80
|
-
|
81
|
-
value = e.partition('=').last
|
97
|
+
def target(target)
|
98
|
+
targets = yaml['targets']
|
82
99
|
|
83
|
-
|
100
|
+
return nil if targets.nil?
|
84
101
|
|
85
|
-
|
86
|
-
acc
|
102
|
+
return Target.new yaml['targets'][target], self
|
87
103
|
end
|
88
104
|
end
|
89
105
|
|
90
|
-
|
91
|
-
|
106
|
+
class Target
|
107
|
+
include Environment
|
92
108
|
|
93
|
-
|
94
|
-
|
95
|
-
return Target.new yaml['targets'][target], self
|
96
|
-
end
|
97
|
-
end
|
109
|
+
attr_reader :yaml, :parent
|
98
110
|
|
99
|
-
|
100
|
-
|
111
|
+
def initialize(yaml, parent)
|
112
|
+
@yaml = yaml
|
113
|
+
@parent = parent
|
114
|
+
end
|
101
115
|
|
102
|
-
|
116
|
+
def commands
|
117
|
+
Array(@yaml.is_a?(Hash) ? @yaml['run'] : @yaml)
|
118
|
+
end
|
103
119
|
|
104
|
-
|
105
|
-
|
106
|
-
|
120
|
+
def options
|
121
|
+
{ env: parent.env, privileged: parent.privileged? }
|
122
|
+
end
|
107
123
|
end
|
108
124
|
|
109
|
-
def
|
110
|
-
|
125
|
+
def self.load(content)
|
126
|
+
Global.new YAML.load(content)
|
111
127
|
end
|
112
128
|
|
113
|
-
def
|
114
|
-
|
129
|
+
def self.load_file(path)
|
130
|
+
Global.new YAML.load_file(path)
|
115
131
|
end
|
116
132
|
end
|
117
|
-
|
118
|
-
def self.load(content)
|
119
|
-
Global.new YAML.load(content)
|
120
|
-
end
|
121
|
-
|
122
|
-
def self.load_file(path)
|
123
|
-
Global.new YAML.load_file(path)
|
124
|
-
end
|
125
133
|
end
|
126
134
|
|