pkgr 1.1.8 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,18 +2,20 @@
2
2
 
3
3
  ## Goal
4
4
 
5
- Make debian packages out of any app that can run on Heroku.
5
+ Make debian packages out of any Ruby or NodeJS app that can run on Heroku. Hosted service available at <https://pkgr.io/>.
6
6
 
7
- ## Supported distributions (64bits only)
7
+ More languages and target distributions will be added after thorough testing, though nothing prevents you from specifying a specific buildpack (see Usage).
8
8
 
9
- * Ubuntu precise
10
- * Debian squeeze / Ubuntu lucid
9
+ ## Supported distributions (64bits only)
11
10
 
12
- Note: packages can work on Debian wheezy, provided that libssl0.9.8 is installed. It has to be done manually though, as they're no longer provided in the default repositories.
11
+ * Ubuntu 12.04 ("Precise")
12
+ * Debian 7.4 ("Wheezy")
13
+ * Ubuntu 10.04 ("Lucid")
14
+ * Debian 6 ("Squeeze")
13
15
 
14
16
  ## Examples
15
17
 
16
- * See <http://deb.pkgr.io/> for examples of apps packaged with `pkgr` (e.g. Gitlab, Discourse).
18
+ See <https://pkgr.io/showcase> for examples of apps packaged with `pkgr` (Gitlab, Redmine, Discourse, Ghost, etc.).
17
19
 
18
20
  ## Installation
19
21
 
@@ -86,19 +88,24 @@ Finally, it's a great way to share your open source software with your users and
86
88
 
87
89
  ## What this does
88
90
 
89
- * Uses Heroku buildpacks to embed all your dependencies within the debian package. That way, no need to mess with stale system dependencies, and no need to install anything by hand. Also, we get for free all the hard work done by Heroku developers to make sure your app runs fine in an isolated way.
91
+ * Uses Heroku buildpacks to embed all the dependencies related to your application runtime within the debian package. For a Rails app for instance, this means that `pkgr` will embed the specific ruby runtime you asked for, along with all the gems specified in your Gemfile. However, all other dependencies you may need must be specified as additional system dependencies (see Usage). This avoids the 'packaging-the-world' approach used by other tools such as omnibus (with the pros and cons that come with it), but it still allows you to use the latest and greatest libraries for your language of choice. See this [blog post][background-pkgr] for more background.
92
+
93
+ [background-pkgr]: http://blog.pkgr.io/post/81988994454/why-i-made-pkgr-io-digressions-on-software-packaging
90
94
 
91
95
  * Gives you a nice executable, which closely replicates the Heroku toolbelt utility. For instance, assuming you're packaging an app called `my-app`, you can do the following:
92
96
 
93
97
  my-app config:set VAR=value
94
98
  my-app config:get VAR
95
- my-app run [procfile process] # e.g. my-app run rake db:migrate, my-app run console, etc.
99
+ my-app run [procfile process] # e.g. my-app run rake db:migrate; my-app run console; etc.
100
+ my-app run [arbitrary process] # e.g. my-app run ruby -v; my-app run bundle install; etc.
96
101
  my-app scale web=1 worker=1
97
102
  ...
98
103
 
99
104
  * Your app will reside in `/opt/app-name`.
100
105
 
101
- * You'll also get a upstart based initialization script that you can use directly.
106
+ * You'll also get upstart (or sysvinit) initialization scripts that you can use directly:
107
+
108
+ service my-app start/stop/restart/status
102
109
 
103
110
  * Logs will be stored in `/var/log/app-name/`, with a proper logrotate config automatically added.
104
111
 
data/lib/pkgr/builder.rb CHANGED
@@ -95,6 +95,8 @@ module Pkgr
95
95
  process_file = File.join(proc_dir, process.name)
96
96
 
97
97
  File.open(process_file, "w+") do |f|
98
+ f.puts "#!/bin/sh"
99
+ f << "exec "
98
100
  f << process.command
99
101
  f << " $@"
100
102
  end
@@ -37,6 +37,7 @@ module Pkgr
37
37
 
38
38
  def compile(path, compile_cache_dir)
