vanagon 0.4.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 71209b38d92410c93fd14043757199b43b7eb354
4
- data.tar.gz: 00e90c362e4e79b5301c8c2ca25d4e34756cc2c5
3
+ metadata.gz: 0277e8af73f3165f6e9b9dac09f09afbf92257d1
4
+ data.tar.gz: b6d18711b68b4ca2ce845bb1cae01bbf019dfd90
5
5
  SHA512:
6
- metadata.gz: a416ecdf1e5c8d44250d9dd4192ec0d9d45c711fab197a444739bd7c711644baa9c8541488293151e5bb96a10b3fc615997ccf1bf92718e666214773aee4634b
7
- data.tar.gz: 6e8aa16121c6d1c5a97abbe5569f98b032137402282d135e210c40b3981846e6f248a520a5ca1a38e2d9cf548d8ec398363c1f04e5e270c5e75bd6e382dde8bb
6
+ metadata.gz: b8cccacd01204b1474944ec8975597369883ea354e71e58724802ab27b2581af7a009dd3ab07fe770fadd121180fb35b53bed8ae6bd409b3e031839c5d353d4d
7
+ data.tar.gz: a8b4f78d37aa2844f1615b7aded498e6c5ca47c5d34d5a18e229125062928d1c6033d9bb97beb3725a1bfeb2250bf714262af187d2509014b4573e18c95bf338
data/README.md CHANGED
@@ -84,6 +84,7 @@ Currently supported engines are:
84
84
  * `local` - Build on the local machine; platform name must match the local machine
85
85
  * `docker` - Builds in a docker container
86
86
  * `pooler` - Selects a vm from Puppet Labs' vm pooler to build on
87
+ * `hardware` - Build on a specific taget and lock it in redis
87
88
 
88
89
  #### Flags (can be anywhere in the command)
89
90
 
@@ -110,6 +111,13 @@ Used in conjunction with the pooler engine, this is a token to pass to the
110
111
  vmpooler to access the API. Without this token, the default lifetime of vms
111
112
  will be much shorter.
112
113
 
114
+ ##### LOCK\_MANAGER\_HOST
115
+ The name of the host where redis is running. Redis is used to handle a lock
116
+ when using the hardware engine. It defaults to *redis*, with no domain.
117
+
118
+ #### LOCK\_MANAGER\_PORT
119
+ Port of the system where redis is running. Defaults to *6379*.
120
+
113
121
  #### Example usage
114
122
  `build --preserve puppet-agent el-6-i386` will build the puppet-agent project
115
123
  on the el-6-i386 platform and leave the host intact afterward.
data/bin/build CHANGED
@@ -2,7 +2,7 @@
2
2
  load File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "vanagon.rb"))
3
3
 
4
4
  optparse = Vanagon::OptParse.new("#{File.basename(__FILE__)} <project-name> <platform-name> [<target>] [options]",
5
- [:workdir, :configdir, :engine, :preserve, :verbose])
5
+ [:workdir, :configdir, :engine, :preserve, :verbose, :skipcheck])
6
6
  options = optparse.parse! ARGV
7
7
 
8
8
  project = ARGV[0]
data/lib/makefile.rb ADDED
@@ -0,0 +1,67 @@
1
+ class Makefile
2
+
3
+ # The Rule class defines a single Makefile rule.
4
+ #
5
+ # @see http://www.gnu.org/software/make/manual/make.html#Rule-Introduction
6
+ class Rule
7
+
8
+ # @!attribute [rw] target
9
+ # @return [String] The target generated by this rule.
10
+ attr_accessor :target
11
+
12
+ # @!attribute [rw] dependencies
13
+ # @return [Array<String>] A list of dependencies that this rule depends on.
14
+ attr_accessor :dependencies
15
+
16
+ # @!attribute [rw] recipe
17
+ # @return [Array<String>] A list of commands to execute upon invocation of this rule.
18
+ attr_accessor :recipe
19
+
20
+ # Create a new Makefile rule. When a block is provided then it is called and passed the
21
+ # newly created Rule object.
22
+ #
23
+ # @overload initialize(target, dependencies: [], recipe: [])
24
+ # @param target [String] target
25
+ # @param dependencies [Array<String>]]
26
+ # @param recipe [Array<String>]
27
+ #
28
+ # @overload initialize(target, dependencies: [], recipe: [], &block)
29
+ # @param target [String] target
30
+ # @param dependencies [Array<String>]]
31
+ # @param recipe [Array<String>]
32
+ # @yieldparam rule [Makefile::Rule]
33
+ #
34
+ # @example Providing a block to #initialize
35
+ # newrule = Makefile::Rule.new("test", dependencies: ["all"]) do |rule|
36
+ # rule.recipe = [
37
+ # "make test",
38
+ # "make cpplint",
39
+ # ]
40
+ # end
41
+ def initialize(target, dependencies: [], recipe: [], &block)
42
+ @target = target
43
+ @dependencies = dependencies
44
+ @recipe = recipe
45
+
46
+ block.call(self) if block
47
+ end
48
+
49
+ # Format this rule as a Makefile rule.
50
+ #
51
+ # Recipes that have multiline statements will have tabs inserted after each
52
+ # newline to ensure that the recipe is parsed as part of a single makefile rule.
53
+ #
54
+ # @return [String]
55
+ def format
56
+ s = @target + ":"
57
+ unless @dependencies.empty?
58
+ s << " " << @dependencies.join(" ")
59
+ end
60
+ s << "\n"
61
+ s << @recipe.map { |line| "\t" + line.gsub("\n", "\n\t") + "\n" }.join
62
+ s
63
+ end
64
+
65
+ alias to_s format
66
+ end
67
+ end
@@ -1,13 +1,14 @@
1
1
  require 'vanagon/component/source'
