pkgr 0.1.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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Cyril Rohr
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,149 @@
1
+ # pkgr
2
+
3
+ Plug this [Railtie](http://api.rubyonrails.org/classes/Rails/Railtie.html)
4
+ into your Rails 3 app (ruby1.9 only), and you'll be ready to package your
5
+ Rails app as a DEB or RPM (coming soon) package.
6
+
7
+ ## Why?
8
+
9
+ [Capistrano](http://capify.org/) is great for deploying Rails/Ruby
10
+ applications, but the deployment recipe can quickly become a mess, and scaling
11
+ the deployment to more than a few servers can prove to be difficult. Plus, if
12
+ you're already using automation tools such as
13
+ [Puppet](http://www.puppetlabs.com/) to configure your servers, you have to
14
+ run two different processes to configure your infrastructure.
15
+
16
+ Another issue with Capistrano is that the hook system is not that powerful.
17
+ Compare that with the pre/post-install/upgrade/uninstall steps that you can
18
+ define in a RPM or DEB package, and you'll quickly see the advantage of
19
+ letting a robust package manager such as `apt` or `yum` handle all those
20
+ things for you in a reliable manner.
21
+
22
+ Last thing, once you built your RPM or DEB package and you tested that it
23
+ works once, you can deploy it on any number of servers at any time and you're
24
+ sure that it will install the required package dependencies, run the hooks,
25
+ and put the files in the directories you specified, creating them as needed.
26
+ Then, you can downgrade or uninstall the whole application in one command.
27
+
28
+ ## How?
29
+
30
+ The issue with Ruby applications is that most of the gems are not (yet)
31
+ packaged in the various Linux distributions. And even if they were, installing
32
+ multiple Ruby applications that need two different versions of the same Ruby
33
+ library would be impossible, since you can't install two different (minor)
34
+ versions of a library with the package managers.
35
+
36
+ So, how are we going to easily package Ruby applications and avoid dependency
37
+ issues? Well, I know package maintainers will scream at me, but we'll just
38
+ vendor the required gems in the package we'll build, and use bundler to manage
39
+ those dependencies. Thus, the only dependency we'll put in our package will be
40
+ the Ruby1.9 (+rubygems).
41
+
42
+ ## What?
43
+
44
+ This gem will allow you to package your Rails3 application, create an `init.d`
45
+ script for you, install a binary file to start your app/rake tasks/console,
46
+ put your configuration files in `/etc/app-name/`, setup a proper logrotate
47
+ file so that your log files don't eat all the disk space of your server, and a
48
+ few other things.
49
+
50
+ The default target installation directory for the other app files will be
51
+ `/opt/local/app-name`. This can be configured.
52
+
53
+ ## Usage
54
+
55
+ Declare `pkgr` as one of your **development** dependencies in your `Gemfile`:
56
+
57
+ group :development do
58
+ gem 'pkgr'
59
+ end
60
+
61
+ Now make sure you have all the gems installed:
62
+
63
+ bundle install
64
+
65
+ `pkgr` will install a number of new rake tasks to handle the packaging
66
+ workflow. But first, you'll have to create a configuration file to get it
67
+ working:
68
+
69
+ rake pkgr:setup
70
+
71
+ This will create a configuration file at `config/pkgr.yml`. Edit it, and fill
72
+ in details about the `name` of your application, description, and the list of
73
+ runtime dependencies it depends on. Same for dependencies required at build
74
+ time only (most of the time, development headers).
75
+
76
+ Now you can generate all the files required for building a debian package:
77
+
78
+ rake pkgr:generate
79
+
80
+ A new directory `debian/` should have been created. You can have a look at it,
81
+ but you should not have to edit anything manually.
82
+
83
+ Once you're ready to package your app, just run the following steps:
84
+
85
+ * Increment the version number:
86
+
87
+ rake pkgr:bump:patch # or rake pkgr:bump:minor or rake pkgr:bump:major
88
+
89
+ * Re-generate the debian files:
90
+
91
+ rake pkgr:generate
92
+
93
+ * Commit your changes (the `pkgr` app will `git archive HEAD`, which means all
94
+ your changes must be committed first -- we may want to change this):
95
+
96
+ commit -am "..."
97
+
98
+ * Build the package on your machine (default, but you better be running a
99
+ Debian Squeeze), or on a remote machine (recommended, for instance you can
100
+ get a Vagrant VM in no time):
101
+
102
+ HOST=debian-build-machine rake pkgr:build:deb
103
+ # or HOST=localhost rake pkgr:build:deb, or just rake pkgr:build:deb
104
+
105
+ Note that the user with which you're connecting to the build machine **must
106
+ have `sudo` privileges** (required to install build and runtime
107
+ dependencies).
108
+
109
+ Also, it's most likely that you'll have to do this a few times at first, as
110
+ well as adding missing runtime and build dependencies, before your app can
111
+ be successfully packaged.
112
+
113
+ * Your .deb package should be made available in the `pkg` directory of your
114
+ app. Next step is probably to upload it to a local apt repository, and then
115
+ a simple `apt-get install my-app` will install everything. Enjoy!
116
+
117
+
118
+
119
+ ## Requirements
120
+
121
+ * You must use Rails3+ and ruby1.9+ in your application. This may work with
122
+ other rubies but then you'll need to add a rubygems dependency.
123
+
124
+ * Your Rails application must be able to run with the
125
+ [`thin`](http://code.macournoyer.com/thin/) web server. Don't forget to add
126
+ `thin` to your Gemfile!
127
+
128
+ * Your application must be checked into a **Git** repository. Your name and
129
+ email is taken from the git configuration, and the changelog is populated
130
+ based on the git log between two versions.
131
+
132
+ ## TODO
133
+
134
+ * Speed up the packaging process (currently, bundler re-downloads all the gems
135
+ each time you package an app).
136
+
137
+ * Include tasks for building RPMs.
138
+
139
+ * Better debian initd script.
140
+
141
+ * Some tests.
142
+
143
+ ## Authors
144
+
145
+ * Cyril Rohr <cyril.rohr@gmail.com> - <http://crohr.me>
146
+
147
+ ## Copyright
148
+
149
+ See LICENSE (MIT)
@@ -0,0 +1,35 @@
1
+ require 'pkgr/app'
2
+ require 'pkgr/railtie' if defined?(Rails)
3
+
4
+ module Pkgr
5
+ DEBIAN_DIR = "debian"
6
+
7
+ def self.setup(root)
8
+ setup_config(root)
9
+ end
10
+
11
+ protected
12
+
13
+ def self.setup_config(root)
14
+ puts "Setting up configuration file..."
15
+ target = File.join(root, "config", "pkgr.yml")
16
+ FileUtils.mkdir_p(File.dirname(target))
17
+ if File.exist?(target)
18
+ puts "'#{target}' already exists. Skipped."
19
+ else
20
+ FileUtils.cp(File.expand_path("../pkgr/data/pkgr.yml", __FILE__), target, :verbose => true)
21
+ puts "Edit '#{target}' and fill in the required information, then enter 'rake pkgr:generate:debian' to generate the debian control files."
22
+ end
23
+ end
24
+
25
+
26
+ def self.mkdir(target)
27
+ if File.directory?(target)
28
+ puts "#{target} directory already exists. Skipped."
29
+ elsif File.file?(target)
30
+ raise "#{target} already exists and is a file. Aborting."
31
+ else
32
+ FileUtils.mkdir_p target, :verbose => true
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,246 @@
1
+ require 'rake'
2
+ require 'erb'
3
+
4
+ module Pkgr
5
+ class App
6
+ include RakeFileUtils
7
+ attr_reader :root
8
+ attr_reader :errors
9
+ attr_reader :config
10
+
11
+ # +root+: the root directory of the app.
12
+ # +config+ a Configuration object, hosting the parameters defined in `config/pkgr.yml`.
13
+ def initialize(root, config_path)
14
+ @root = root
15
+ load_config(config_path)
16
+ @errors = []
17
+ end
18
+
19
+ def load_config(path)
20
+ @config = YAML::load_file(path)
21
+ raise ArgumentError, "The given configuration file at '#{path}' is not a well-formed YAML file. Please fix it or remove it and run 'rake pkgr:setup'" unless @config.kind_of?(Hash)
22
+ @config['_path'] = path
23
+ end
24
+
25
+ def write_config
26
+ File.open(@config['_path'] || raise("Don't know where to save myself!"), "w+") {|f|
27
+ YAML.dump(@config.reject{|k,v| k == '_path'}, f)
28
+ }
29
+ end
30
+
31
+ # Returns true if the app is correctly configured. Else otherwise.
32
+ def valid?
33
+ @errors.clear
34
+ @errors.push("is not a valid git repository") unless File.exist?(File.join(@root, ".git", "HEAD"))
35
+ @errors.push("must have a name") unless @config.fetch('name')
36
+ @errors.push("must have a valid name ([a-zA-Z0-9_-])") unless @config.fetch('name').scan(/[^a-z0-9\_\-]/i)
37
+ @errors.push("must have a version") unless @config.fetch('version')
38
+ @errors.push("must have a valid target architecture") unless @config.fetch('architecture')
39
+ @errors.empty?
40
+ end
41
+
42
+ def generate_required_files
43
+ setup_debian
44
+ setup_binary
45
+ end
46
+
47
+ def git_ref
48
+ @config.fetch('git_ref') { 'HEAD' }
49
+ end
50
+
51
+ def prefix
52
+ @config.fetch('prefix') { "/opt/local" }
53
+ end
54
+
55
+ def author_name
56
+ @author_name ||= `git config --get user.name`.chomp
57
+ end
58
+
59
+ def author_email
60
+ @author_email ||= `git config --get user.email`.chomp
61
+ end
62
+
63
+ def name
64
+ @config['name']
65
+ end
66
+
67
+ def description
68
+ @config['description'] || ""
69
+ end
70
+
71
+ def debian_build_dependencies(installable_only = false)
72
+ deps = @config['debian_build_dependencies'] || []
73
+ if installable_only
74
+ deps = deps.reject{|d| d =~ /[\$\{\}]/}.map{|d| d.split(/\s/)[0]}
75
+ end
76
+ deps
77
+ end
78
+
79
+ def debian_runtime_dependencies(installable_only = false)
80
+ deps = @config['debian_runtime_dependencies'] || []
81
+ if installable_only
82
+ deps = deps.reject{|d| d =~ /[\$\{\}]/}.map{|d| d.split(/\s/)[0]}
83
+ end
84
+ deps
85
+ end
86
+
87
+ def architecture
88
+ @config['architecture'] || "all"
89
+ end
90
+
91
+ def homepage
92
+ @config['homepage'] || ""
93
+ end
94
+
95
+ def config_files
96
+ @config['config_files'] || []
97
+ end
98
+
99
+ def version
100
+ @config['version']
101
+ end
102
+
103
+ def user
104
+ @config.fetch('user') { name }
105
+ end
106
+
107
+ def group
108
+ @config.fetch('group') { name }
109
+ end
110
+
111
+ # prefix without the leading slash.
112
+ def pkg_prefix
113
+ prefix[1..-1]
114
+ end
115
+
116
+ def setup_debian
117
+ target = File.join(root, Pkgr::DEBIAN_DIR)
118
+ Pkgr.mkdir(target)
119
+
120
+ Dir[File.expand_path("../data/debian/*", __FILE__)].each do |file|
121
+ case File.extname(file)
122
+ when ".erb"
123
+ file_target = File.join(target, File.basename(file, ".erb"))
124
+ File.open(file_target, "w+") do |f|
125
+ f << ERB.new(File.read(file)).result(binding)
126
+ end
127
+ else
128
+ file_target = File.join(target, File.basename(file))
129
+ if File.exist?(file_target)
130
+ puts "File #{file_target} already exists. Skipped."
131
+ else
132
+ FileUtils.cp(file, file_target, :verbose => true)
133
+ end
134
+ end
135
+ end
136
+
137
+ puts "Correctly set up debian files."
138
+ end
139
+
140
+ # Creates an executable file for easy launch of the server/console/rake tasks once it is installed.
141
+ # E.g. /usr/bin/my-app console, /usr/bin/my-app server start -p 8080
142
+ def setup_binary
143
+ target = File.join(root, "bin", name)
144
+ Pkgr.mkdir(File.dirname(target))
145
+ FileUtils.cp(File.expand_path("../data/bin/executable", __FILE__), target, :verbose => true)
146
+ FileUtils.chmod 0755, target, :verbose => true
147
+ puts "Correctly set up executable file. Try running './bin/#{name} console'."
148
+ end
149
+
150
+ # 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(".")
161
+
162
+ changelog = File.read(debian_file("changelog"))
163
+
164
+ last_commit = changelog.scan(/\s+\* ([a-z0-9]{7}) /).flatten[0]
165
+
166
+ cmd = "git log --oneline"
167
+ cmd << " #{last_commit}..#{git_ref}" unless last_commit.nil?
168
+ result = %x{#{cmd}}
169
+ ok = $?.exitstatus == 0
170
+ if !ok
171
+ raise "Command failed. Aborting."
172
+ else
173
+ content_changelog = [
174
+ "#{name} (#{new_version}-1) unstable; urgency=low",
175
+ "",
176
+ result.split("\n").reject{|l| l =~ / v#{version}/}.map{|l| " * #{l}"}.join("\n"),
177
+ "",
178
+ " -- #{author_name} <#{author_email}> #{Time.now.strftime("%a, %d %b %Y %H:%M:%S %z")}",
179
+ "",
180
+ changelog
181
+ ].join("\n")
182
+
183
+ File.open(debian_file("changelog"), "w+") do |f|
184
+ f << content_changelog
185
+ end
186
+
187
+ @config['version'] = new_version
188
+ write_config
189
+
190
+ puts "Committing changelog and version file..."
191
+ 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(" ")}"
193
+ end
194
+ end
195
+
196
+ def build_debian_package(host)
197
+ puts "Building debian package on '#{host}'..."
198
+ Dir.chdir(root) do
199
+ Pkgr.mkdir("pkg")
200
+ case host
201
+ when 'localhost'
202
+ debian_steps.each do |step|
203
+ sh step
204
+ end
205
+ else
206
+ archive = "#{name}-#{version}"
207
+ sh "scp #{File.expand_path("../data/config/pre_boot.rb", __FILE__)} #{host}:/tmp/"
208
+ cmd = %Q{
209
+ git archive #{git_ref} --prefix=#{archive}/ | ssh #{host} 'cat - > /tmp/#{archive}.tar &&
210
+ set -x && rm -rf /tmp/#{archive} &&
211
+ cd /tmp && tar xf #{archive}.tar && cd #{archive} &&
212
+ cat config/boot.rb >> /tmp/pre_boot.rb && cp -f /tmp/pre_boot.rb config/boot.rb &&
213
+ #{debian_steps.join(" &&\n")}'
214
+ }
215
+ sh cmd
216
+ # Fetch the .deb, and put it in the `pkg` directory
217
+ sh "scp #{host}:/tmp/#{name}_#{version}*.deb pkg/"
218
+ end
219
+ end
220
+ end
221
+
222
+ def debian_steps
223
+ target_vendor = "vendor/bundle/ruby/1.9.1"
224
+ [
225
+ "sudo apt-get install #{debian_runtime_dependencies(true).join(" ")} -y",
226
+ "sudo apt-get install #{debian_build_dependencies(true).join(" ")} -y",
227
+ # Vendor bundler
228
+ "gem1.9.1 install bundler --no-ri --no-rdoc --version #{bundler_version} -i #{target_vendor}",
229
+ "GEM_HOME='#{target_vendor}' #{target_vendor}/bin/bundle install --deployment --without test development",
230
+ "rm -rf #{target_vendor}/{cache,doc}",
231
+ "dpkg-buildpackage -us -uc -d"
232
+ ]
233
+ end
234
+
235
+ private
236
+ def bundler_version
237
+ @config.fetch('bundler_version') { '1.1.3' }
238
+ end
239
+
240
+ def debian_file(filename)
241
+ file = File.join(Pkgr::DEBIAN_DIR, filename)
242
+ return nil unless File.exist?(file)
243
+ file
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+
5
+ config = YAML.load_file(::File.expand_path("../../config/pkgr.yml", __FILE__))
6
+
7
+ require ::File.expand_path("../../config/boot", __FILE__)
8
+
9
+ supported_commands = ["server", "rake", "console"]
10
+ command = ARGV.shift
11
+
12
+ case command
13
+ when "rake"
14
+ ENV['RACK_ENV'] ||= "production"
15
+ ARGV << "-f" << ::File.expand_path("../../Rakefile", __FILE__)
16
+ require 'rake'
17
+ Rake.application.run
18
+ when "console"
19
+ APP_PATH = ::File.expand_path('../../config/application', __FILE__)
20
+ require ::File.expand_path('../../config/boot', __FILE__)
21
+ ARGV.push("production") if ARGV.empty?
22
+ ARGV.unshift("console")
23
+ require 'rails/commands'
24
+ when "server"
25
+ require 'thin'
26
+ rackup_file = ::File.expand_path('../../config.ru', __FILE__)
27
+ argv = ARGV
28
+ argv << ["-R", rackup_file] unless ARGV.include?("-R")
29
+ argv << ["-p", "8000"] unless ARGV.include?("-p")
30
+ argv << ["-e", "production"] unless ARGV.include?("-e")
31
+ argv << ["--tag", "#{config['name']}-#{config['version']}"] unless ARGV.include?("--tag")
32
+ Thin::Runner.new(argv.flatten).run!
33
+ else
34
+ STDERR.puts "You must choose one of the following commands: #{supported_commands.inspect}"
35
+ exit(1)
36
+ end
@@ -0,0 +1,15 @@
1
+ # This part of code is added by Pkgr, before the original content of the
2
+ # `config/boot.rb` file.
3
+ require 'rubygems'
4
+
5
+ # Attempts to use a vendored Bundler, if any
6
+ vendored_gems = File.expand_path(
7
+ '../../vendor/bundle/ruby/1.9.1/gems', __FILE__
8
+ )
9
+
10
+ vendored_bundler = Dir["#{vendored_gems}/bundler-*/lib"].sort.last
11
+
12
+ if !vendored_bundler.nil? && !$LOAD_PATH.include?(vendored_bundler)
13
+ $LOAD_PATH.unshift(vendored_bundler)
14
+ end
15
+
File without changes
@@ -0,0 +1,12 @@
1
+ Source: <%= name %>
2
+ Section: unknown
3
+ Priority: extra
4
+ Maintainer: <%= author_name %> <<%= author_email %>>
5
+ Build-Depends: <%= debian_build_dependencies.join(",") %>
6
+ Standards-Version: 3.7.3
7
+ Homepage: <%= homepage %>
8
+
9
+ Package: <%= name %>
10
+ Architecture: <%= architecture %>
11
+ Depends: <%= debian_runtime_dependencies.join(", ") %>
12
+ Description: <%= description %>
@@ -0,0 +1,17 @@
1
+ This package was debianized by Pkgr <http://crohr.me/pkgr> on <%= Time.now.to_s %>.
2
+
3
+ It was downloaded from <ssh://somewhere>
4
+
5
+ Upstream Author(s):
6
+
7
+ <%= author_name %> <<%=author_email %>>
8
+
9
+ Copyright:
10
+
11
+ Some copyright here
12
+
13
+ License:
14
+
15
+ <Put the license of the package here indented by 4 spaces>
16
+
17
+ The Debian packaging is public domain.
@@ -0,0 +1,4 @@
1
+ #
2
+ # Put your cron tasks here
3
+ #
4
+ # 0 4 * * * root [ -x /usr/bin/some_script ] && /usr/bin/some_script
@@ -0,0 +1,11 @@
1
+ # Defaults for <%= name %> initscript
2
+ # sourced by /etc/init.d/<%= name %>
3
+ # installed at /etc/default/<%= name %> by the maintainer scripts
4
+
5
+ #
6
+ # This is a POSIX shell fragment
7
+ #
8
+
9
+ # Additional options that are passed to the Daemon.
10
+ DAEMON_OPTS="server -d --pid $PIDFILE --user $NAME --group $NAME --log /var/log/$NAME/thin.log"
11
+
@@ -0,0 +1,2 @@
1
+ var/log/<%= name %>
2
+ var/db/<%= name %>
File without changes
@@ -0,0 +1,155 @@
1
+ #! /bin/sh
2
+ #
3
+ ### BEGIN INIT INFO
4
+ # Provides: <%= name %>
5
+ # Required-Start: $remote_fs $syslog
6
+ # Required-Stop: $remote_fs $syslog
7
+ # Default-Start: 2 3 4 5
8
+ # Default-Stop: 0 1 6
9
+ # Short-Description: Start <%= name %> app at boot time.
10
+ # Description: Enable service provided by <%= name %>.
11
+ ### END INIT INFO
12
+ #
13
+
14
+ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
15
+ NAME="<%= name %>"
16
+ DAEMON=/usr/bin/$NAME
17
+ DESC=$NAME
18
+
19
+ test -x $DAEMON || exit 0
20
+
21
+ LOGDIR=/var/log/$NAME
22
+ PIDFILE=/var/run/$NAME.pid
23
+ DODTIME=5 # Time to wait for the server to die, in seconds
24
+ # If this value is set too low you might not
25
+ # let some servers to die gracefully and
26
+ # 'restart' will not work
27
+
28
+ # Include defaults if available
29
+ if [ -f /etc/default/$NAME ] ; then
30
+ . /etc/default/$NAME
31
+ fi
32
+
33
+ set -e
34
+
35
+
36
+ running_pid()
37
+ {
38
+ # Check if a given process status name matches a given name
39
+ pid=$1
40
+ name=$2
41
+ [ -z "$pid" ] && return 1
42
+ [ ! -d /proc/$pid ] && return 1
43
+ cmd=`cat /proc/$pid/status | grep Name: | cut -f 2`
44
+ # Is this the expected child?
45
+ [ "$cmd" != "$name" ] && return 1
46
+ return 0
47
+ }
48
+
49
+ running()
50
+ {
51
+ # Check if the process is running looking at /proc
52
+ # (works for all users)
53
+ # No pidfile, probably no daemon present
54
+ [ ! -f "$PIDFILE" ] && return 1
55
+ # Obtain the pid
56
+ pid=`cat $PIDFILE`
57
+ running_pid $pid $NAME || return 1
58
+ return 0
59
+ }
60
+
61
+ force_stop() {
62
+ # Forcefully kill the process
63
+ [ ! -f "$PIDFILE" ] && return
64
+ if running ; then
65
+ kill -15 $pid
66
+ # Is it really dead?
67
+ [ -n "$DODTIME" ] && sleep "$DODTIME"s
68
+ if running ; then
69
+ kill -9 $pid
70
+ [ -n "$DODTIME" ] && sleep "$DODTIME"s
71
+ if running ; then
72
+ echo "Cannot kill $NAME (pid=$pid)!"
73
+ exit 1
74
+ fi
75
+ fi
76
+ fi
77
+ rm -f $PIDFILE
78
+ return 0
79
+ }
80
+
81
+ case "$1" in
82
+ start)
83
+ echo -n "Starting $DESC: "
84
+ if running ; then
85
+ echo "already running."
86
+ else
87
+ $DAEMON $DAEMON_OPTS start
88
+ # Needed to let Thin handle stale pid file.
89
+ sleep 1
90
+ if running ; then
91
+ echo "OK."
92
+ else
93
+ echo "ERROR."
94
+ fi
95
+ fi
96
+ ;;
97
+ stop)
98
+ echo -n "Stopping $DESC: "
99
+ $DAEMON $DAEMON_OPTS stop
100
+ echo "OK."
101
+ ;;
102
+ force-stop)
103
+ echo -n "Forcefully stopping $DESC: "
104
+ force_stop
105
+ if ! running ; then
106
+ echo "OK."
107
+ else
108
+ echo "ERROR."
109
+ fi
110
+ ;;
111
+ #reload)
112
+ #
113
+ # If the daemon can reload its config files on the fly
114
+ # for example by sending it SIGHUP, do it here.
115
+ #
116
+ # If the daemon responds to changes in its config file
117
+ # directly anyway, make this a do-nothing entry.
118
+ #
119
+ # echo "Reloading $DESC configuration files."
120
+ # start-stop-daemon --stop --signal 1 --quiet --pidfile \
121
+ # /var/run/$NAME.pid --exec $DAEMON
122
+ #;;
123
+ force-reload)
124
+ #
125
+ # If the "reload" option is implemented, move the "force-reload"
126
+ # option to the "reload" entry above. If not, "force-reload" is
127
+ # just the same as "restart" except that it does nothing if the
128
+ # daemon isn't already running.
129
+ # check wether $DAEMON is running. If so, restart
130
+ if running ; then
131
+ $0 restart
132
+ fi
133
+ ;;
134
+ restart)
135
+ echo "Restarting $DESC..."
136
+ $0 stop && $0 start
137
+ ;;
138
+ status)
139
+ echo -n "$NAME is "
140
+ if running ; then
141
+ echo "running."
142
+ else
143
+ echo "not running."
144
+ exit 1
145
+ fi
146
+ ;;
147
+ *)
148
+ N=/etc/init.d/$NAME
149
+ # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
150
+ echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2
151
+ exit 1
152
+ ;;
153
+ esac
154
+
155
+ exit 0
@@ -0,0 +1,16 @@
1
+ <% config_files.each do |file| %>
2
+ config/<%= file %> etc/<%= name %>
3
+ <% end %>
4
+ config <%= pkg_prefix %>/<%= name %>
5
+ .bundle <%= pkg_prefix %>/<%= name %>
6
+ Gemfile <%= pkg_prefix %>/<%= name %>
7
+ Gemfile.lock <%= pkg_prefix %>/<%= name %>
8
+ config.ru <%= pkg_prefix %>/<%= name %>
9
+ Rakefile <%= pkg_prefix %>/<%= name %>
10
+ app <%= pkg_prefix %>/<%= name %>
11
+ bin <%= pkg_prefix %>/<%= name %>
12
+ db/* var/db/<%= name %>
13
+ lib <%= pkg_prefix %>/<%= name %>
14
+ public <%= pkg_prefix %>/<%= name %>
15
+ script <%= pkg_prefix %>/<%= name %>
16
+ vendor <%= pkg_prefix %>/<%= name %>
@@ -0,0 +1,5 @@
1
+ <% config_files.each do |file| %>
2
+ etc/<%= name %>/<%= file %> <%= pkg_prefix %>/<%= name %>/config/<%= file %>
3
+ <% end %>
4
+ var/log/<%= name %> <%= pkg_prefix %>/<%= name %>/log
5
+ var/db/<%= name %> <%= pkg_prefix %>/<%= name %>/db
@@ -0,0 +1,10 @@
1
+ # <%= name %> logs:
2
+ /var/log/<%= name %>/*.log {
3
+ daily
4
+ missingok
5
+ rotate 14
6
+ compress
7
+ delaycompress
8
+ notifempty
9
+ copytruncate
10
+ }
@@ -0,0 +1,59 @@
1
+ #!/bin/sh
2
+ # postinst script for $NAME
3
+ #
4
+ # see: dh_installdeb(1)
5
+
6
+ set -e
7
+
8
+ # summary of how this script can be called:
9
+ # * <postinst> `configure' <most-recently-configured-version>
10
+ # * <old-postinst> `abort-upgrade' <new version>
11
+ # * <conflictor's-postinst> `abort-remove' `in-favour' <package>
12
+ # <new-version>
13
+ # * <postinst> `abort-remove'
14
+ # * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
15
+ # <failed-install-package> <version> `removing'
16
+ # <conflicting-package> <version>
17
+ # for details, see http://www.debian.org/doc/debian-policy/ or
18
+ # the debian-policy package
19
+
20
+ NAME="<%= name %>"
21
+ PREFIX="<%= prefix %>"
22
+ USER="<%= user %>"
23
+ GROUP="<%= group %>"
24
+
25
+ case "$1" in
26
+ configure)
27
+
28
+ if [ ! -f $PREFIX/$NAME/bin/$NAME.rb ]; then
29
+ mv $PREFIX/$NAME/bin/$NAME $PREFIX/$NAME/bin/$NAME.rb
30
+ fi
31
+ echo "#!/usr/bin/ruby1.9.1
32
+ require '$PREFIX/$NAME/bin/$NAME'
33
+ " > /usr/bin/$NAME && chmod a+x /usr/bin/$NAME
34
+ # Creating the user if it does not exist
35
+ if ! getent passwd $USER > /dev/null; then
36
+ adduser --no-create-home --system --group $GROUP
37
+ fi
38
+ chown -R $USER.$GROUP /etc/$NAME/
39
+ chown -R $USER.$GROUP /var/db/$NAME/
40
+ chown -R $USER.$GROUP /var/log/$NAME/
41
+ ;;
42
+
43
+ abort-upgrade|abort-remove|abort-deconfigure)
44
+ ;;
45
+
46
+ *)
47
+ echo "postinst called with unknown argument \`$1'" >&2
48
+ exit 1
49
+ ;;
50
+ esac
51
+
52
+ # dh_installdeb will replace this with shell code automatically
53
+ # generated by other debhelper scripts.
54
+
55
+ #DEBHELPER#
56
+
57
+ exit 0
58
+
59
+
@@ -0,0 +1,57 @@
1
+ #!/bin/sh
2
+ # prerm script for $NAME
3
+ #
4
+ # see: dh_installdeb(1)
5
+
6
+ set -e
7
+
8
+ # summary of how this script can be called:
9
+ # * <prerm> `remove'
10
+ # * <old-prerm> `upgrade' <new-version>
11
+ # * <new-prerm> `failed-upgrade' <old-version>
12
+ # * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
13
+ # * <deconfigured's-prerm> `deconfigure' `in-favour'
14
+ # <package-being-installed> <version> `removing'
15
+ # <conflicting-package> <version>
16
+ # for details, see http://www.debian.org/doc/debian-policy/ or
17
+ # the debian-policy package
18
+
19
+ NAME="<%= name %>"
20
+ PREFIX="<%= prefix %>"
21
+ USER="<%= user %>"
22
+ GROUP="<%= group %>"
23
+
24
+ cleanup()
25
+ {
26
+ /etc/init.d/$NAME stop || true
27
+ rm /usr/bin/$NAME
28
+ mv $PREFIX/$NAME/bin/$NAME.rb $PREFIX/$NAME/bin/$NAME
29
+ return 0;
30
+ }
31
+
32
+ case "$1" in
33
+ remove)
34
+ cleanup
35
+ deluser $USER || true
36
+ ;;
37
+ upgrade|deconfigure)
38
+ cleanup
39
+ ;;
40
+
41
+ failed-upgrade)
42
+ ;;
43
+
44
+ *)
45
+ echo "prerm called with unknown argument \`$1'" >&2
46
+ exit 1
47
+ ;;
48
+ esac
49
+
50
+ # dh_installdeb will replace this with shell code automatically
51
+ # generated by other debhelper scripts.
52
+
53
+ #DEBHELPER#
54
+
55
+ exit 0
56
+
57
+
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/make -f
2
+
3
+ export DH_VERBOSE=1
4
+
5
+
6
+ %:
7
+ dh $@
@@ -0,0 +1,31 @@
1
+ version: 0.0.0
2
+ name:
3
+ description:
4
+ # The git reference from which to build the package:
5
+ git_ref: HEAD
6
+ # The list of configuration files taht you want to see in /etc/{{name}}/
7
+ config_files:
8
+ - pkgr.yml
9
+ - database.yml
10
+ # The target architecture of the server on which your app will be built (must
11
+ # be the same as the one on which it is deployed):
12
+ architecture: amd64
13
+ # The list of dependencies required for your app to correctly run:
14
+ debian_runtime_dependencies:
15
+ - ${shlibs:Depends}
16
+ - ${misc:Depends}
17
+ - ruby1.9.1-full
18
+ - git-core
19
+ - libxml2
20
+ - libxslt1.1
21
+ # The list of dependencies required for your app to be packaged (i.e.
22
+ # dependencies of your app's gems + dependencies required to build the
23
+ # package):
24
+ debian_build_dependencies:
25
+ - debhelper (>= 7)
26
+ - dpkg-dev
27
+ - libmysqlclient15-dev
28
+ - libxml2-dev
29
+ - libxslt-dev
30
+ - libsqlite3-dev
31
+
@@ -0,0 +1,42 @@
1
+ # ROOT=. rake -I lib -f lib/pkgr/pkgr.rake pkgr:setup
2
+
3
+ require 'pkgr'
4
+ require 'fileutils'
5
+
6
+ ROOT = ENV.fetch('ROOT') { Rails.root }
7
+ CONFIG = ENV.fetch('CONFIG') { File.join(ROOT, "config/pkgr.yml") }
8
+ if File.exist?(CONFIG)
9
+ APP = Pkgr::App.new ROOT, CONFIG
10
+ APP.valid? || fail("There is an issue with the app you're trying to package: #{APP.errors.join(", ")}")
11
+ end
12
+
13
+ namespace :pkgr do
14
+
15
+ desc "Setup the required files for pkgr"
16
+ task :setup do
17
+ Pkgr.setup(ROOT)
18
+ end
19
+
20
+ if defined?(APP)
21
+ task :generate do
22
+ APP.generate_required_files
23
+ end
24
+
25
+ namespace :bump do
26
+ %w{patch minor major}.each do |version|
27
+ desc "Increments the #{version} version by one"
28
+ task version.to_sym do
29
+ APP.bump!(version.to_sym)
30
+ end
31
+ end
32
+ end
33
+
34
+ namespace :build do
35
+ desc "Builds the debian package"
36
+ task :deb do
37
+ build_host = ENV.fetch('HOST') { 'localhost' }
38
+ APP.build_debian_package(build_host)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ module Pkgr
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load File.expand_path("../pkgr.rake", __FILE__)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Pkgr
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pkgr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Cyril Rohr
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.8'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2'
46
+ description: Package your Rails apps as debian packages
47
+ email:
48
+ - cyril.rohr@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files:
52
+ - LICENSE
53
+ - README.md
54
+ files:
55
+ - lib/pkgr/app.rb
56
+ - lib/pkgr/data/bin/executable
57
+ - lib/pkgr/data/config/pre_boot.rb
58
+ - lib/pkgr/data/debian/changelog
59
+ - lib/pkgr/data/debian/compat.erb
60
+ - lib/pkgr/data/debian/control.erb
61
+ - lib/pkgr/data/debian/copyright.erb
62
+ - lib/pkgr/data/debian/cron.d
63
+ - lib/pkgr/data/debian/default.erb
64
+ - lib/pkgr/data/debian/dirs.erb
65
+ - lib/pkgr/data/debian/docs.erb
66
+ - lib/pkgr/data/debian/init.d.erb
67
+ - lib/pkgr/data/debian/install.erb
68
+ - lib/pkgr/data/debian/links.erb
69
+ - lib/pkgr/data/debian/logrotate.erb
70
+ - lib/pkgr/data/debian/postinst.erb
71
+ - lib/pkgr/data/debian/prerm.erb
72
+ - lib/pkgr/data/debian/rules.erb
73
+ - lib/pkgr/data/pkgr.yml
74
+ - lib/pkgr/pkgr.rake
75
+ - lib/pkgr/railtie.rb
76
+ - lib/pkgr/version.rb
77
+ - lib/pkgr.rb
78
+ - LICENSE
79
+ - README.md
80
+ homepage: http://github.com/crohr/pkgr
81
+ licenses: []
82
+ post_install_message:
83
+ rdoc_options:
84
+ - --charset=UTF-8
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '1.9'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '1.3'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.21
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Package your Rails apps as debian packages
105
+ test_files: []