39
39
  cmd = %{env -i PATH="$PATH"#{env} #{dir}/bin/compile "#{path}" "#{compile_cache_dir}" }
40
+ Pkgr.debug "Running #{cmd.inspect}"
40
41
 
41
42
  Dir.chdir(path) do
42
43
  IO.popen(cmd) do |io|
data/lib/pkgr/cli.rb CHANGED
@@ -26,6 +26,9 @@ module Pkgr
26
26
  method_option :buildpack,
27
27
  :type => :string,
28
28
  :desc => "Custom buildpack to use"
29
+ method_option :buildpack_list,
30
+ :type => :string,
31
+ :desc => "Specify a file containing a list of buildpacks to use (--buildpack takes precedence if given)"
29
32
  method_option :target,
30
33
  :type => :string,
31
34
  :default => "deb",
@@ -33,6 +36,9 @@ module Pkgr
33
36
  method_option :changelog,
34
37
  :type => :string,
35
38
  :desc => "Changelog"
39
+ method_option :maintainer,
40
+ :type => :string,
41
+ :desc => "Maintainer"
36
42
  method_option :architecture,
37
43
  :type => :string,
38
44
  :default => "x86_64",
@@ -101,10 +107,17 @@ module Pkgr
101
107
 
102
108
  packager = Dispatcher.new(tarball, options)
103
109
  packager.call
104
- rescue Pkgr::Errors::Base => e
105
- Pkgr.error "#{e.class.name} : #{e.message}"
106
- puts "* ERROR: #{e.message}"
110
+ rescue => e
111
+ Pkgr.debug "#{e.class.name} : #{e.message}"
112
+ e.backtrace.each{|line| Pkgr.debug line}
113
+ puts " ! ERROR: #{e.message}"
107
114
  exit 1
115
+ # Only used for logging. Re-raise immediately.
116
+ rescue Exception => e
117
+ Pkgr.debug "#{e.class.name} : #{e.message}"
118
+ e.backtrace.each{|line| Pkgr.debug line}
119
+ puts " ! SYSTEM ERROR: #{e.class.name} : #{e.message}"
120
+ raise e
108
121
  end
109
122
  end
110
123
  end
data/lib/pkgr/config.rb CHANGED
@@ -71,6 +71,10 @@ module Pkgr
71
71
  @table[:description] || "No description given"
72
72
  end
73
73
 
74
+ def maintainer
75
+ @table[:maintainer] || "<someone@pkgr>"
76
+ end
77
+
74
78
  def env
75
79
  Pkgr::Env.new(@table[:env])
76
80
  end
@@ -135,12 +139,14 @@ module Pkgr
135
139
  "--architecture \"#{architecture}\"",
136
140
  "--target \"#{target}\"",
137
141
  "--description \"#{description}\"",
142
+ "--maintainer \"#{maintainer}\""
138
143
  ]
139
144
  args.push "--dependencies #{dependencies.map{|d| "\"#{d}\""}.join}" unless dependencies.nil? || dependencies.empty?
140
145
  args.push "--build-dependencies #{build_dependencies.map{|d| "\"#{d}\""}.join}" unless build_dependencies.nil? || build_dependencies.empty?
141
146
  args.push "--compile-cache-dir \"#{compile_cache_dir}\"" unless compile_cache_dir.nil? || compile_cache_dir.empty?
142
147
  args.push "--before-precompile \"#{before_precompile}\"" unless before_precompile.nil? || before_precompile.empty?
143
148
  args.push "--buildpack \"#{buildpack}\"" unless buildpack.nil? || buildpack.empty?
149
+ args.push "--buildpack_list \"#{buildpack_list}\"" unless buildpack_list.nil? || buildpack_list.empty?
144
150
  args.push "--force-os \"#{force_os}\"" unless force_os.nil? || force_os.empty?
145
151
  args.push "--env #{env.variables.map{|v| "\"#{v}\""}.join(" ")}" if env.present?
146
152
  args.push "--auto" if auto
@@ -0,0 +1,2 @@
1
+ https://github.com/heroku/heroku-buildpack-ruby.git
2
+ https://github.com/heroku/heroku-buildpack-nodejs.git
@@ -0,0 +1,2 @@
1
+ https://github.com/pkgr/heroku-buildpack-ruby.git#487c79e8cc3ab038ac13fef82d1e59a9c6ac39e6,BUILDPACK_VENDOR_URL="https://s3-external-1.amazonaws.com/pkgr-buildpack-ruby/20140408175240-debian-7.4",BUILDPACK_NODE_VERSION="0.6.8"
2
+ https://github.com/heroku/heroku-buildpack-nodejs.git#v58
@@ -0,0 +1,2 @@
1
+ https://github.com/heroku/heroku-buildpack-ruby.git
2
+ https://github.com/heroku/heroku-buildpack-nodejs.git
@@ -0,0 +1,2 @@
1
+ https://github.com/pkgr/heroku-buildpack-ruby.git#487c79e8cc3ab038ac13fef82d1e59a9c6ac39e6,BUILDPACK_VENDOR_URL="https://s3-external-1.amazonaws.com/pkgr-buildpack-ruby/20140408175240-ubuntu-12.04",BUILDPACK_NODE_VERSION="0.6.8"
2
+ https://github.com/heroku/heroku-buildpack-nodejs.git#v58
@@ -1,5 +1,4 @@
1
1
  default:
