cide 0.7.0 → 0.8.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.
- 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
|