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/lib/construi/container.rb
CHANGED
@@ -45,29 +45,37 @@ module Construi
|
|
45
45
|
other.is_a? Container and id == other.id
|
46
46
|
end
|
47
47
|
|
48
|
-
def self.create(image, cmd,
|
48
|
+
def self.create(image, cmd, options = {})
|
49
|
+
env = options[:env] || []
|
50
|
+
privileged = options[:privileged] || false
|
51
|
+
|
52
|
+
host_config = {
|
53
|
+
'Binds' => ["#{Dir.pwd}:/var/workspace"],
|
54
|
+
'Privileged' => privileged
|
55
|
+
}
|
56
|
+
|
49
57
|
wrap Docker::Container.create(
|
50
58
|
'Cmd' => cmd.split,
|
51
59
|
'Image' => image.id,
|
52
60
|
'Env' => env.to_json,
|
53
61
|
'Tty' => false,
|
54
62
|
'WorkingDir' => '/var/workspace',
|
55
|
-
'HostConfig' =>
|
63
|
+
'HostConfig' => host_config)
|
56
64
|
end
|
57
65
|
|
58
66
|
def self.wrap(container)
|
59
67
|
new container
|
60
68
|
end
|
61
69
|
|
62
|
-
def self.use(image, cmd,
|
63
|
-
container = create
|
70
|
+
def self.use(image, cmd, options = {})
|
71
|
+
container = create image, cmd, options
|
64
72
|
yield container
|
65
73
|
ensure
|
66
74
|
container.delete unless container.nil?
|
67
75
|
end
|
68
76
|
|
69
|
-
def self.run(image, cmd,
|
70
|
-
use
|
77
|
+
def self.run(image, cmd, options = {})
|
78
|
+
use image, cmd, options, &:run
|
71
79
|
end
|
72
80
|
|
73
81
|
class Error < StandardError
|
data/lib/construi/image.rb
CHANGED
@@ -56,8 +56,8 @@ module Construi
|
|
56
56
|
run chmod
|
57
57
|
end
|
58
58
|
|
59
|
-
def run(cmd,
|
60
|
-
Container.run
|
59
|
+
def run(cmd, options = {})
|
60
|
+
Container.run self, cmd, options
|
61
61
|
end
|
62
62
|
|
63
63
|
def ==(other)
|
@@ -116,7 +116,7 @@ module Construi
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def run(cmd, env = [])
|
119
|
-
map { |i| i.run
|
119
|
+
map { |i| i.run cmd, env: env }
|
120
120
|
end
|
121
121
|
|
122
122
|
def map
|
data/lib/construi/runner.rb
CHANGED
@@ -9,7 +9,7 @@ require 'colorize'
|
|
9
9
|
require 'docker'
|
10
10
|
|
11
11
|
module Construi
|
12
|
-
|
12
|
+
# Runs Construi
|
13
13
|
class Runner
|
14
14
|
def initialize(config)
|
15
15
|
@config = config
|
@@ -24,7 +24,12 @@ module Construi
|
|
24
24
|
Excon.defaults[:ssl_verify_peer] = false
|
25
25
|
|
26
26
|
Docker.validate_version!
|
27
|
-
|
27
|
+
|
28
|
+
# Don't time out. We can't differentiate between a long running
|
29
|
+
# task and a time out.
|
30
|
+
Docker.options[:read_timeout] = nil
|
31
|
+
|
32
|
+
# Low chunk size as we wish to receive streaming output ASAP
|
28
33
|
Docker.options[:chunk_size] = 8
|
29
34
|
end
|
30
35
|
|
@@ -35,9 +40,7 @@ module Construi
|
|
35
40
|
|
36
41
|
puts "Current directory: #{Dir.pwd}"
|
37
42
|
|
38
|
-
targets.map {|t| Target.new t, @config.target(t) } .each(&:run)
|
43
|
+
targets.map { |t| Target.new t, @config.target(t) } .each(&:run)
|
39
44
|
end
|
40
45
|
end
|
41
|
-
|
42
46
|
end
|
43
|
-
|
data/lib/construi/target.rb
CHANGED
data/lib/construi/version.rb
CHANGED
data/site/_config.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Site settings
|
2
|
+
title: Construi
|
3
|
+
email: levi.stephen@gmail.com
|
4
|
+
description: > # this means to ignore newlines until "baseurl:"
|
5
|
+
Write an awesome description for your new site here. You can edit this
|
6
|
+
line in _config.yml. It will appear in your document head meta (for
|
7
|
+
Google search results) and in your feed.xml site description.
|
8
|
+
baseurl: "" # the subpath of your site, e.g. /blog/
|
9
|
+
url: "http://yourdomain.com" # the base hostname & protocol for your site
|
10
|
+
twitter_username: jekyllrb
|
11
|
+
github_username: jekyll
|
12
|
+
github:
|
13
|
+
project: https://github.com/lstephen/construi
|
14
|
+
issues: https://github.com/lstephen/construi/issues
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
markdown: redcarpet
|
@@ -0,0 +1,79 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
+
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
8
|
+
<title>{{ site.title }}</title>
|
9
|
+
|
10
|
+
<!-- Bootstrap -->
|
11
|
+
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
|
12
|
+
|
13
|
+
<link href="css/main.css" rel="stylesheet"/>
|
14
|
+
|
15
|
+
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
16
|
+
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
17
|
+
<!--[if lt IE 9]>
|
18
|
+
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
19
|
+
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
20
|
+
<![endif]-->
|
21
|
+
</head>
|
22
|
+
<body>
|
23
|
+
<nav class="navbar navbar-inverse navbar-fixed-top">
|
24
|
+
<div class="container">
|
25
|
+
<div class="navbar-header">
|
26
|
+
<a class="navbar-brand" href="./">{{ site.title }}</a>
|
27
|
+
</div>
|
28
|
+
<div id="navbar" class="collapse navbar-collapse">
|
29
|
+
<ul class="nav navbar-nav pull-right">
|
30
|
+
<li><a href="{{ site.github.project }}">GitHub project</a></li>
|
31
|
+
<li class="dropdown">
|
32
|
+
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Contribute <b class="caret"></b></a>
|
33
|
+
<ul class="dropdown-menu">
|
34
|
+
<li><a href="{{ site.github.issues }}">Issues</a></li>
|
35
|
+
<li><a href="{{ site.github.project }}">Fork on GitHub</a></li>
|
36
|
+
</ul>
|
37
|
+
</li>
|
38
|
+
<li class="dropdown">
|
39
|
+
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Reports <b class="caret"></b></a>
|
40
|
+
<ul class="dropdown-menu">
|
41
|
+
<li><a href="yard/index.html">Yard Doc</a></li>
|
42
|
+
<li><a href="coverage/index.html">SimpleCov</a></li>
|
43
|
+
<li><a href="rubocop.html">Rubocop</a></li>
|
44
|
+
</ul>
|
45
|
+
</li>
|
46
|
+
</ul>
|
47
|
+
</div><!--/.nav-collapse -->
|
48
|
+
</div>
|
49
|
+
</nav>
|
50
|
+
|
51
|
+
<div class="main-body">
|
52
|
+
<div class="container">
|
53
|
+
{{ content }}
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
|
57
|
+
<footer class="well">
|
58
|
+
<div class="container">
|
59
|
+
<div class="row">
|
60
|
+
<div class="col-md-12">
|
61
|
+
<a href="https://rubygems.org/gems/construi">
|
62
|
+
<img src="https://img.shields.io/gem/v/formatador.svg?style=plastic"/>
|
63
|
+
</a>
|
64
|
+
<a href='http://jenkins.mylonelybear.org/job/construi-develop/'>
|
65
|
+
<img src='http://jenkins.mylonelybear.org/buildStatus/icon?job=construi-develop&style=plastic'>
|
66
|
+
</a>
|
67
|
+
<p class="pull-right"><a href="#">Back to top</a></p>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
</div>
|
71
|
+
</footer>
|
72
|
+
|
73
|
+
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
74
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
|
75
|
+
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
76
|
+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
77
|
+
</body>
|
78
|
+
</html>
|
79
|
+
|
data/site/css/main.css
ADDED
data/site/index.md
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
---
|
4
|
+
|
5
|
+
# Construi
|
6
|
+
|
7
|
+
Construi allows you to use [Docker](http://www.docker.com) containers as your build environment.
|
8
|
+
This allows a consistent and recreatable build environment on any machine running Construi
|
9
|
+
and Docker.
|
10
|
+
|
11
|
+
This is useful for ensuring consistency between development machines.
|
12
|
+
It is also useful in a CI environment where you may need to build projects from many different
|
13
|
+
languages and/or versions (e.g., Java 6, Java 8, Ruby).
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Construi requires [Ruby](http://www.ruby-lang.org) version 1.9 or higher.
|
18
|
+
It can be installed as a Gem.
|
19
|
+
|
20
|
+
```
|
21
|
+
> gem install construi
|
22
|
+
```
|
23
|
+
|
24
|
+
## Running
|
25
|
+
|
26
|
+
Construi requires that a `construi.yml` file be present in the root directory of your project.
|
27
|
+
Targets can then be run by specifying them on the command line. For example:
|
28
|
+
|
29
|
+
```
|
30
|
+
> construi build
|
31
|
+
> construi build install
|
32
|
+
```
|
33
|
+
|
34
|
+
Construi will create a Docker container with the project directory as a volume.
|
35
|
+
It will then run the commands configured for the given targets.
|
36
|
+
|
37
|
+
## The Construi File
|
38
|
+
|
39
|
+
As a minimal `construi.yml` requires an image and a target to be configured.
|
40
|
+
For example a simple configuration for a Java 8 project built with Maven could be:
|
41
|
+
|
42
|
+
```
|
43
|
+
image: maven:3-jdk-8
|
44
|
+
|
45
|
+
targets:
|
46
|
+
install: mvn install
|
47
|
+
```
|
48
|
+
|
49
|
+
Construi is built using itself, so it's
|
50
|
+
[`construi.yml`](https://github.com/lstephen/construi/blob/develop/construi.yml)
|
51
|
+
can be used as an example.
|
52
|
+
|
53
|
+
### Image
|
54
|
+
|
55
|
+
Specifies an image to be pulled that will be used as the build environment.
|
56
|
+
It can also be given on a per target basis.
|
57
|
+
|
58
|
+
```
|
59
|
+
image: maven:3-jdk-7
|
60
|
+
|
61
|
+
targets:
|
62
|
+
install: mvn install
|
63
|
+
|
64
|
+
test-java-8:
|
65
|
+
image: maven:3-jdk-8
|
66
|
+
run: mvn verify
|
67
|
+
```
|
68
|
+
|
69
|
+
### Build
|
70
|
+
|
71
|
+
Specifies a directory containing a `Dockerfile`.
|
72
|
+
Construi will build a Docker container based on that `Dockerfile` and use it as the build
|
73
|
+
environment.
|
74
|
+
Can be used as an alternative to providing an image.
|
75
|
+
Can also be given on a per target basis.
|
76
|
+
|
77
|
+
```
|
78
|
+
build: etc/build_environment
|
79
|
+
|
80
|
+
targets:
|
81
|
+
build:
|
82
|
+
- mvn install
|
83
|
+
- /usr/local/bin/custom_installed_command.sh
|
84
|
+
```
|
85
|
+
|
86
|
+
|
87
|
+
### Privileged
|
88
|
+
|
89
|
+
An image can be marked as a privileged image.
|
90
|
+
This is equivalent to passing `--privileged` to the Docker command line.
|
91
|
+
Useful when requiring docker to be part of the build process.
|
92
|
+
|
93
|
+
```
|
94
|
+
build: lstephen/docker
|
95
|
+
privileged: true
|
96
|
+
|
97
|
+
targets:
|
98
|
+
build: docker build latest/
|
99
|
+
```
|
100
|
+
|
101
|
+
### Environment
|
102
|
+
|
103
|
+
Declares environment variables that will be passed through or set in the build environment.
|
104
|
+
If no value is provided then the value from the host environment will be used.
|
105
|
+
In this example `NEXUS_SERVER_URL` will be set as provided, while `NEXUS_USERNAME` and
|
106
|
+
`NEXUS_PASSWORD` will be retrieved from the host.
|
107
|
+
|
108
|
+
```
|
109
|
+
image: maven:3-jdk-7
|
110
|
+
|
111
|
+
environment:
|
112
|
+
- NEXUS_SERVER_URL=http://nexus.example.com
|
113
|
+
- NEXUS_USERNAME
|
114
|
+
- NEXUS_PASSWORD
|
115
|
+
targets:
|
116
|
+
build: mvn install
|
117
|
+
```
|
118
|
+
|
119
|
+
### Files
|
120
|
+
|
121
|
+
Declares files to be copied into the build environment before the build is run.
|
122
|
+
Also allows setting of permissions.
|
123
|
+
Can be used on a per target basis.
|
124
|
+
|
125
|
+
```
|
126
|
+
image: maven:3-jdk-7
|
127
|
+
|
128
|
+
files:
|
129
|
+
- etc/maven-settings.xml:/home/root/.m2/settings.xml
|
130
|
+
|
131
|
+
targets:
|
132
|
+
deploy:
|
133
|
+
files:
|
134
|
+
- $GIT_SSH_KEY:/home/root/.ssh/id_rsa:0600
|
135
|
+
run: scripts/construi/deploy.sh
|
136
|
+
```
|
137
|
+
|
138
|
+
### Targets
|
139
|
+
|
140
|
+
Any number of targets can be specified.
|
141
|
+
Each must specify at least one command.
|
142
|
+
If additional configuration is required for a target then the commands should be provided
|
143
|
+
under the `run` key.
|
144
|
+
If more than one command is required then a YAML list should be used.
|
145
|
+
|
146
|
+
```
|
147
|
+
image: maven:3-jdk-7
|
148
|
+
|
149
|
+
targets:
|
150
|
+
build: mvn install
|
151
|
+
|
152
|
+
test-java-8:
|
153
|
+
image: maven:3-jdk-8
|
154
|
+
run: mvn verify
|
155
|
+
|
156
|
+
deploy:
|
157
|
+
- mvn deploy
|
158
|
+
- curl http://ci.example.com/deploy/trigger
|
159
|
+
```
|
160
|
+
|
161
|
+
|
@@ -281,7 +281,49 @@ RSpec.describe Construi::Config do
|
|
281
281
|
.to have_attributes :host => host, :container => container, :permissions => permissions
|
282
282
|
end
|
283
283
|
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe '#privileged?' do
|
287
|
+
subject { config.target('build').privileged? }
|
288
|
+
|
289
|
+
context 'when privileged absent' do
|
290
|
+
let(:config_content) do
|
291
|
+
<<-YAML
|
292
|
+
targets:
|
293
|
+
build:
|
294
|
+
run: cmd1
|
295
|
+
YAML
|
296
|
+
end
|
297
|
+
|
298
|
+
it { is_expected.to eq(false) }
|
299
|
+
end
|
284
300
|
|
301
|
+
context 'when present' do
|
302
|
+
let(:config_content) do
|
303
|
+
<<-YAML
|
304
|
+
privileged: true
|
305
|
+
targets:
|
306
|
+
build:
|
307
|
+
run: cmd1
|
308
|
+
YAML
|
309
|
+
end
|
310
|
+
|
311
|
+
it { is_expected.to eq(true) }
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'when overridden on target' do
|
315
|
+
let(:config_content) do
|
316
|
+
<<-YAML
|
317
|
+
privileged: true
|
318
|
+
targets:
|
319
|
+
build:
|
320
|
+
run: cmd1
|
321
|
+
privileged: false
|
322
|
+
YAML
|
323
|
+
end
|
324
|
+
|
325
|
+
it { is_expected.to eq(false) }
|
326
|
+
end
|
285
327
|
end
|
286
328
|
end
|
287
329
|
|
@@ -87,11 +87,12 @@ RSpec.describe Construi::Container do
|
|
87
87
|
let(:cmd) { 'cmd1 p1 p2' }
|
88
88
|
let(:env) { ['ENV1=VAL1', 'ENV2=VAL2'] }
|
89
89
|
let(:pwd) { '/project/dir' }
|
90
|
+
let(:privileged) { true }
|
90
91
|
|
91
92
|
before { allow(docker_container_class).to receive(:create).and_return docker_container }
|
92
93
|
before { allow(Dir).to receive(:pwd).and_return(pwd) }
|
93
94
|
|
94
|
-
subject! { Construi::Container::create(image, cmd, env) }
|
95
|
+
subject! { Construi::Container::create(image, cmd, env: env, privileged: privileged) }
|
95
96
|
|
96
97
|
it do
|
97
98
|
expect(docker_container_class).to have_received(:create).with( {
|
@@ -100,8 +101,11 @@ RSpec.describe Construi::Container do
|
|
100
101
|
'Env' => env.to_json,
|
101
102
|
'Tty' => false,
|
102
103
|
'WorkingDir' => '/var/workspace',
|
103
|
-
'HostConfig' => {
|
104
|
-
|
104
|
+
'HostConfig' => {
|
105
|
+
'Binds' => ["#{pwd}:/var/workspace"],
|
106
|
+
'Privileged' => true
|
107
|
+
}
|
108
|
+
} )
|
105
109
|
end
|
106
110
|
it { is_expected.to eq(Construi::Container.wrap docker_container) }
|
107
111
|
end
|
@@ -113,7 +117,7 @@ RSpec.describe Construi::Container do
|
|
113
117
|
before { allow(docker_container).to receive(:wait).and_return({'StatusCode' => 0}) }
|
114
118
|
before { allow(docker_container).to receive(:commit).and_return image }
|
115
119
|
|
116
|
-
subject! { Construi::Container.run(image, cmd
|
120
|
+
subject! { Construi::Container.run(image, cmd) }
|
117
121
|
|
118
122
|
it do
|
119
123
|
expect(docker_container_class).to have_received(:create).with(
|