simp-rake-helpers 1.0.12 → 1.0.13

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NjAxMDc4MmVmNzM4ZWVmNDMzYjI2ZmU5ODA0OGMyMjkwMzIwOTViMw==
4
+ NGQ2NWYwNDBiMTViOTk4NDQyNGQ5ZTMwNDk3ZDYwMWUzNWU1OGMxZA==
5
5
  data.tar.gz: !binary |-
6
- NTVmNzdmZGVhMjdhYzEzNGY1YTBjODEyMTNlYmZkYmJlNTM1YjU4Yw==
6
+ ODkzYzlhOWRjNDc4MjMxMDJjZWUzMWZmMTgxOWNhODM3MjgwMzAyMA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NmVjMWZhZGM3YjEwZmNjYmRlZmNhMmM0YTA3ZDVmNzAxNTNkNDU2M2RjMGM3
10
- ZmM4NDFkNjkyOTU3OWYwZjY3NzFhYzA4ZTRjZGRkNWYzMDM0MDQxYTY0MzNm
11
- ZTNiNWQ3ZDM1MzM3MjIzODhlNGE3NGZiNDhmY2YwOTdjZDY1ZTM=
9
+ ZTBiYWY0OTBiODcyZjg5Yjk4YjNkNWI5OTc4Yzc0ODE5ODAwYjk5M2I3ZWE1
10
+ ODMzMTc1MGU0NGIyNGI4ZjQ3ZWFjMTA4OWZiMmNiYjcyNGExYTQwMjk3Y2Ey
11
+ MGJlZGVkYzYzOTRhMjM3NmUxNmJkZjExYzY0YjBkNjc1MjdkYmM=
12
12
  data.tar.gz: !binary |-
13
- MWExNWM4NTA5MGViNGEzNGViNzEzMWUwZmIzODc2OTkwOThkYzYzOTY1NTg0
14
- NGVkM2Q0NTk1OWViOGJjMmZiOGFkYjZhYTExNWQ5NDVjZTZhOGVjNmFkODdk
15
- MDRjZDlhNWU2MjQ5MzQ3MmUyYjlkN2IwZTM0NGYxNTc4NjJiZmI=
13
+ Y2EwMTI1NWE1ZjVjZTU4ODkyYjAzMDA1ZTFlZWVlN2FhNTE1ZDc3OGYwODBm
14
+ OTRhOTFiMGUyMmNjOGY0M2VhNTNkYTU3MmUxNmNhNTA0OTBiODhlNmUwZDU5
15
+ MDQ5Nzg3NjJhN2Q4OTI5ZTA3ZDIxMTk1ZTdiNDEzMTJiYTk1NjY=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### 1.0.13 / 2016-02-10
2
+ * Ensure that all rake tasks can run on EL6 systems
3
+ * Update the processing of RPM spec files to properly handle macros in target builds
4
+
1
5
  ### 1.0.12 / 2015-11-13
2
6
  * Ensure that openssl, openssl-devel, and vim-enhanced are installed in mock by
3
7
  default
data/Rakefile CHANGED
@@ -38,7 +38,7 @@ namespace :pkg do
38
38
  task :gem => :chmod do
39
39
  Dir.chdir @rakefile_dir
40
40
  Dir['*.gemspec'].each do |spec_file|
41
- cmd = %Q{SIMP_RPM_BUILD=1 bundle exec gem build "#{spec_file}"}
41
+ cmd = %Q{SIMP_RPM_BUILD=0 bundle exec gem build "#{spec_file}"}
42
42
  sh cmd
43
43
  FileUtils.mkdir_p 'dist'
44
44
  FileUtils.mv Dir.glob("#{@package}*.gem"), 'dist/'
@@ -2,5 +2,5 @@ module Simp; end
2
2
  module Simp::Rake; end
3
3
 
4
4
  class Simp::Rake::Helpers
5
- VERSION = '1.0.12'
5
+ VERSION = '1.0.13'
6
6
  end
data/lib/simp/rake/pkg.rb CHANGED
@@ -52,13 +52,6 @@ module Simp::Rake
52
52
 