2
2
  require 'vanagon/component/dsl'
3
+ require 'vanagon/component/rules'
3
4
 
4
5
  class Vanagon
5
6
  class Component
6
7
  # @!attribute [r] files
7
8
  # @return [Set] the list of files marked for installation
8
9
 
9
- attr_accessor :name, :version, :source, :url, :configure, :build, :install
10
- attr_accessor :environment, :extract_with, :dirname, :build_requires
10
+ attr_accessor :name, :version, :source, :url, :configure, :build, :check, :install
11
+ attr_accessor :environment, :extract_with, :dirname, :build_requires, :build_dir
11
12
  attr_accessor :settings, :platform, :patches, :requires, :service, :options
12
13
  attr_accessor :directories, :replaces, :provides, :cleanup_source, :environment
13
14
  attr_accessor :sources, :preinstall_actions, :postinstall_actions
@@ -50,6 +51,7 @@ class Vanagon
50
51
  @configure = []
51
52
  @install = []
52
53
  @build = []
54
+ @check = []
53
55
  @patches = []
54
56
  @files = Set.new
55
57
  @directories = []
@@ -121,6 +123,14 @@ class Vanagon
121
123
  end
122
124
  end
123
125
 
126
+ # Expands the build directory
127
+ def get_build_dir
128
+ if @build_dir
129
+ File.join(@dirname, @build_dir)
130
+ else
131
+ @dirname
132
+ end
133
+ end
124
134
 
125
135
  # Fetches secondary sources for the component. These are just dumped into the workdir currently.
126
136
  #
@@ -156,5 +166,9 @@ class Vanagon
156
166
  "export #{env.join(' ')}"
157
167
  end
158
168
  end
169
+
170
+ def rules(project, platform)
171
+ Vanagon::Component::Rules.new(self, project, platform)
172
+ end
159
173
  end
160
174
  end
@@ -1,4 +1,5 @@
1
1
  require 'vanagon/component'
2
+ require 'vanagon/patch'
2
3
  require 'ostruct'
3
4
  require 'json'
4
5
 
@@ -56,13 +57,20 @@ class Vanagon
56
57
  @component.configure << block.call
57
58
  end
58
59
 
59
- # Set or add to the build call for the component. The commands required to build the component before installing it.
60
+ # Set or add to the build call for the component. The commands required to build the component before testing/installing it.
60
61
  #
61
62
  # @param block [Proc] the command(s) required to build the component
62
63
  def build(&block)
63
64
  @component.build << block.call
64
65
  end
65
66
 
67
+ # Set or add to the check call for the component. The commands required to test the component before installing it.
68
+ #
69
+ # @param block [Proc] the command(s) required to test the component
70
+ def check(&block)
71
+ @component.check << block.call
72
+ end
73
+
66
74
  # Set or add to the install call for the component. The commands required to install the component.
67
75
  #
68
76
  # @param block [Proc] the command(s) required to install the component
@@ -80,10 +88,12 @@ class Vanagon
80
88
  # Add a patch to the list of patches to apply to the component's source after unpacking
81
89
  #
82
90
  # @param patch [String] Path to the patch that should be applied
91
+ # @param destination [String] Path to the location where the patch should be applied
83
92
  # @param strip [String, Integer] directory levels to skip in applying patch
84
93
  # @param fuzz [String, Integer] levels of context miss to ignore in applying patch
