cide 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.dockerignore +3 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +10 -2
- data/cide.gemspec +1 -1
- data/cide.yml +2 -4
- data/docs/cide.yml.md +1 -1
- data/lib/cide/builder.rb +54 -0
- data/lib/cide/cli.rb +161 -140
- data/lib/cide/config_file.rb +101 -0
- data/lib/cide/config_file_loader.rb +305 -0
- data/lib/cide/docker.rb +16 -18
- data/lib/cide/runner.rb +110 -0
- data/man/{cide-build.1.md → cide-exec.1.md} +19 -11
- data/man/cide-package.1.md +56 -0
- data/man/cide.1.md +28 -2
- data/man/cide.yml.1.md +1 -1
- data/script/build +29 -0
- data/script/ci +2 -0
- data/spec/build_config_loader_spec.rb +4 -4
- metadata +11 -6
- data/lib/cide/build.rb +0 -2
- data/lib/cide/build/config.rb +0 -103
- data/lib/cide/build/config_loader.rb +0 -307
data/lib/cide/runner.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require 'cide/docker'
|
4
|
+
|
5
|
+
module CIDE
|
6
|
+
class Runner
|
7
|
+
include CIDE::Docker
|
8
|
+
|
9
|
+
def initialize(
|
10
|
+
command: [],
|
11
|
+
env: {},
|
12
|
+
links: [],
|
13
|
+
tag: nil,
|
14
|
+
user: nil
|
15
|
+
)
|
16
|
+
fail ArgumentError, 'tag missing' unless tag
|
17
|
+
|
18
|
+
@containers = []
|
19
|
+
@id = SecureRandom.hex
|
20
|
+
|
21
|
+
@tag = tag
|
22
|
+
@env = env
|
23
|
+
@links = links
|
24
|
+
@command = command
|
25
|
+
@user = user
|
26
|
+
end
|
27
|
+
|
28
|
+
# !!!! Don't call run twice !!!!
|
29
|
+
def run!(interactive: false)
|
30
|
+
start_links!
|
31
|
+
|
32
|
+
run_options = ['--detach']
|
33
|
+
|
34
|
+
@env.each_pair do |key, value|
|
35
|
+
run_options.push '--env', [key, value].join('=')
|
36
|
+
end
|
37
|
+
|
38
|
+
@links.each do |link|
|
39
|
+
run_options.push '--link', [link.id, link.name].join(':')
|
40
|
+
end
|
41
|
+
|
42
|
+
run_options.push '--name', @id
|
43
|
+
|
44
|
+
run_options.push '--user', @user if @user
|
45
|
+
|
46
|
+
run_options.push('--interactive', '--tty') if interactive
|
47
|
+
|
48
|
+
run_options.push @tag
|
49
|
+
run_options.push(*@command)
|
50
|
+
|
51
|
+
id = docker(:run, *run_options, capture: true).strip
|
52
|
+
@containers << id
|
53
|
+
docker(:attach, id)
|
54
|
+
end
|
55
|
+
|
56
|
+
def export!(guest_dir: nil, host_dir: nil)
|
57
|
+
fail ArgumentError, 'guest export_dir missing' unless guest_dir
|
58
|
+
fail ArgumentError, 'host export_dir missing' unless host_dir
|
59
|
+
|
60
|
+
# FIXME: strip trailing slashes ?
|
61
|
+
guest_dir = File.expand_path(guest_dir, CIDE_SRC_DIR)
|
62
|
+
host_dir = File.expand_path(host_dir, Dir.pwd)
|
63
|
+
|
64
|
+
FileUtils.mkdir_p(File.dirname(host_dir))
|
65
|
+
|
66
|
+
docker :cp, [@id, guest_dir].join(':'), host_dir
|
67
|
+
end
|
68
|
+
|
69
|
+
def cleanup!(output: $stderr)
|
70
|
+
return if @containers.empty?
|
71
|
+
begin
|
72
|
+
report_containers!(output)
|
73
|
+
ensure
|
74
|
+
# Shutdown old containers
|
75
|
+
docker :rm, '--force', '--volumes', *@containers.reverse, capture: true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
def start_links!
|
82
|
+
@links.each do |link|
|
83
|
+
args = ['--detach']
|
84
|
+
link.env.each_pair do |key, value|
|
85
|
+
args.push('--env', [key, value].join('='))
|
86
|
+
end
|
87
|
+
args << link.image
|
88
|
+
args << link.run if link.run
|
89
|
+
link.id = docker(:run, *args, capture: true).strip
|
90
|
+
@containers << link.id
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def report_containers!(output)
|
95
|
+
infos = docker(:inspect, *@containers, capture: true)
|
96
|
+
|
97
|
+
JSON.parse(infos).each do |info|
|
98
|
+
config = info['Config']
|
99
|
+
state = info['State']
|
100
|
+
|
101
|
+
next unless state['Dead'] || state['ExitCode'] > 0
|
102
|
+
|
103
|
+
output.puts "=== Failed container #{info['Id']} ==="
|
104
|
+
output.puts "Image: #{config['Image']}"
|
105
|
+
output.puts "State: #{state.inspect}"
|
106
|
+
docker(:logs, '--tail', 20, info['Id'])
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
|
-
CIDE-
|
2
|
-
|
1
|
+
CIDE-EXEC 1 "FEBRUARY 2016" cide-exec "Cide Manual"
|
2
|
+
===================================================
|
3
3
|
|
4
4
|
NAME
|
5
5
|
----
|
6
6
|
|
7
|
-
cide-
|
7
|
+
cide-exec - Builds an image and executes the run script
|
8
8
|
|
9
9
|
SYNOPSIS
|
10
10
|
--------
|
11
11
|
|
12
|
-
*cide
|
13
|
-
[
|
12
|
+
*cide exec* [`--export`|`--no-export`] [`-o`|`--export-dir`=<*path*>]
|
13
|
+
[`--guest_export_dir`=<*path*>] [`-r`|`--run`=<*command*>]
|
14
14
|
[`--pull`|`--no-pull`] [`-s`|`--ssh-key`=<*path*>]
|
15
15
|
|
16
16
|
DESCRIPTION
|
@@ -28,21 +28,29 @@ CI run with isolated dependencies.
|
|
28
28
|
OPTIONS
|
29
29
|
-------
|
30
30
|
|
31
|
-
`-n`, `--name`=<*name*>
|
31
|
+
`-n`, `-t`, `--name`=<*name*>
|
32
32
|
Name of the built image. This can be used to differentiate between branches
|
33
33
|
or others in a CI environment. By default the name is the basename(1) of the
|
34
34
|
current directory.
|
35
35
|
|
36
36
|
`--export`, `--no-export`
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
Whether to export artifacts. If `--export` is passed and the directory to
|
38
|
+
be exported is set (either with `export_dir:` in the `cide.yml` file, or by
|
39
|
+
specifying `--guest-export-dir` on the command line) artifacts from that
|
40
|
+
directory are transfered back outside of the container (see `--export-dir`
|
41
|
+
and `--guest-export-dir`)
|
40
42
|
|
41
43
|
`-o`, `--export-dir`=<*path*>
|
42
|
-
|
43
|
-
|
44
|
+
Where the directory extracted from the container should be placed on the
|
45
|
+
host. By default the export directory is the same as the one given in the
|
46
|
+
`export_dir:` directive in the `cide.yml` file. It is possible to change that
|
44
47
|
target folder outside of the container.
|
45
48
|
|
49
|
+
`--guest-export-dir`=<*path*>
|
50
|
+
Which directory from the container should be extracted. By default the
|
51
|
+
export directory is the same as the one specified with `--export-dir` if any,
|
52
|
+
or in the `export_dir:` directive in the `cide.yml` file otherwise.
|
53
|
+
|
46
54
|
`-r`, `--run`=<*command*>
|
47
55
|
Override the script to run. Usually the `run:` directive in the `cide.yml`
|
48
56
|
is defining what to run but this could be used for a quick one-off.
|
@@ -0,0 +1,56 @@
|
|
1
|
+
CIDE-PACKAGE "FEBRUARY 2016" cide-package "Cide Manual"
|
2
|
+
=======================================================
|
3
|
+
|
4
|
+
NAME
|
5
|
+
----
|
6
|
+
|
7
|
+
cide-package - Builds a package from the run script
|
8
|
+
|
9
|
+
SYNOPSIS
|
10
|
+
--------
|
11
|
+
|
12
|
+
*cide package* [`-n`|`-t`|`--name`=<*name*>] [`-s`|`--ssh-key`=<*path*>]
|
13
|
+
[`--package`=<*package*>] [`--upload`]
|
14
|
+
[`--set-version`]
|
15
|
+
|
16
|
+
DESCRIPTION
|
17
|
+
-----------
|
18
|
+
|
19
|
+
This tells `cide` to package a built package for you, and possibly upload it to
|
20
|
+
s3.
|
21
|
+
|
22
|
+
When invoke, cide will retrieve a previously created container (see `--name`),
|
23
|
+
perform a `cide` run, and package a given directory. The behavior is the same
|
24
|
+
as `exec` but will always export a directory, which it will upload to Amazon
|
25
|
+
s3.
|
26
|
+
|
27
|
+
OPTIONS
|
28
|
+
-------
|
29
|
+
|
30
|
+
`-n`, `-t`, `--name`
|
31
|
+
The name (tag) of the container from which to retrieve the build.
|
32
|
+
|
33
|
+
`-s`, `--ssh-key`=<*path*>
|
34
|
+
When the `use_ssh:` directive is set to true, where to get the ssh key to
|
35
|
+
inject into the container. Defaults to `~/.ssh/id_rsa`.
|
36
|
+
|
37
|
+
`--package`=<*package*>
|
38
|
+
The name of the package. The final archive will have the name
|
39
|
+
`<package>.<timestamp>.<version>.tar.gz`, where timestamp is the time at
|
40
|
+
which the packaging occured (in format `YYYY-mm-dd_HHMMSS`) and `<version>`
|
41
|
+
is the package version (see `--set-version`).
|
42
|
+
|
43
|
+
`--upload`
|
44
|
+
Whether the archive should be uploaded to Amazon s3. If the archive should be
|
45
|
+
uploaded to s3 by the packager, the s3 credentials must be provided to
|
46
|
+
`cide`. The s3 credentials must be exported as environment variables.
|
47
|
+
|
48
|
+
`--set-version`
|
49
|
+
Sets a package version. Is is solely used when naming the archive (see
|
50
|
+
`--package`). If no version is provided on the command line, a default
|
51
|
+
version name will be extracted from git (short sha).
|
52
|
+
|
53
|
+
SEE ALSO
|
54
|
+
--------
|
55
|
+
|
56
|
+
cide(1)
|
data/man/cide.1.md
CHANGED
@@ -25,6 +25,9 @@ of the current directory's structure, builds an image with it and then runs a
|
|
25
25
|
container from it that executes the specified tests. See the cide.yml(1) man
|
26
26
|
page for the structure of that file.
|
27
27
|
|
28
|
+
Cide can also be used to package and upload projects after they have been
|
29
|
+
built. See cide-package(1) for more information.
|
30
|
+
|
28
31
|
OPTIONS
|
29
32
|
-------
|
30
33
|
|
@@ -45,11 +48,18 @@ These are global options that set the behavior of all commands.
|
|
45
48
|
COMMANDS
|
46
49
|
--------
|
47
50
|
|
48
|
-
*cide
|
51
|
+
*cide exec* [<*options*>]
|
49
52
|
Builds an image and executes the run script. This is the default command
|
50
53
|
when none is provided.
|
51
54
|
|
52
|
-
See cide-
|
55
|
+
See cide-package(1)
|
56
|
+
|
57
|
+
*cide package* [<*options*>]
|
58
|
+
Packages a directory that resulting from a run script. Can also upload the
|
59
|
+
package to Amazon s3.
|
60
|
+
|
61
|
+
See cide-package(1)
|
62
|
+
|
53
63
|
|
54
64
|
*cide clean* [<*options*>]
|
55
65
|
Removes old containers.
|
@@ -91,6 +101,22 @@ https://docs.docker.com/docker/reference/commandline/cli/#environment-variables:
|
|
91
101
|
*DOCKER_TLS_VERIFY*
|
92
102
|
When set Docker uses TLS and verifies the remote.
|
93
103
|
|
104
|
+
|
105
|
+
The following environment variables are used by the Amazon `s3` SDK to
|
106
|
+
authenticate, and should be set by the user. See also
|
107
|
+
http://docs.aws.amazon.com/sdkforruby/api/index.html.
|
108
|
+
|
109
|
+
*AWS_ACCESS_KEY_ID*
|
110
|
+
*AWS_SECRET_ACCESS_KEY*
|
111
|
+
The Amazon key id and access key (see
|
112
|
+
http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html)
|
113
|
+
|
114
|
+
*AWS_REGION*
|
115
|
+
The Amazon region (e.g. `us-east-1`)
|
116
|
+
|
117
|
+
*AWS_BUCKET*
|
118
|
+
Your bucket's name
|
119
|
+
|
94
120
|
CONTRIBUTE
|
95
121
|
----------
|
96
122
|
|
data/man/cide.yml.1.md
CHANGED
data/script/build
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/bin/bash -e
|
2
|
+
|
3
|
+
if [[ -z $1 ]]; then
|
4
|
+
echo "Missing <TARGET>" >&2
|
5
|
+
exit 1
|
6
|
+
fi
|
7
|
+
|
8
|
+
packager_bin() {
|
9
|
+
local bin=$1
|
10
|
+
local name=$(basename "$1")
|
11
|
+
mkdir -p .packager/bin
|
12
|
+
cat <<BIN > ".packager/bin/${name}"
|
13
|
+
#!/bin/sh -e
|
14
|
+
here=\$(dirname "\$(readlink -f "\$0")")
|
15
|
+
target=\$(readlink -f "\$here/../../${bin}")
|
16
|
+
exec "\$target" "\$@"
|
17
|
+
BIN
|
18
|
+
chmod +x ".packager/bin/${name}"
|
19
|
+
}
|
20
|
+
|
21
|
+
TARGET=$1
|
22
|
+
|
23
|
+
cp -r "$PWD" "$TARGET"
|
24
|
+
cd "$TARGET"
|
25
|
+
bundle install --standalone --binstubs=binstubs --without=development test
|
26
|
+
|
27
|
+
rm -rf vendor/bundle/ruby/*/{bin,build_info,cache,doc,extensions,specifications}
|
28
|
+
|
29
|
+
packager_bin binstubs/cide
|
data/script/ci
ADDED
@@ -1,12 +1,12 @@
|
|
1
|
-
require "cide/
|
1
|
+
require "cide/config_file"
|
2
2
|
require "stringio"
|
3
3
|
require "ostruct"
|
4
4
|
require "active_support/json"
|
5
5
|
|
6
|
-
describe "CIDE::
|
6
|
+
describe "CIDE::ConfigFile::Loader" do
|
7
7
|
before do
|
8
|
-
@config = CIDE::
|
9
|
-
@loader = CIDE::
|
8
|
+
@config = CIDE::ConfigFile.new
|
9
|
+
@loader = CIDE::ConfigFileLoader.new(@config)
|
10
10
|
ENV['TEST1'] = 'test1'
|
11
11
|
ENV['TEST2'] = 'test2'
|
12
12
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cide
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zimbatm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -119,6 +119,7 @@ executables:
|
|
119
119
|
extensions: []
|
120
120
|
extra_rdoc_files: []
|
121
121
|
files:
|
122
|
+
- ".dockerignore"
|
122
123
|
- ".editorconfig"
|
123
124
|
- ".gitignore"
|
124
125
|
- ".nojekyll"
|
@@ -138,20 +139,24 @@ files:
|
|
138
139
|
- docs/cide.yml.md
|
139
140
|
- docs/sidebar.md
|
140
141
|
- index.html
|
141
|
-
- lib/cide/
|
142
|
-
- lib/cide/build/config.rb
|
143
|
-
- lib/cide/build/config_loader.rb
|
142
|
+
- lib/cide/builder.rb
|
144
143
|
- lib/cide/cli.rb
|
144
|
+
- lib/cide/config_file.rb
|
145
|
+
- lib/cide/config_file_loader.rb
|
145
146
|
- lib/cide/constants.rb
|
146
147
|
- lib/cide/default_cide.yml
|
147
148
|
- lib/cide/docker.rb
|
148
149
|
- lib/cide/dockerfile_template.erb
|
149
|
-
-
|
150
|
+
- lib/cide/runner.rb
|
150
151
|
- man/cide-clean.1.md
|
151
152
|
- man/cide-debug.1.md
|
153
|
+
- man/cide-exec.1.md
|
152
154
|
- man/cide-init.1.md
|
155
|
+
- man/cide-package.1.md
|
153
156
|
- man/cide.1.md
|
154
157
|
- man/cide.yml.1.md
|
158
|
+
- script/build
|
159
|
+
- script/ci
|
155
160
|
- spec/build_config_loader_spec.rb
|
156
161
|
- spec/spec_helper.rb
|
157
162
|
homepage: https://zimbatm.github.io/cide
|
data/lib/cide/build.rb
DELETED
data/lib/cide/build/config.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'virtus'
|
2
|
-
|
3
|
-
require 'erb'
|
4
|
-
require 'yaml'
|
5
|
-
|
6
|
-
require 'cide/build/config_loader'
|
7
|
-
|
8
|
-
module CIDE
|
9
|
-
module Build
|
10
|
-
class Config
|
11
|
-
DOCKERFILE_TEMPLATE =
|
12
|
-
File.expand_path('../../dockerfile_template.erb', __FILE__)
|
13
|
-
|
14
|
-
module NiceInspect
|
15
|
-
def inspect
|
16
|
-
out = []
|
17
|
-
attributes.each_pair do |key, value|
|
18
|
-
out << "#{key}=#{value.inspect}"
|
19
|
-
end
|
20
|
-
"<#{out.join(' ')}>"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class FileAdd
|
25
|
-
include Virtus.model(strict: true)
|
26
|
-
include NiceInspect
|
27
|
-
attribute :src, Array[String], default: []
|
28
|
-
attribute :dest, String
|
29
|
-
end
|
30
|
-
|
31
|
-
class Step
|
32
|
-
include Virtus.model(strict: true)
|
33
|
-
include NiceInspect
|
34
|
-
attribute :add, Array[FileAdd], default: []
|
35
|
-
attribute :env, Hash[String, String], default: {}
|
36
|
-
attribute :run, Array[String], default: []
|
37
|
-
end
|
38
|
-
|
39
|
-
class Link
|
40
|
-
include Virtus.model
|
41
|
-
include NiceInspect
|
42
|
-
attribute :name, String
|
43
|
-
attribute :image, String
|
44
|
-
attribute :env, Hash[String, String], default: {}
|
45
|
-
attribute :run, String
|
46
|
-
# Container ID added after the fact
|
47
|
-
attr_accessor :id
|
48
|
-
end
|
49
|
-
|
50
|
-
include Virtus.model(strict: true)
|
51
|
-
include NiceInspect
|
52
|
-
attribute :from, String, default: 'ubuntu'
|
53
|
-
attribute :as_root, Step, required: false
|
54
|
-
attribute :use_ssh, Boolean, default: false
|
55
|
-
attribute :before, Step, required: false
|
56
|
-
attribute :env, Hash[String, String], default: {}
|
57
|
-
attribute :export_dir, String, required: false
|
58
|
-
attribute :links, Array[Link], default: []
|
59
|
-
attribute :run, Array[String], default: ['script/ci']
|
60
|
-
|
61
|
-
attr_reader :warnings, :errors
|
62
|
-
|
63
|
-
def initialize(*)
|
64
|
-
super
|
65
|
-
@warnings = []
|
66
|
-
@errors = []
|
67
|
-
end
|
68
|
-
|
69
|
-
def to_dockerfile
|
70
|
-
ERB.new(File.read(DOCKERFILE_TEMPLATE), nil, '<>-').result(binding)
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.load(dir = Dir.pwd, output = $stderr)
|
74
|
-
file_path = find_config(dir)
|
75
|
-
load_file(file_path, output)
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.load_file(file_path, output = $stderr)
|
79
|
-
obj = new
|
80
|
-
loader = ConfigLoader.new(obj)
|
81
|
-
loader.load YAML.load_file(file_path)
|
82
|
-
|
83
|
-
obj.warnings.each do |warn|
|
84
|
-
output.puts "WARN: #{warn}"
|
85
|
-
end
|
86
|
-
|
87
|
-
obj.errors.each do |error|
|
88
|
-
output.puts "ERROR: #{error}"
|
89
|
-
end
|
90
|
-
|
91
|
-
return obj if obj.errors.empty?
|
92
|
-
nil
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.find_config(dir)
|
96
|
-
paths = CONFIG_FILES.map { |name| File.expand_path(name, dir) }
|
97
|
-
paths
|
98
|
-
.find { |path| File.exist?(path) } ||
|
99
|
-
fail("Config not found among these paths: #{paths.inspect}")
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|