53
53
  ::CLEAN.include( @clean_list )
54
54
 
55
- @spec_info = Pkg.get_info( @spec_file )
56
- @chroot_name = @chroot_name || "#{@spec_info[:name]}__#{ENV.fetch( 'USER', 'USER' )}"
57
- @dir_name = "#{@spec_info[:name]}-#{@spec_info[:version]}"
58
- @mfull_pkg_name = "#{@dir_name}-#{@spec_info[:release]}"
59
- @full_pkg_name = @mfull_pkg_name.gsub("%{?snapshot_release}","")
60
- @tar_dest = "#{@pkg_dir}/#{@full_pkg_name}.tar.gz"
61
-
62
55
  define
63
56
  end
64
57
 
@@ -77,6 +70,37 @@ module Simp::Rake
77
70
  self
78
71
  end
79
72
 
73
+ # Initialize the mock space if passed and retrieve the spec info from that
74
+ # space directly.
75
+ #
76
+ # Ensures that the correct file names are used across the board.
77
+ def initialize_spec_info(chroot, unique)
78
+ unless @spec_info
79
+ spec_file = @spec_file
80
+
81
+ # This gets the resting spec file and allows us to pull out the name
82
+ @spec_info = Simp::RPM.get_info( spec_file )
83
+ @chroot_name = @chroot_name || "#{@spec_info[:name]}__#{ENV.fetch( 'USER', 'USER' )}"
84
+
85
+ if chroot
86
+ mock_cmd = mock_pre_check( chroot, @chroot_name, unique ) + " --root #{chroot}"
87
+
88
+ sh %Q(#{mock_cmd} --copyin #{spec_file} /tmp)
89
+ info_hash = {
90
+ :command => %Q(#{mock_cmd} --shell),
91
+ :rpm_extras => %(--specfile /tmp/#{File.basename(spec_file)} )
92
+ }
93
+
94
+ @spec_info = Simp::RPM.get_info(spec_file, info_hash)
95
+ end
96
+
97
+ @dir_name = "#{@spec_info[:name]}-#{@spec_info[:version]}"
98
+ @mfull_pkg_name = "#{@dir_name}-#{@spec_info[:release]}"
99
+ @full_pkg_name = @mfull_pkg_name.gsub("%{?snapshot_release}","")
100
+ @tar_dest = "#{@pkg_dir}/#{@full_pkg_name}.tar.gz"
101
+ @variants = (ENV['SIMP_BUILD_VARIANTS'].to_s.split(',') + ['default'])
102
+ end
103
+ end
80
104
 
81
105
  def define_clean
82
106
  desc <<-EOM
@@ -87,8 +111,6 @@ module Simp::Rake
87
111
  end
88
112
  end
89
113
 
90
-
91
-
92
114
  def define_clobber
93
115
  desc <<-EOM
94
116
  Clobber build artifacts for #{@pkg_name} (except for mock)
@@ -105,13 +127,19 @@ module Simp::Rake
105
127
  # :pkg:tar
106
128
  # -----------------------------
107
129
  desc <<-EOM
108
- Build the #{@pkg_name} tar package
130
+ Build the #{@pkg_name} tar package.
109
131
  * :snapshot_release - Add snapshot_release (date and time) to rpm
110
132
  version, rpm spec file must have macro for
111
133
  this to work.
112
134
  EOM
113
- task :tar,[:snapshot_release] => [@pkg_dir] do |t,args|
135
+ task :tar,[:chroot,:unique,:snapshot_release] => [@pkg_dir] do |t,args|
114
136
  args.with_defaults(:snapshot_release => false)
137
+ args.with_defaults(:unique => false)
138
+ args.with_defaults(:chroot => nil)
139
+
140
+ if args.chroot
141
+ initialize_spec_info(args.chroot, args.unique)
142
+ end
115
143
 
116
144
  l_date = ''
117
145
  if args.snapshot_release == 'true'
@@ -140,13 +168,26 @@ module Simp::Rake
140
168
  def define_pkg_srpm
141
169
  namespace :pkg do
142
170
  desc <<-EOM
143
- Build the #{@pkg_name} SRPM
171
+ Build the #{@pkg_name} SRPM.
144
172
  Building RPMs requires a working Mock setup (http://fedoraproject.org/wiki/Projects/Mock)
145
173
  * :chroot - The Mock chroot configuration to use. See the '--root' option in mock(1)."
146
174
  * :unique - Whether or not to build the SRPM in a unique Mock environment.
147
175
  This can be very useful for parallel builds of all modules.
148
176
  * :snapshot_release - Add snapshot_release (date and time) to rpm version.
149
177
  Rpm spec file must have macro for this to work.
178
+
179
+ Environment Variables
180
+ SIMP_BUILD_VARIANTS - A comma delimted list of the target versions of Puppet/PE to build toward.
181
+
182
+ Currently supported are 'pe', 'p4', 'pe-2015'.
183
+
184
+ These will build for Puppet Enterprise, Puppet 4, and
185
+ Puppet Enterprise 2015+ respectively.
186
+
187
+ Anything after a dash '-' will be considered a VERSION.
188
+
189
+ NOTE: Different RPM spec files may have different
190
+ behaviors based on the value passed.
150
191
  EOM
151
192
  task :srpm,[:chroot,:unique,:snapshot_release] => [:tar] do |t,args|
152
193
  args.with_defaults(:unique => false)
@@ -161,11 +202,20 @@ module Simp::Rake
161
202
 
162
203
  mock_cmd = mock_pre_check( args.chroot, @chroot_name, args.unique )
163
204
 
164
- srpms = Dir.glob(%(#{@pkg_dir}/#{@full_pkg_name}#{l_date}.*src.rpm))
205
+ @variants.each do |variant|
206
+ if variant != 'default'
207
+ suffix = "-#{variant}"
208
+ end
165
209
 
166
- if require_rebuild?(@tar_dest,srpms)
167
- cmd = %Q(#{mock_cmd} --no-clean --root #{args.chroot} #{mocksnap} --buildsrpm --spec #{@spec_file} --source #{@pkg_dir})
168
- sh cmd
210
+ srpms = Dir.glob(%(#{@pkg_dir}/#{@spec_info[:name]}#{suffix}-#{@spec_info[:version]}-#{@spec_info[:release]}#{l_date}.*.src.rpm))
211
+
212
+ if require_rebuild?(@tar_dest,srpms)
213
+ cmd = %Q(#{mock_cmd} --no-clean --root #{args.chroot} #{mocksnap} --buildsrpm --spec #{@spec_file} --source #{@pkg_dir})
214
+ if suffix
215
+ cmd += %( -D "_variant #{variant}")
216
+ end
217
+ sh cmd
218
+ end
169
219
  end
170
220
  end
171
221
  end
@@ -174,13 +224,26 @@ module Simp::Rake
174
224
  def define_pkg_rpm
175
225
  namespace :pkg do
176
226
  desc <<-EOM
177
- Build the #{@pkg_name} RPM
227
+ Build the #{@pkg_name} RPM.
178
228
  Building RPMs requires a working Mock setup (http://fedoraproject.org/wiki/Projects/Mock)
179
229
  * :chroot - The Mock chroot configuration to use. See the '--root' option in mock(1)."
180
230
  * :unique - Whether or not to build the RPM in a unique Mock environment.
181
231
  This can be very useful for parallel builds of all modules.
182
232
  * :snapshot_release - Add snapshot_release (date and time) to rpm version.
183
233
  Rpm spec file must have macro for this to work.
234
+
235
+ Environment Variables
236
+ SIMP_BUILD_VARIANTS - A comma delimted list of the target versions of Puppet/PE to build toward.
237
+
238
+ Currently supported are 'pe', 'p4', 'pe-2015'.
239
+
240
+ These will build for Puppet Enterprise, Puppet 4, and
241
+ Puppet Enterprise 2015+ respectively.
242
+
243
+ Anything after a dash '-' will be considered a VERSION.
244
+
245
+ NOTE: Different RPM spec files may have different
246
+ behaviors based on the value passed.
184
247
  EOM
185
248
  task :rpm,[:chroot,:unique,:snapshot_release] do |t,args|
186
249
  args.with_defaults(:unique => false)
@@ -197,14 +260,23 @@ module Simp::Rake
197
260
 
198
261
  mock_cmd = mock_pre_check(args.chroot, @chroot_name, args.unique)
199
262
 
200
- rpms = Dir.glob(%(#{@pkg_dir}/#{@full_pkg_name}#{l_date}*.rpm))
201
- srpms = rpms.select{|x| x =~ /src\.rpm$/}
202
- rpms = (rpms - srpms)
263
+ @variants.each do |variant|
264
+ if variant != 'default'
265
+ suffix = "-#{variant}"
266
+ end
203
267
 
204
- srpms.each do |srpm|
205
- if require_rebuild?(srpm,rpms)
206
- cmd = %Q(#{mock_cmd} --root #{args.chroot} #{mocksnap} #{srpm})
207
- sh cmd
268
+ rpms = Dir.glob(%(#{@pkg_dir}/#{@spec_info[:name]}#{suffix}-#{@spec_info[:version]}-#{@spec_info[:release]}#{l_date}.*.rpm))
269
+ srpms = rpms.select{|x| x =~ /src\.rpm$/}
270
+ rpms = (rpms - srpms)
271
+
272
+ srpms.each do |srpm|
273
+ if require_rebuild?(srpm,rpms)
274
+ cmd = %Q(#{mock_cmd} --root #{args.chroot} #{mocksnap} #{srpm})
275
+ if suffix
276
+ cmd += %( -D "_variant #{variant}")
277
+ end
278
+ sh cmd
279
+ end
208
280
  end
209
281
  end
210
282
  end
@@ -216,7 +288,7 @@ module Simp::Rake
216
288
  # :pkg:scrub
217
289
  # -----------------------------
218
290
  desc <<-EOM
219
- Scrub the #{@pkg_name} mock build directory
291
+ Scrub the #{@pkg_name} mock build directory.
220
292
  EOM
221
293
  task :scrub,[:chroot,:unique] do |t,args|
222
294
  args.with_defaults(:unique => false)
@@ -233,11 +305,6 @@ module Simp::Rake
233
305
  # ------------------------------------------------------------------------------
234
306
  # helper methods
235
307
  # ------------------------------------------------------------------------------
236
- # Pull the main RPM information out of the package spec file.
237
- def Pkg.get_info(specfile)
238
- return Simp::RPM.get_info(specfile)
239
- end
240
-
241
308
  # Get a list of all of the mock configs available on the system.
242
309
  def Pkg.get_mock_configs
243
310
  Dir.glob('/etc/mock/*.cfg').sort.map{ |x| x = File.basename(x,'.cfg')}
data/lib/simp/rpm.rb CHANGED
@@ -3,6 +3,7 @@ module Simp
3
3
  class Simp::RPM
4
4
  require 'expect'
5
5
  require 'pty'
6
+ require 'rake'
6
7
 
7
8
  @@gpg_keys = Hash.new
8
9
  attr_accessor :basename, :version, :release, :full_version, :name, :sources, :verbose
@@ -52,27 +53,31 @@ module Simp
52
53
 
53
54
  # Parses information, such as the version, from the given specfile or RPM
54
55
  # into a hash.
55
- def self.get_info(rpm_source)
56
- info = Hash.new
56
+ #
57
+ # Can take an optional mock hash that should have the following structure:
58
+ # {
59
+ # :command => The actual mock command to run
60
+ # :rpm_extras => Extra arguments to pass to RPM. This will probably be a
61
+ # reference to the spec file itself
62
+ # }
63
+ def self.get_info(rpm_source, mock_hash=nil)
64
+ info = Hash.new
65
+ rpm_cmd = "rpm -q --queryformat '%{NAME} %{VERSION} %{RELEASE}\n'"
66
+
67
+ if mock_hash
68
+ rpm_cmd = mock_hash[:command] + ' ' + '"' + rpm_cmd + ' ' + mock_hash[:rpm_extras] + '"'
69
+ end
70
+
57
71
  if File.readable?(rpm_source)
58
72
  if rpm_source.split('.').last == 'rpm'
59
- rpm_info = %x(rpm -q --queryformat '%{NAME} %{VERSION} %{RELEASE}' -p #{rpm_source} 2>/dev/null)
60
- info[:name],info[:version],info[:release] = rpm_info.split(' ')
73
+ rpm_info = %x(#{rpm_cmd} -p #{rpm_source} 2>/dev/null)
74
+ elsif mock_hash
75
+ rpm_info = %x(#{rpm_cmd})
61
76
  else
62
- File.open(rpm_source).each do |line|
63
- if line =~ /^\s*Version:\s+(.*)\s*/
64
- info[:version] = $1
65
- next
66
- elsif line =~ /^\s*Release:\s+(.*)\s*/
67
- # We don't want anything after the first '%'
68
- info[:release] = $1.split('%').first
69
- next
70
- elsif line =~ /^\s*Name:\s+(.*)\s*/
71
- info[:name] = $1
72
- next
73
- end
74
- end
77
+ rpm_info = %x(#{rpm_cmd} --specfile #{rpm_source} 2>/dev/null)
75
78
  end
79
+
80
+ info[:name],info[:version],info[:release] = rpm_info.split("\n").first.split(' ')
76
81
  else
77
82
  raise "Error: unable to read '#{rpm_source}'"
78
83
  end
@@ -189,7 +194,7 @@ module Simp
189
194
  end
190
195
  Process.wait(pid)
191
196
  end
192
-
197
+
193
198
  raise "Failure running #{signcommand}" unless $?.success?
194
199
  rescue Exception => e
195
200
  puts "Error occured while attempting to sign #{rpm}, skipping."
@@ -1,37 +1,32 @@
1
1
  Name: testpackage
2
2
  Version: 1
3
- Release: 0%{?dist}
4
- Summary: a test package
3
+ Release: 0
4
+ Summary: dummy test package
5
+ BuildArch: noarch
5
6
 
6
7
  License: Apache-2.0
7
- URL:
8
- Source0:
9
-
10
- BuildRequires:
11
- Requires:
8
+ URL: http://foo.bar
12
9
 
13
10
  %description
14
-
11
+ A dummy package used to test Simp::RPM methods
15
12
 
16
13
  %prep
17
- %setup -q
18
-
14
+ exit 0
19
15
 
20
16
  %build
21
- %configure
22
- make %{?_smp_mflags}
17
+ exit 0
23
18
 
24
19
 
25
20
  %install
26
- rm -rf $RPM_BUILD_ROOT
27
- %make_install
21
+ exit 0
28
22
 
23
+ %clean
24
+ exit 0
29
25
 
30
26
  %files
31
27
  %doc
32
28
 
33
29
 
34
-
35
30
  %changelog
36
31
  * Wed Jun 10 2015 nobody
37
32
  - some comment
@@ -0,0 +1,40 @@
1
+ Name: testpackage-multi-1
2
+ Version: 1
3
+ Release: 0
4
+ Summary: dummy test package #2
5
+ BuildArch: noarch
6
+
7
+ License: Apache-2.0
8
+ URL: http://foo.bar
9
+
10
+ %description
11
+ A dummy package used to test Simp::RPM methods
12
+
13
+ %prep
14
+ exit 0
15
+
16
+ %build
17
+ exit 0
18
+
19
+
20
+ %install
21
+ exit 0
22
+
23
+ %clean
24
+ exit 0
25
+
26
+ %files
27
+ %doc
28
+
29
+
30
+ %package testpackage-multi-2
31
+ Summary: dummy test package #2
32
+ License: Apache-2.0
33
+
34
+ %description testpackage-multi-2
35
+ A dummy package used to test Simp::RPM methods
36
+
37
+
38
+ %changelog
39
+ * Wed Jun 10 2015 nobody
40
+ - some comment
@@ -1,37 +1,32 @@
1
1
  Name: testpackage
2
2
  Version: 1
3
- Release: 0%{?dist}
4
- Summary: a test package
3
+ Release: 0
4
+ Summary: dummy test package
5
+ BuildArch: noarch
5
6
 
6
7
  License: Apache-2.0
7
- URL:
8
- Source0:
9
-
10
- BuildRequires:
11
- Requires:
8
+ URL: http://foo.bar
12
9
 
13
10
  %description
14
-
11
+ A dummy package used to test Simp::RPM methods
15
12
 
16
13
  %prep
17
- %setup -q
18
-
14
+ exit 0
19
15
 
20
16
  %build
21
- %configure
22
- make %{?_smp_mflags}
17
+ exit 0
23
18
 
24
19
 
25
20
  %install
26
- rm -rf $RPM_BUILD_ROOT
27
- %make_install
21
+ exit 0
28
22
 
23
+ %clean
24
+ exit 0
29
25
 
30
26
  %files
31
27
  %doc
32
28
 
33
29
 
34
-
35
30
  %changelog
36
31
  * Wed Jun 10 2015 nobody
37
32
  - some comment
@@ -3,15 +3,29 @@ require 'spec_helper'
3
3
 
4
4
  describe Simp::RPM do
5
5
  before :all do
6
- dir = File.expand_path( 'files', File.dirname( __FILE__ ) )
7
- @spec_file = File.join( dir, 'testpackage.spec' )
8
- @obj = Simp::RPM.new( @spec_file )
6
+ dir = File.expand_path( 'files', File.dirname( __FILE__ ) )
7
+ @spec_file = File.join( dir, 'testpackage.spec' )
8
+ @spec_obj = Simp::RPM.new( @spec_file )
9
+ @m_spec_file = File.join( dir, 'testpackage-multi.spec' )
10
+ @m_spec_obj = Simp::RPM.new( @spec_file )
11
+ @rpm_file = File.join( dir, 'testpackage-1-0.noarch.rpm' )
12
+ @rpm_obj = Simp::RPM.new( @spec_file )
9
13
  end
10
14
 
11
15
  describe "#initialize" do
12
- it "initializes (smoke test)" do
13
- expect( @obj.class ).to eq Simp::RPM
16
+
17
+ it "initializes w/RPM (smoke test)" do
18
+ expect( @rpm_obj.class ).to eq Simp::RPM
19
+ end
20
+
21
+ it "initializes w/spec file (smoke test)" do
22
+ expect( @spec_obj.class ).to eq Simp::RPM
14
23
  end
24
+
25
+ it "initializes w/multi-package spec file (smoke test)" do
26
+ expect( @m_spec_obj.class ).to eq Simp::RPM
27
+ end
28
+
15
29
  end
16
30
 
17
31
  describe ".get_info" do
@@ -20,5 +34,17 @@ describe Simp::RPM do
20
34
  expect( info.fetch( :name ) ).to eq 'testpackage'
21
35
  expect( info.fetch( :version ) ).to eq '1'
22
36
  end
37
+
38
+ it "extracts correct information from an .rpm file" do
39
+ info = Simp::RPM.get_info(@rpm_file)
40
+ expect( info.fetch( :name ) ).to eq 'testpackage'
41
+ expect( info.fetch( :version ) ).to eq '1'
42
+ end
43
+
44
+ it "extracts coreect information from the first entry from a multi-package .spec file" do
45
+ info = Simp::RPM.get_info(@m_spec_file)
46
+ expect( info.fetch( :name ) ).to eq 'testpackage-multi-1'
47
+ expect( info.fetch( :version ) ).to eq '1'
48
+ end
23
49
  end
24
50
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simp-rake-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.12
4
+ version: 1.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Tessmer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-14 00:00:00.000000000 Z
12
+ date: 2016-02-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -251,6 +251,8 @@ files:
251
251
  - lib/simp/rake/pkg.rb
252
252
  - lib/simp/rpm.rb
253
253
  - spec/lib/simp/files/build/testpackage.spec
254
+ - spec/lib/simp/files/testpackage-1-0.noarch.rpm
255
+ - spec/lib/simp/files/testpackage-multi.spec
254
256
  - spec/lib/simp/files/testpackage.spec
255
257
  - spec/lib/simp/rake/helpers_spec.rb
256
258
  - spec/lib/simp/rake/pkg_spec.rb