85
- def apply_patch(patch, strip: 1, fuzz: 0)
86
- @component.patches << OpenStruct.new('path' => patch, 'strip' => strip.to_s, 'fuzz' => fuzz.to_s)
94
+ # @param after [String] the location in the makefile where the patch command should be run
95
+ def apply_patch(patch, destination: @component.dirname, strip: 1, fuzz: 0, after: 'unpack')
96
+ @component.patches << Vanagon::Patch.new(patch, strip, fuzz, after, destination)
87
97
  end
88
98
 
89
99
  # Loads and parses json from a file. Will treat the keys in the
@@ -263,6 +273,27 @@ class Vanagon
263
273
  @component.options[:ref] = the_ref
264
274
  end
265
275
 
276
+ # Set a build dir relative to the source directory.
277
+ #
278
+ # The build dir will be created before the configure block runs and configure/build/install commands will be run
279
+ # in the build dir.
280
+ #
281
+ # @example
282
+ # pkg.build_dir "build"
283
+ # pkg.source "my-cmake-project" # Will create the path "my-cmake-project/build"
284
+ # pkg.configure { ["cmake .."] }
285
+ # pkg.build { ["make -j 3"] }
286
+ # pkg.install { ["make install"] }
287
+ #
288
+ # @param path [String] The build directory to use for building the project
289
+ def build_dir(path)
290
+ if Pathname.new(path).relative?
291
+ @component.build_dir = path
292
+ else
293
+ raise Vanagon::Error, "build_dir should be a relative path, but '#{path}' looks to be absolute."
294
+ end
295
+ end
296
+
266
297
  # This will add a source to the project and put it in the workdir alongside the other sources
267
298
  #
268
299
  # @param url [String] url of the source
