pkgr 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,7 +2,16 @@
2
2
 
3
3
  Plug this [Railtie](http://api.rubyonrails.org/classes/Rails/Railtie.html)
4
4
  into your Rails 3 app (ruby1.9 only), and you'll be ready to package your
5
- Rails app as a DEB package. RPM support could be added in the short future.
5
+ Rails app as a DEB package. RPM support could/will be added in the short
6
+ future.
7
+
8
+ This gem originates from hours spent trying to figure out how to package a
9
+ Ruby app for CentOS, and then Debian. It's definitely not trivial, because
10
+ there are so many pieces to put together before getting something working.
11
+ Hopefully this will save time for everyone :)
12
+
13
+ Fair warning: there are probably a few things that could be done better, or in
14
+ a more standard way. Feel free to open an issue and/or a pull-request.
6
15
 
7
16
  ## Why?
8
17
 
@@ -59,6 +68,8 @@ The default target installation directory for the other app files will be
59
68
  [`thin`](http://code.macournoyer.com/thin/) web server. Don't forget to add
60
69
  `thin` to your Gemfile!
61
70
 
71
+ * Your Rails application must have a `config.ru` file.
72
+
62
73
  * Your application must be checked into a **Git** repository. Your name and
63
74
  email is taken from the git configuration, and the changelog is populated
64
75
  based on the git log between two versions.
@@ -252,7 +263,7 @@ Now you can send a first request:
252
263
 
253
264
  Obviously this app does nothing, so you'll get a 404. So go back to building your app, and then just type `rake pkgr:bump:patch` and `HOST=debian-build-machine rake pkgr:build:deb` to generate a new package !
254
265
 
255
- ## Release it (debian)
266
+ ### Release it (debian)
256
267
 
257
268
  As of 0.2.0, you can now release the latest package on a server, and add it to
258
269
  your list of APT sources for easy installation. In the following we'll assume
@@ -368,6 +379,41 @@ Once you're ready to package your app, just run the following commands:
368
379
  app. Next step is probably to upload it to a local apt repository, and then
369
380
  a simple `apt-get install my-app` will install everything. Enjoy!
370
381
 
382
+ ## CLI usage
383
+
384
+ Starting from version 0.3.0, pkgr now comes with an executable, which allows
385
+ to package any app stored in a git repository with one command.
386
+
387
+ For instance, here is how you would package the Redmine app:
388
+
389
+ pkgr --uri https://github.com/edavis10/redmine --ref master --bump 1.4.1 \
390
+ -c https://raw.github.com/crohr/pkgr/master/examples/redmine/configuration.yml \
391
+ -c https://raw.github.com/crohr/pkgr/master/examples/redmine/database.yml \
392
+ -c https://raw.github.com/crohr/pkgr/master/examples/redmine/pkgr.yml \
393
+ --host debian-build
394
+
395
+ You .deb package will be available in `redmine/pkg/`. In this example, the given `pkgr.yml` configuration file automatically adds a dependency on `mysql-server`, which means that when you install the generated redmine package, it will be ready to be accessed on `0.0.0.0:8000`.
396
+
397
+ Note that for simple projects, you may not need to specify any configuration
398
+ file on the command line. See `pkgr -h` for the list of options available:
399
+
400
+ $ pkgr -h
401
+ * Description
402
+ pkgr 0.2.0 - Package Rails apps effortlessly.
403
+ * Usage
404
+ pkgr --uri GIT_REPOSITORY --config database.yml:http://path/to/database.yml --config ...
405
+
406
+ * Common options
407
+ --uri= Sets the Git repository URI (FILE, HTTP, SSH, GIT, etc.) [required]
408
+ -c, --config= Download a configuration file into the config/ folder of the app (HTTP or FILE URIs)
409
+ -b, --bump= Sets the app version [required]
410
+ -n, --name= Sets the app name [optional]
411
+ --ref= Sets the git reference to checkout [default=master]
412
+ --host= Sets the build machine hostname. If none, the process will stop just before building the package.
413
+
414
+ * Other
415
+ -h, --help Show this message
416
+ --version Show version
371
417
 
372
418
  ## Todo
373
419
 
@@ -378,6 +424,8 @@ Once you're ready to package your app, just run the following commands:
378
424
 
379
425
  * Better debian initd script.
380
426
 
427
+ * Populate dependencies based on gems declared in the Gemfile.
428
+
381
429
  * Some tests.
382
430
 
383
431
  ## Authors
@@ -1,5 +1,7 @@
1
1
  require 'rake'
2
2
  require 'erb'
3
+ require 'pkgr/version'
4
+ require 'yaml'
3
5
 
4
6
  module Pkgr
5
7
  class App
@@ -148,18 +150,24 @@ module Pkgr
148
150
  end
149
151
 
150
152
  # FIXME: this is ugly
151
- def bump!(version_index = :patch)
152
- indices = [:major, :minor, :patch]
153
- index = indices.index(version_index) || raise(ArgumentError, "The given version index is not valid (#{version_index})")
154
- version = @config.fetch('version') { '0.0.0' }
155
- fragments = version.split(".")
156
- fragments[index] = fragments[index].to_i+1
157
- ((index+1)..2).each{|i|
158
- fragments[i] = 0
159
- }
160
- new_version = fragments.join(".")
153
+ def bump!(version_index = :patch, new_version = nil)
154
+ unless version_index == :custom
155
+ indices = [:major, :minor, :patch]
156
+ index = indices.index(version_index) || raise(ArgumentError, "The given version index is not valid (#{version_index})")
157
+ fragments = version.split(".")
158
+ fragments[index] = fragments[index].to_i+1
159
+ ((index+1)..2).each{|i|
160
+ fragments[i] = 0
161
+ }
162
+ new_version = fragments.join(".")
163
+ else
164
+ raise ArgumentError, "new_version must not be nil when bumping with a :custom version" if new_version.nil?
165
+ end
161
166
 
162
167
  changelog = File.read(debian_file("changelog"))
168
+ dist = (changelog.scan(/#{name} \(#{new_version}-(\d+)\)/).flatten[0].to_i)
169
+ dist += 1 if new_version == version
170
+ dist = 1 if dist == 0
163
171
 
164
172
  last_commit = changelog.scan(/\s+\* ([a-z0-9]{7}) /).flatten[0]
165
173
 
@@ -171,7 +179,7 @@ module Pkgr
171
179
  raise "Command failed. Aborting."
172
180
  else
173
181
  content_changelog = [
174
- "#{name} (#{new_version}-1) unstable; urgency=low",
182
+ "#{name} (#{new_version}-#{dist}) unstable; urgency=low",
175
183
  "",
176
184
  result.split("\n").reject{|l| l =~ / v#{version}/}.map{|l| " * #{l}"}.join("\n"),
177
185
  "",
@@ -189,7 +197,7 @@ module Pkgr
189
197
 
190
198
  puts "Committing changelog and version file..."
191
199
  files_to_commit = [debian_file('changelog'), @config['_path']]
192
- sh "git add #{files_to_commit.join(" ")} && git commit -m 'v#{new_version}' #{files_to_commit.join(" ")}"
200
+ sh "git add #{files_to_commit.join(" ")} && git commit -m '[pkgr] v#{new_version}-#{dist}' #{files_to_commit.join(" ")}"
193
201
  end
194
202
  end
195
203
 
@@ -215,7 +223,7 @@ module Pkgr
215
223
  def debian_steps
216
224
  target_vendor = "vendor/bundle/ruby/1.9.1"
217
225
  [
218
- "sudo apt-get install #{debian_runtime_dependencies(true).join(" ")} -y",
226
+ # "sudo apt-get install #{debian_runtime_dependencies(true).join(" ")} -y",
219
227
  "sudo apt-get install #{debian_build_dependencies(true).join(" ")} -y",
220
228
  # Vendor bundler
221
229
  "gem1.9.1 install bundler --no-ri --no-rdoc --version #{bundler_version} -i #{target_vendor}",
@@ -248,8 +256,8 @@ module Pkgr
248
256
  end
249
257
 
250
258
  def debian_file(filename)
251
- file = File.join(Pkgr::DEBIAN_DIR, filename)
252
- return nil unless File.exist?(file)
259
+ file = File.join(root, Pkgr::DEBIAN_DIR, filename)
260
+ raise "The debian/changelog file does not exist. Please generate it first." unless File.exist?(file)
253
261
  file
254
262
  end
255
263
  end
@@ -0,0 +1,164 @@
1
+ require 'open-uri'
2
+ require 'fileutils'
3
+ require 'pkgr'
4
+ require 'uri'
5
+
6
+ module Pkgr
7
+ class CLI
8
+ include Rake::DSL
9
+
10
+ class Error < StandardError; end
11
+
12
+ attr_reader :errors
13
+ attr_reader :uri
14
+ attr_reader :dir
15
+ attr_reader :config_files
16
+ attr_reader :version
17
+ attr_reader :name
18
+ attr_reader :app
19
+ attr_reader :host
20
+ attr_reader :ref
21
+
22
+ def initialize(opts = {})
23
+ @errors = []
24
+ @uri, @config_files, @version, @name, @host, @ref = opts.values_at(
25
+ :uri, :config_files, :version, :name, :host, :ref
26
+ )
27
+ @app = nil
28
+ end
29
+
30
+ def run
31
+ raise Error, "Can't run pkgr: #{errors.join(", ")}" unless valid?
32
+ clone_repository
33
+ Dir.chdir(dir) do
34
+ checkout
35
+ copy_remote_config_files
36
+ copy_example_config_files
37
+ setup
38
+ bundle
39
+ configure_app
40
+ generate
41
+ bump
42
+ build
43
+ end
44
+ end
45
+
46
+ def valid?
47
+ @errors.clear
48
+ @errors.push("You must pass a repository URI through --uri") if uri.nil?
49
+ @errors.push("You must pass a version number through --bump") if version.nil?
50
+ @errors.empty?
51
+ end
52
+
53
+ def build
54
+ if host.nil?
55
+ puts "Can't build the package. You must pass the --host option for this."
56
+ else
57
+ @app.build_debian_package(host)
58
+ end
59
+ end
60
+
61
+ def bump
62
+ @app.bump!(:custom, version)
63
+ end
64
+
65
+ def bundle
66
+ sh "bundle install"
67
+ sh "git add -f Gemfile.lock"
68
+ sh "if git status --porcelain | grep Gemfile.lock; then git commit -m '[pkgr] Update Gemfile.lock.'; fi"
69
+ end
70
+
71
+ def checkout
72
+ sh "if git branch | grep '#{pkgr_branch}'; then git checkout #{pkgr_branch}; else git checkout -b #{pkgr_branch} #{ref}; fi"
73
+ end
74
+
75
+ def clone_repository
76
+ parsed_uri = URI.parse(uri)
77
+ case parsed_uri.scheme
78
+ when nil, "file"
79
+ @dir = parsed_uri.path
80
+ else
81
+ @dir = File.basename(uri, ".git")
82
+ sh "git clone #{uri}"
83
+ end
84
+ @dir = File.expand_path @dir
85
+ end
86
+
87
+ def configure_app
88
+ @app = Pkgr::App.new(dir, "config/pkgr.yml")
89
+ @app.config['git_ref'] = pkgr_branch
90
+ @app.config['config_files'].push(*Dir["config/*.yml"].map{|f| File.basename(f)}).uniq!
91
+ if name.nil?
92
+ @app.config['name'] = File.basename(dir) if @app.name.nil?
93
+ else
94
+ @app.config['name'] = name
95
+ end
96
+ raise Error, "The app is not correctly configured: #{@app.errors.join(", ")}" unless @app.valid?
97
+ @app.write_config
98
+ end
99
+
100
+ # Download the given config files
101
+ def copy_remote_config_files
102
+ (config_files || []).each do |file|
103
+ filename, file_uri = file.split("::")
104
+ if file_uri.nil?
105
+ file_uri = filename
106
+ filename = File.basename(file_uri)
107
+ end
108
+
109
+ file_uri = File.expand_path(file_uri) if URI.parse(file_uri).scheme.nil?
110
+ target = "config/#{filename}"
111
+ puts "Copying #{file_uri} into #{target}..."
112
+ File.open(target, "w+") { |f| f << open(file_uri).read }
113
+ end
114
+ end
115
+
116
+ def copy_example_config_files
117
+ [".example", ".dist"].each do |pattern|
118
+ Dir["config/*.yml#{pattern}"].each do |file|
119
+ target = File.basename(file, pattern)
120
+ unless File.exist?("config/#{target}")
121
+ FileUtils.cp(file, "config/#{target}")
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ def generate
128
+ @app.generate_required_files
129
+ sh "git add debian/"
130
+ sh "if git status --porcelain | grep debian/; then git commit -m '[pkgr] Add debian files.'; fi"
131
+ sh "git add bin/"
132
+ sh "if git status --porcelain | grep bin/; then git commit -m '[pkgr] Add executable file.'; fi"
133
+ end
134
+
135
+ def pkgr_branch
136
+ "pkgr-#{ref}"
137
+ end
138
+
139
+ def setup
140
+ Pkgr.setup(dir)
141
+
142
+ gemfile = File.read("Gemfile")
143
+ unless gemfile =~ /$gem 'pkgr'/
144
+ File.open("Gemfile", "a") do |f|
145
+ f.puts
146
+ f.puts "gem 'pkgr'"
147
+ end
148
+ end
149
+
150
+ unless gemfile =~ /$gem 'thin'/
151
+ File.open("Gemfile", "a") do |f|
152
+ f.puts
153
+ f.puts "gem 'pkgr'"
154
+ end
155
+ end
156
+
157
+ sh "git add Gemfile"
158
+ sh" if git status --porcelain | grep Gemfile; then git commit -m '[pkgr] Update Gemfile.'; fi"
159
+ sh "git add -f config/*.yml"
160
+ sh" if git status --porcelain | grep config/*.yml; then git commit -m '[pkgr] Update configuration files.'; fi"
161
+ end
162
+ end
163
+
164
+ end
@@ -23,10 +23,10 @@ namespace :pkgr do
23
23
  end
24
24
 
25
25
  namespace :bump do
26
- %w{patch minor major}.each do |version|
27
- desc "Increments the #{version} version by one"
26
+ %w{patch minor major custom}.each do |version|
27
+ desc "Increments the #{version} version. If using :custom, then you can pass a specific VERSION environment variable."
28
28
  task version.to_sym do
29
- APP.bump!(version.to_sym)
29
+ APP.bump!(version.to_sym, ENV.fetch('VERSION'))
30
30
  end
31
31
  end
32
32
  end
@@ -1,3 +1,3 @@
1
1
  module Pkgr
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pkgr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -16,17 +16,17 @@ dependencies:
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: '0.8'
22
- type: :development
21
+ version: '0'
22
+ type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ~>
27
+ - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: '0.8'
29
+ version: '0'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rspec
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -53,6 +53,7 @@ extra_rdoc_files:
53
53
  - README.md
54
54
  files:
55
55
  - lib/pkgr/app.rb
56
+ - lib/pkgr/cli.rb
56
57
  - lib/pkgr/data/bin/executable
57
58
  - lib/pkgr/data/config/pre_boot.rb
58
59
  - lib/pkgr/data/debian/changelog