2
- - upstart
3
2
  - mysql-common
4
3
  - libpq5
5
4
  - libsqlite3-0
@@ -24,4 +24,4 @@ export DATABASE_URL=db_adapter://db_user:db_password@db_host/db_name
24
24
  export PORT=\${PORT:=6000}
25
25
  CONF
26
26
 
27
- chmod -R 0600 /etc/${APP_NAME}
27
+ chmod -R 0600 /etc/${APP_NAME}/conf.d
@@ -1,4 +1,5 @@
1
1
  #!/bin/bash
2
+ # Generated by pkgr.
2
3
 
3
4
  set -e
4
5
 
@@ -20,8 +21,149 @@ fi
20
21
 
21
22
  DEFAULT_FILE=/etc/default/<%= name %>
22
23
 
24
+ # Source all environment variables for the app. This must be done as
25
+ # privileged user since the config variables are only readable by root.
23
26
  . ${DEFAULT_FILE}
24
27
 
28
+ # Returns the type of process manager supported by the current distribution.
29
+ function process_manager() {
30
+ version=$(cat /etc/debian_version)
31
+
32
+ case "$version" in
33
+ wheezy*|squeeze*)
34
+ init_system="upstart"
35
+ ;;
36
+ *)
37
+ init_system="sysv"
38
+ ;;
39
+ esac
40
+
41
+ echo "${init_system}"
42
+ }
43
+
44
+ # You can force a specific process manager by setting the PROCESS_MANAGER
45
+ # environment variable.
46
+ PROCESS_MANAGER=${PROCESS_MANAGER:=$(process_manager)}
47
+
48
+ function current_number_of_processes() {
49
+ PROCESS_NAME="$1"
50
+ if [ "${PROCESS_MANAGER}" = "upstart" ]; then
51
+ echo $(ls -rv1 /etc/init/${APP_NAME}-${PROCESS_NAME}-*.conf 2>/dev/null | head -1 | sed -r 's/.*\-([0-9]+)\.conf/\1/g')
52
+ else
53
+ echo $(ls -rv1 /etc/init.d/${APP_NAME}-${PROCESS_NAME}-* 2>/dev/null | head -1 | sed -r 's/.*\-([0-9]+)/\1/g')
54
+ fi
55
+
56
+ return 0
57
+ }
58
+
59
+ function update_port() {
60
+ file="$1"
61
+ process_name="$2"
62
+ port="$3"
63
+ index="$4"
64
+
65
+ sed -i "s/PROCESS_NUM/${index}/g" "${file}"
66
+ if [ "${process_name}" = "web" ]; then
67
+ sed -i "s/PORT_NUM/${port}/g" "${file}"
68
+ else
69
+ sed -i "s/^env .*PORT_NUM.*$//g" "${file}"
70
+ sed -i "s/^export PORT=PORT_NUM$//g" "${file}"
71
+ fi
72
+ }
73
+
74
+ function scale_up() {
75
+ PROCESS_NAME="${1}"
76
+ CURRENT_SCALE=${2}
77
+ NEW_SCALE=${3}
78
+ SCALE_DELTA=${4}
79
+
80
+ echo "Scaling up..."
81
+
82
+ if [ "${PROCESS_MANAGER}" = "upstart" ]; then
83
+ cp "${HOME}/vendor/pkgr/scaling/upstart/${APP_NAME}.conf" /etc/init/
84
+ cp "${HOME}/vendor/pkgr/scaling/upstart/${APP_NAME}-${PROCESS_NAME}.conf" /etc/init/
85
+ for i in $(seq ${SCALE_DELTA}); do
86
+ index=$((${i} + ${CURRENT_SCALE}))
87
+ PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${index}"
88
+ cp "${HOME}/vendor/pkgr/scaling/upstart/${APP_NAME}-${PROCESS_NAME}-PROCESS_NUM.conf" "/etc/init/${PROCESS_ID}.conf"
89
+ port=$((${PORT} + ${index} - 1))
90
+
91
+ update_port "/etc/init/${PROCESS_ID}.conf" "${PROCESS_NAME}" $port $index
92
+
93
+ service "${PROCESS_ID}" start
94
+ done
95
+
96
+ service ${APP_NAME}-${PROCESS_NAME} start || true
97
+ service ${APP_NAME} start || true
98
+ else
99
+ cp "${HOME}/vendor/pkgr/scaling/sysv/${APP_NAME}" /etc/init.d/
100
+ chmod a+x /etc/init.d/${APP_NAME}
101
+ update-rc.d ${APP_NAME} defaults
102
+ cp "${HOME}/vendor/pkgr/scaling/sysv/${APP_NAME}-${PROCESS_NAME}" /etc/init.d/
103
+ chmod a+x /etc/init.d/${APP_NAME}-${PROCESS_NAME}
104
+ update-rc.d ${APP_NAME}-${PROCESS_NAME} defaults
105
+ for i in $(seq ${SCALE_DELTA}); do
106
+ index=$((${i} + ${CURRENT_SCALE}))
107
+ PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${index}"
108
+ cp "${HOME}/vendor/pkgr/scaling/sysv/${APP_NAME}-${PROCESS_NAME}-PROCESS_NUM" "/etc/init.d/${PROCESS_ID}"
109
+ port=$((${PORT} + ${index} - 1))
110
+
111
+ update_port "/etc/init.d/${PROCESS_ID}" "${PROCESS_NAME}" $port $index
112
+
113
+ chmod a+x /etc/init.d/${PROCESS_ID}
114
+ update-rc.d ${PROCESS_ID} defaults
115
+ /etc/init.d/${PROCESS_ID} start
116
+ done
117
+ fi
118
+ echo "--> done."
119
+ }
120
+
121
+ function scale_down() {
122
+ PROCESS_NAME="${1}"
123
+ CURRENT_SCALE=${2}
124
+ NEW_SCALE=${3}
125
+ SCALE_DELTA=${4}
126
+
127
+ echo "Scaling down..."
128
+ for i in $(seq $(($SCALE_DELTA * -1))); do
129
+ index=$((${i} + ${NEW_SCALE}))
130
+ PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${index}"
131
+
132
+ if [ "${PROCESS_MANAGER}" = "upstart" ]; then
133
+ service "${PROCESS_ID}" stop
134
+ rm -f "/etc/init/${PROCESS_ID}.conf"
135
+ else
136
+ /etc/init.d/${PROCESS_ID} stop
137
+ update-rc.d -f ${PROCESS_ID} remove
138
+ rm -f "/etc/init.d/${PROCESS_ID}"
139
+ fi
140
+ done
141
+ echo "--> done."
142
+ }
143
+
144
+ # Scale processes
145
+ function scale() {
146
+ PROCESS_NAME="$1"
147
+ NEW_SCALE="$2"
148
+
149
+ CURRENT_SCALE=$(current_number_of_processes ${PROCESS_NAME})
150
+ CURRENT_SCALE=${CURRENT_SCALE:="0"}
151
+ SCALE_DELTA=$((${NEW_SCALE} - ${CURRENT_SCALE}))
152
+
153
+ if [ $SCALE_DELTA -gt 0 ]; then
154
+ scale_up "${PROCESS_NAME}" $CURRENT_SCALE $NEW_SCALE $SCALE_DELTA
155
+ elif [ $SCALE_DELTA -lt 0 ]; then
156
+ scale_down "${PROCESS_NAME}" $CURRENT_SCALE $NEW_SCALE $SCALE_DELTA
157
+ else
158
+ echo "Nothing to do."
159
+ fi
160
+ }
161
+
162
+ # Return all the environment variables accessible to the app.
163
+ function show_env() {
164
+ env -i ${0} run env | sort
165
+ }
166
+
25
167
  while : ; do
