construi 0.35.2 → 0.36.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.
- 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
|
[](https://rubygems.org/gems/construi)
|
4
4
|
[](http://jenkins.mylonelybear.org/job/construi-develop/)
|
5
|
-
[](https://gemnasium.com/lstephen/construi)
|
6
|
-
[](https://codeclimate.com/github/lstephen/construi)
|
7
|
-
[](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
|
|