@@ -0,0 +1,217 @@
1
+ require 'vanagon/component'
2
+ require 'vanagon/utilities/shell_utilities'
3
+ require 'makefile'
4
+
5
+ class Vanagon
6
+ class Component
7
+ # Vanagon::Component::Rules creates all Makefile rules for a given component.
8
+ class Rules
9
+
10
+ include Vanagon::Utilities::ShellUtilities
11
+
12
+ # Create methods that generate Makefile rules.
13
+ #
14
+ # This method cuts out some of the boilerplate of creating Makefile rules
15
+ # by creating methods and Makefile objects with a common name.
16
+ #
17
+ # @param target [Symbol] The rule target name.
18
+ # @param dependencies [Array<String>] An optional list of dependencies for the rule
19
+ # @yieldparam rule [Makefile::Rule] The generated Makefile rule
20
+ # @return [void]
21
+ #
22
+ # @!macro [attach] rule
23
+ # @return [Makefile::Rule] The $1 rule
24
+ def self.rule(target, dependencies: [], &block)
25
+ define_method("#{target}_rule") do
26
+ Makefile::Rule.new("#{@component.name}-#{target}", dependencies: dependencies) do |rule|
27
+ instance_exec(rule, &block)
28
+ end
29
+ end
30
+ end
31
+
32
+ # @param component [Vanagon::Component] The component to create rules for.
33
+ # @param project [Vanagon::Project] The project associated with the component.
34
+ # @param platform [Vanagon::Platform] The platform where this component will be built.
35
+ def initialize(component, project, platform)
36
+ @component = component
37
+ @project = project
38
+ @platform = platform
39
+ end
40
+
41
+ # Generate all Makefile rules for this component.
42
+ #
43
+ # If the project has the cleanup attribute set, a cleanup rule will be included
44
+ # in the returned rules.
45
+ #
46
+ # @return [Array<Makefile::Rule>]
47
+ def rules
48
+ list = [
49
+ component_rule,
50
+ unpack_rule,
51
+ patch_rule,
52
+ configure_rule,
53
+ build_rule,
54
+ check_rule,
55
+ install_rule,
56
+ clean_rule,
57
+ clobber_rule,
58
+ ]
59
+ if @project.cleanup
60
+ list << cleanup_rule
61
+ end
62
+
63
+ list
64
+ end
65
+
66
+ # Generate a top level rule to build this component.
67
+ #
68
+ # @return [Makefile::Rule]
69
+ def component_rule
70
+ Makefile::Rule.new("#{@component.name}", dependencies: ["#{@component.name}-install"])
71
+ end
72
+
73
+ # Unpack the source for this component. The unpacking behavior depends on
74
+ # the source type of the component.
75
+ #
76
+ # @see [Vanagon::Component::Source]
77
+ rule("unpack", dependencies: ['file-list-before-build']) do |r|
78
+ r.recipe << andand(@component.get_environment, @component.extract_with)
79
+ r.recipe << "touch #{r.target}"
80
+ end
81
+
82
+ # Apply any patches for this component.
83
+ rule("patch") do |r|
84
+ r.dependencies = ["#{@component.name}-unpack"]
85
+
86
+ after_unpack_patches = @component.patches.select { |patch| patch.after == "unpack" }
87
+ unless after_unpack_patches.empty?
88
+ r.recipe << andand_multiline(
89
+ "cd #{@component.dirname}",
90
+ after_unpack_patches.map { |patch| patch.cmd(@platform) }
91
+ )
92
+ end
93
+
94
+ r.recipe << "touch #{r.target}"
95
+ end
96
+
97
+ # Create a build directory for this component if an out of source tree build is specified,
98
+ # and any configure steps, if any.
99
+ rule("configure") do |r|
100
+ r.dependencies = ["#{@component.name}-patch"].concat(@project.list_component_dependencies(@component))
101
+
102
+ if @component.get_build_dir
103
+ r.recipe << "[ -d #{@component.get_build_dir} ] || mkdir -p #{@component.get_build_dir}"
104
+ end
105
+
106
+ unless @component.configure.empty?
107
+ r.recipe << andand_multiline(
108
+ "cd #{@component.get_build_dir}",
109
+ @component.get_environment,
110
+ @component.configure
111
+ )
112
+ end
113
+
114
+ r.recipe << "touch #{r.target}"
115
+ end
116
+
117
+ # Build this component.
118
+ rule("build") do |r|
119
+ r.dependencies = ["#{@component.name}-configure"]
120
+
121
+ unless @component.build.empty?
122
+ r.recipe << andand_multiline(
123
+ "cd #{@component.get_build_dir}",
124
+ @component.get_environment,
125
+ @component.build
126
+ )
127
+ end
128
+
129
+ r.recipe << "touch #{r.target}"
130
+ end
131
+
132
+ # Run tests for this component.
133
+ rule("check") do |r|
134
+ r.dependencies = ["#{@component.name}-build"]
135
+
136
+ unless @component.check.empty? || @project.settings[:skipcheck]
137
+ r.recipe << andand_multiline(
138
+ "cd #{@component.get_build_dir}",
139
+ @component.get_environment,
140
+ @component.check
141
+ )
142
+ end
143
+
144
+ r.recipe << "touch #{r.target}"
145
+ end
146
+
147
+ # Install this component.
148
+ rule("install") do |r|
149
+ r.dependencies = ["#{@component.name}-check"]
150
+
151
+ unless @component.install.empty?
152
+ r.recipe << andand_multiline(
153
+ "cd #{@component.get_build_dir}",
154
+ @component.get_environment,
155
+ @component.install
156
+ )
157
+ end
158
+
159
+ after_install_patches = @component.patches.select { |patch| patch.after == "install" }
160
+ after_install_patches.each do |patch|
161
+ r.recipe << andand(
162
+ "cd #{patch.destination}",
163
+ patch.cmd(@platform),
164
+ )
165
+ end
166
+
167
+ r.recipe << "touch #{r.target}"
168
+ end
169
+
170
+ # Run any post-installation cleanup steps for this component.
171
+ #
172
+ # This component is only included by {#rules} if the associated project has
173
+ # the `cleanup` attribute set.
174
+ rule("cleanup") do |r|
175
+ r.dependencies = ["#{@component.name}-install"]
176
+ r.recipe = [@component.cleanup_source, "touch #{r.target}"]
177
+ end
178
+
179
+ # Clean up any files generated while building this project.
180
+ #
181
+ # This cleans up the project by invoking `make clean` and removing the touch files
182
+ # for the configure/build/install steps.
183
+ rule("clean") do |r|
184
+ r.recipe << andand(
185
+ "[ -d #{@component.get_build_dir} ]",
186
+ "cd #{@component.get_build_dir}",
187
+ "#{@platform[:make]} clean"
188
+ )
189
+
190
+ %w(configure build install).each do |type|
191
+ touchfile = "#{@component.name}-#{type}"
192
+ r.recipe << andand(
193
+ "[ -e #{touchfile} ]",
194
+ "rm #{touchfile}"
195
+ )
196
+ end
197
+ end
198
+
199
+ # Remove all files associated with this component.
200
+ rule("clobber") do |r|
201
+ r.dependencies = ["#{@component.name}-clean"]
202
+ r.recipe = [
203
+ andand("[ -d #{@component.dirname} ]", "rm -r #{@component.dirname}"),
204
+ andand("[ -e #{@component.name}-unpack ]", "rm #{@component.name}-unpack")
205
+ ]
206
+ end
207
+
208
+ # Generate a Makefile fragment that contains all of the rules for the component.
209
+ # @return [String]
210
+ def format
211
+ rules.map(&:to_s).join("\n")
212
+ end
213
+
214
+ alias to_s format
215
+ end
216
+ end
217
+ end