26
168
  case "$1" in
27
169
  run)
@@ -29,7 +171,25 @@ while : ; do
29
171
  COMMAND="$2"
30
172
  shift 2
31
173
 
32
- exec su -m - "${APP_USER}" -c ". ${DEFAULT_FILE} && cd ${HOME} && if [ -f vendor/pkgr/processes/${COMMAND} ]; then vendor/pkgr/processes/${COMMAND} ${*}; else ${COMMAND} ${*}; fi"
174
+ runnable=$(echo -n "cd ${HOME} && exec")
175
+
176
+ if [ -f "${HOME}/vendor/pkgr/processes/${COMMAND}" ]; then
177
+ # Command alias defined in Procfile
178
+ runnable="${runnable}$(printf " %q" "vendor/pkgr/processes/${COMMAND}" "$@")"
179
+ else
180
+ # Everything else.
181
+ #
182
+ # We're going through printf to preserve quotes in arguments. See
183
+ # <http://stackoverflow.com/questions/10835933 /preserve-quotes-in-
184
+ # bash-arguments>.
185
+ runnable="${runnable}$(printf " %q" ${COMMAND} "$@")"
186
+ fi
187
+
188
+ # Do not use su, to avoid creating a new process. Note: chroot version
189
+ # is too old on Ubuntu Lucid, so this will fail. It works on Debian
190
+ # Squeeze though (and later).
191
+ exec chroot --userspec ${APP_USER}:${APP_GROUP} / sh -c "$runnable"
192
+
33
193
  break ;;
34
194
 
35
195
  scale)
@@ -37,57 +197,18 @@ while : ; do
37
197
  for arg in "$@"; do
38
198
  [ "$arg" = "" ] && usage
39
199
 
40
- PROCESS=(${arg//=/ })
41
-
42
- set +e
43
- PROCESS_NAME=${PROCESS[0]}
44
- NEW_SCALE=${PROCESS[1]}
45
- CURRENT_SCALE=$(ls -rv1 /etc/init/${APP_NAME}-${PROCESS_NAME}-*.conf 2>/dev/null | head -1 | sed -r 's/.*\-([0-9]+)\.conf/\1/g')
46
- CURRENT_SCALE=${CURRENT_SCALE:="0"}
47
- SCALE_DELTA=$(expr ${NEW_SCALE} - ${CURRENT_SCALE})
48
- set -e
49
-
50
- if [ $NEW_SCALE -eq 0 ]; then
51
- echo "Stopping all ${PROCESS_NAME} processes... "
52
- for file in `ls -1 /etc/init/${APP_NAME}-${PROCESS_NAME}-*.conf 2>/dev/null`; do
53
- service "$(basename ${file} .conf)" stop || true
54
- rm "${file}"
55
- done
56
- # Finally, remove master process
57
- rm -f "/etc/init/${APP_NAME}-${PROCESS_NAME}.conf"
58
- echo "--> done."
59
- elif [ $SCALE_DELTA -gt 0 ]; then
60
- echo "Scaling up..."
61
- cp "${HOME}/vendor/pkgr/scaling/${APP_NAME}-${PROCESS_NAME}.conf" /etc/init/
62
- for i in $(seq ${SCALE_DELTA}); do
63
- PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${i}"
64
- i=$(expr ${i} + ${CURRENT_SCALE})
65
- cp "${HOME}/vendor/pkgr/scaling/${APP_NAME}-${PROCESS_NAME}-PROCESS_NUM.conf" "/etc/init/${PROCESS_ID}.conf"
66
- sed -i "s/PROCESS_NUM/${i}/g" "/etc/init/${PROCESS_ID}.conf"
67
- if [ "${PROCESS_NAME}" = "web" ]; then
68
- port=$(expr ${PORT} + ${i} - 1)
69
- sed -i "s/PORT_NUM/${port}/g" "/etc/init/${PROCESS_ID}.conf"
70
- else
71
- sed -i "s/^env .*PORT_NUM.*$//g" "/etc/init/${PROCESS_ID}.conf"
72
- fi
73
- service "${PROCESS_ID}" start
74
- done
75
- echo "--> done."
76
- elif [ $SCALE_DELTA -lt 0 ]; then
77
- echo "Scaling down..."
78
- for i in $(seq $(expr $SCALE_DELTA \* -1)); do
79
- PROCESS_ID="${APP_NAME}-${PROCESS_NAME}-${i}"
80
- i=$(expr ${i} + ${NEW_SCALE})
81
- service "${PROCESS_ID}" stop || true
82
- rm -f "/etc/init/${PROCESS_ID}.conf"
83
- done
84
- echo "--> done."
85
- else
86
- echo "Nothing to do."
87
- fi
200
+ process=(${arg//=/ })
201
+ process_name=${process[0]}
202
+ new_scale=${process[1]}
203
+
204
+ scale "${process_name}" "${new_scale}"
88
205
  done
89
206
  break ;;
90
207
 
208
+ config)
209
+ show_env
210
+ break;;
211
+
91
212
  config:set)
92
213
  [ $# -lt 2 ] && usage
93
214
 
@@ -106,8 +227,7 @@ while : ; do
106
227
 
107
228
  config:get)
108
229
  [ $# -lt 2 ] && usage
109
- result=$(grep --no-filename "${2}" ${DEFAULT_FILE} /etc/${APP_NAME}/conf.d/*)
110
- echo "${result}" | sed -r "s/^export\s+${2}=//g"
230
+ show_env | grep -e "^${2}=" | sed -r "s/^${2}=//"
111
231
  break;;
112
232
 
113
233
  *)
@@ -0,0 +1,34 @@
1
+ #!/bin/sh
2
+ # Init script for <%= name %>
3
+ # Generated by pkgr.
4
+ # Implemented based on LSB Core 3.1:
5
+ # * Sections: 20.2, 20.3
6
+ #
7
+ ### BEGIN INIT INFO
8
+ # Provides: <%= name %>
9
+ # Required-Start: $remote_fs $syslog
10
+ # Required-Stop: $remote_fs $syslog
11
+ # Default-Start: 2 3 4 5
12
+ # Default-Stop: 0 1 6
13
+ # Description: <%= description %>
14
+ ### END INIT INFO
15
+
16
+ set -e
17
+
18
+ name="<%= name %>"
19
+
20
+ delegate() {
21
+ for file in $(ls -1 /etc/init.d/${name}-*[!-0-9] 2>/dev/null); do
22
+ ${file} "${1}"
23
+ done
24
+ }
25
+
26
+ case "$1" in
27
+ start|stop|force-stop|status|restart) delegate "${1}" ;;
28
+ *)
29
+ echo "Usage: $SCRIPTNAME {start|stop|force-stop|status|restart}" >&2
30
+ exit 3
31
+ ;;
32
+ esac
33
+
34
+ exit $?
@@ -0,0 +1,103 @@
1
+ #!/bin/sh
2
+ # Init script for <%= name %>-<%= process_name %>-PROCESS_NUM
3
+ # Generated by pkgr, heavily borrowed from pleaserun
4
+ # Implemented based on LSB Core 3.1:
5
+ # * Sections: 20.2, 20.3
6
+ #
7
+ ### BEGIN INIT INFO
8
+ # Provides: <%= name %>-<%= process_name %>-PROCESS_NUM
9
+ # Required-Start: <%= name %>-<%= process_name %>
10
+ # Required-Stop: <%= name %>-<%= process_name %>
11
+ # Default-Start: 2 3 4 5
12
+ # Default-Stop: 0 1 6
13
+ # Description: <%= process_name %> component of <%= name %> (PROCESS_NUM)
14
+ ### END INIT INFO
15
+
16
+ export PATH=/sbin:/usr/sbin:/bin:/usr/bin
17
+ export PORT=PORT_NUM
18
+
19
+ name="<%= name %>"
20
+ process_name="<%= process_name %>"
21
+ user="<%= user %>"
22
+ group="<%= group %>"
23
+ full_process_name="${name}-${process_name}-PROCESS_NUM"
24
+ pidfile="/var/run/${full_process_name}.pid"
25
+
26
+
27
+ start() {
28
+ # Run the program!
29
+ /usr/local/bin/${name} run ${process_name} >> /var/log/${name}/${process_name}-PROCESS_NUM.log 2>&1 &
30
+
31
+ # Generate the pidfile from here. If we instead made the forked process
32
+ # generate it there will be a race condition between the pidfile writing
33
+ # and a process possibly asking for status.
34
+ echo $! > $pidfile
35
+
36
+ echo "${full_process_name} started."
37
+ return 0
38
+ }
39
+
40
+ stop() {
41
+ # Try a few times to kill TERM the program
42
+ if status ; then
43
+ pid=`cat "$pidfile"`
44
+ echo "Killing ${full_process_name} (pid $pid) with SIGTERM"
45
+ kill -TERM $pid
46
+ # Wait for it to exit.
47
+ for i in 1 2 3 4 5 ; do
48
+ echo "Waiting ${full_process_name} (pid $pid) to die..."
49
+ status || break
50
+ sleep 1
51
+ done
52
+ if status ; then
53
+ echo "${full_process_name} stop failed; still running."
54
+ else
55
+ echo "${full_process_name} stopped."
56
+ fi
57
+ fi
58
+ }
59
+
60
+ status() {
61
+ if [ -f "$pidfile" ] ; then
62
+ pid=`cat "$pidfile"`
63
+ if kill -0 $pid > /dev/null 2> /dev/null ; then
64
+ return 0
65
+ else
66
+ return 2 # program is dead but pid file exists
67
+ fi
68
+ else
69
+ return 3 # program is not running
70
+ fi
71
+ }
72
+
73
+ force_stop() {
74
+ if status ; then
75
+ stop
76
+ status && kill -KILL `cat "$pidfile"`
77
+ fi
78
+ }
79
+
80
+ case "$1" in
81
+ start) status || start ;;
82
+ stop) stop ;;
83
+ force-stop) force_stop ;;
84
+ status)
85
+ status
86
+ code=$?
87
+ if [ $code -eq 0 ] ; then
88
+ echo "${full_process_name} is running"
89
+ else
90
+ echo "${full_process_name} is not running"
91
+ fi
92
+ exit $code
93
+ ;;
94
+ restart)
95
+ stop && start
96
+ ;;
97
+ *)
98
+ echo "Usage: $SCRIPTNAME {start|stop|force-stop|status|restart}" >&2
99
+ exit 3
100
+ ;;
101
+ esac
102
+
103
+ exit $?
@@ -0,0 +1,35 @@
1
+ #!/bin/sh
2
+ # Init script for <%= name %>-<%= process_name %>
3
+ # Generated by pkgr.
4
+ # Implemented based on LSB Core 3.1:
5
+ # * Sections: 20.2, 20.3
6
+ #
7
+ ### BEGIN INIT INFO
8
+ # Provides: <%= name %>-<%= process_name %>
9
+ # Required-Start: <%= name %>
10
+ # Required-Stop: <%= name %>
11
+ # Default-Start: 2 3 4 5
12
+ # Default-Stop: 0 1 6
13
+ # Description: <%= process_name %> component of <%= name %>
14
+ ### END INIT INFO
15
+
16
+ set -e
17
+
18
+ name="<%= name %>"
19
+ process_name="<%= process_name %>"
20
+
21
+ delegate() {
22
+ for file in $(ls -1 /etc/init.d/${name}-${process_name}-* 2>/dev/null); do
23
+ ${file} "${1}"
24
+ done
25
+ }
26
+
27
+ case "$1" in
28
+ start|stop|force-stop|status|restart) delegate "${1}" ;;
29
+ *)
30
+ echo "Usage: $SCRIPTNAME {start|stop|force-stop|status|restart}" >&2
31
+ exit 3
32
+ ;;
33
+ esac
34
+
35
+ exit $?
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+
3
+ echo "This job runs via upstart, invoking upstart now..."
4
+ exec initctl $1 <%= name %>
@@ -35,8 +35,6 @@ module Pkgr
35
35
 
36
36
  # default
37
37
  list.push Templates::FileTemplate.new("etc/default/#{app_name}", File.new(File.join(data_dir, "default.erb")))
38
- # upstart master
39
- list.push Templates::FileTemplate.new("etc/init/#{app_name}.conf", data_file("upstart/master.conf.erb"))
40
38
  # executable
41
39
  list.push Templates::FileTemplate.new("usr/local/bin/#{app_name}", File.new(File.join(data_dir, "runner.erb")), mode: 0755)
42
40
  # logrotate
@@ -52,8 +50,15 @@ module Pkgr
52
50
  list = []
53
51
  procfile_entries.select(&:daemon?).each do |process|
54
52
  Pkgr.debug "Adding #{process.inspect} to initialization scripts"
55
- list.push [process, Templates::FileTemplate.new("#{app_name}-#{process.name}.conf", data_file("upstart/process_master.conf.erb"))]
56
- list.push [process, Templates::FileTemplate.new("#{app_name}-#{process.name}-PROCESS_NUM.conf", data_file("upstart/process.conf.erb"))]
53
+ # sysvinit
54
+ list.push [process, Templates::FileTemplate.new("sysv/#{app_name}", data_file("sysv/master.erb"))]
55
+ list.push [process, Templates::FileTemplate.new("sysv/#{app_name}-#{process.name}", data_file("sysv/process_master.erb"))]
56
+ list.push [process, Templates::FileTemplate.new("sysv/#{app_name}-#{process.name}-PROCESS_NUM", data_file("sysv/process.erb"))]
57
+ # upstart
58
+ list.push [process, Templates::FileTemplate.new("upstart/#{app_name}", data_file("upstart/init.d.sh.erb"))]
59
+ list.push [process, Templates::FileTemplate.new("upstart/#{app_name}.conf", data_file("upstart/master.conf.erb"))]
60
+ list.push [process, Templates::FileTemplate.new("upstart/#{app_name}-#{process.name}.conf", data_file("upstart/process_master.conf.erb"))]
61
+ list.push [process, Templates::FileTemplate.new("upstart/#{app_name}-#{process.name}-PROCESS_NUM.conf", data_file("upstart/process.conf.erb"))]
57
62
  end
58
63
  list
59
64
  end
@@ -91,6 +96,7 @@ module Pkgr
91
96
  --deb-group "root" \
92
97
  -a "#{config.architecture}" \
93
98
  --description "#{config.description}" \
99
+ --maintainer "#{config.maintainer}" \
94
100
  --template-scripts \
95
101
  --before-install #{preinstall_file(config)} \
96
102
  --after-install #{postinstall_file(config)} \
@@ -105,13 +111,12 @@ module Pkgr
105
111
  uuid = Digest::SHA1.hexdigest(custom_buildpack_uri)
106
112
  [Buildpack.new(custom_buildpack_uri, :custom, config.env)]
107
113
  else
108
- default_buildpacks.map{|url| Buildpack.new(url, :builtin, config.env)}
114
+ load_buildpack_list(config)
109
115
  end
110
116
  end
111
117
 
112
- # Return the default buildpacks. Must be subclassed.
113
- def default_buildpacks
114
- []
118
+ def default_buildpack_list
119
+ data_file(File.join("buildpacks", "#{osfamily}_#{codename}"))
115
120
  end
116
121
 
117
122
  def preinstall_file(config)
@@ -155,6 +160,19 @@ module Pkgr
155
160
  def data_dir
156
161
  File.join(Pkgr.data_dir, "distributions", "debian")
157
162
  end
163
+
164
+ protected
165
+
166
+ def load_buildpack_list(config)
167
+ file = config.buildpack_list || default_buildpack_list
168
+ return [] if file.nil?
169
+
170
+ File.read(file).split("\n").map do |line|
171
+ url, *raw_env = line.split(",")
172
+ buildpack_env = (config.env || Env.new).merge(Env.new(raw_env))
173
+ Buildpack.new(url, :builtin, buildpack_env)
174
+ end
175
+ end
158
176
  end
159
177
  end
160
178
  end
@@ -6,17 +6,6 @@ module Pkgr
6
6
  def codename
7
7
  "squeeze"
8
8
  end
9
-
10
- def default_buildpacks
11
- %w{
12
- https://github.com/heroku/heroku-buildpack-ruby.git
13
- https://github.com/heroku/heroku-buildpack-nodejs.git
14
- https://github.com/heroku/heroku-buildpack-java.git
15
- https://github.com/heroku/heroku-buildpack-play.git
16
- https://github.com/heroku/heroku-buildpack-python.git
17
- https://github.com/heroku/heroku-buildpack-clojure.git
18
- }
19
- end
20
9
  end
21
10
  end
22
11
  end
@@ -6,17 +6,6 @@ module Pkgr
6
6
  def codename
7
7
  "wheezy"
8
8
  end
9
-
10
- def default_buildpacks
11
- %w{
12
- https://github.com/pkgr/heroku-buildpack-ruby.git#precise
13
- https://github.com/heroku/heroku-buildpack-nodejs.git
14
- https://github.com/heroku/heroku-buildpack-java.git
15
- https://github.com/heroku/heroku-buildpack-play.git
16
- https://github.com/heroku/heroku-buildpack-python.git
17
- https://github.com/heroku/heroku-buildpack-clojure.git
18
- }
19
- end
20
9
  end
21
10
  end
22
11
  end
data/lib/pkgr/env.rb CHANGED
@@ -2,7 +2,7 @@ module Pkgr
2
2
  class Env
3
3
  attr_reader :variables
4
4
 
5
- def initialize(variables)
5
+ def initialize(variables = nil)
6
6
  @variables = variables || []
7
7
  end
8
8
 
@@ -18,6 +18,10 @@ module Pkgr
18
18
  create_env_hash_from_string
19
19
  end
20
20
 
21
+ def merge(other)
22
+ self.class.new(self.variables + other.variables)
23
+ end
24
+
21
25
  private
22
26
 
23
27
  def create_env_hash_from_string
data/lib/pkgr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Pkgr
2
- VERSION = "1.1.8"
2
+ VERSION = "1.2.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: 1.1.8
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-26 00:00:00.000000000 Z
12
+ date: 2014-04-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -143,6 +143,10 @@ files:
143
143
  - lib/pkgr/data/bin/executable
144
144
  - lib/pkgr/data/config/pre_boot.rb
145
145
  - lib/pkgr/data/distributions/debian/build_dependencies.yml
146
+ - lib/pkgr/data/distributions/debian/buildpacks/debian_squeeze
147
+ - lib/pkgr/data/distributions/debian/buildpacks/debian_wheezy
148
+ - lib/pkgr/data/distributions/debian/buildpacks/ubuntu_lucid
149
+ - lib/pkgr/data/distributions/debian/buildpacks/ubuntu_precise
146
150
  - lib/pkgr/data/distributions/debian/cron.d
147
151
  - lib/pkgr/data/distributions/debian/default.erb
148
152
  - lib/pkgr/data/distributions/debian/dependencies.yml
@@ -150,6 +154,10 @@ files:
150
154
  - lib/pkgr/data/distributions/debian/hooks/preinstall.sh
151
155
  - lib/pkgr/data/distributions/debian/logrotate.erb
152
156
  - lib/pkgr/data/distributions/debian/runner.erb
157
+ - lib/pkgr/data/distributions/debian/sysv/master.erb
158
+ - lib/pkgr/data/distributions/debian/sysv/process.erb
159
+ - lib/pkgr/data/distributions/debian/sysv/process_master.erb
160
+ - lib/pkgr/data/distributions/debian/upstart/init.d.sh.erb
153
161
  - lib/pkgr/data/distributions/debian/upstart/master.conf.erb
154
162
  - lib/pkgr/data/distributions/debian/upstart/process.conf.erb
155
163
  - lib/pkgr/data/distributions/debian/upstart/process_master.conf.erb