Merge pull request #1856 from opf/merge/release-3.0-into-dev

Merge release 3.0 into dev
pull/1860/head
Alex Coles 10 years ago
commit 2e711943c5
  1. 21
      .pkgr.yml
  2. 3
      Gemfile
  3. 7
      Gemfile.lock
  4. 4
      Procfile
  5. 2
      config/initializers/secret_token.rb
  6. 3
      config/unicorn.rb
  7. 2
      db/seeds/all.rb
  8. 2
      lib/open_project/configuration.rb
  9. 22
      lib/tasks/setting.rake
  10. 4
      packaging/conf/000-establish-connection.rb
  11. 11
      packaging/conf/configuration.yml
  12. 3
      packaging/cron/openproject-clear-old-sessions
  13. 2
      packaging/cron/openproject-create-svn-repositories
  14. 75
      packaging/debian/postinst
  15. 79
      packaging/scripts/backup
  16. 46
      packaging/scripts/check
  17. 21
      packaging/scripts/create-svn-repositories
  18. 42
      packaging/scripts/send-test-email
  19. 13
      packaging/setup
  20. 12
      spec/lib/open_project/configuration_spec.rb

@ -0,0 +1,21 @@
user: openproject
group: openproject
targets:
debian-7:
build_dependencies:
- libmagickwand-dev
- libsqlite3-dev
dependencies:
- debconf
- memcached
before_precompile: "packaging/setup"
after_install: "packaging/debian/postinst"
addons:
- mysql
- apache2
- svn-dav
- smtp
crons:
- packaging/cron/openproject-clear-old-sessions
- packaging/cron/openproject-create-svn-repositories

@ -125,6 +125,9 @@ gem 'i18n-js', git: "https://github.com/fnando/i18n-js.git", branch: '12fe8ec213
# small wrapper around the command line
gem 'cocaine'
# required by Procfile, for deployment on heroku or packaging with packager.io.
# also, better than thin since we can control worker concurrency.
gem 'unicorn'
# Security fixes
# Gems we don't depend directly on, but specify here to make sure we don't use a vulnerable

@ -205,6 +205,7 @@ GEM
json_spec (1.1.1)
multi_json (~> 1.0)
rspec (~> 2.0)
kgio (2.9.2)
launchy (2.3.0)
addressable (~> 2.3)
letter_opener (1.0.0)
@ -302,6 +303,7 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
raindrops (0.13.0)
rake (10.3.2)
rb-readline (0.5.1)
rdoc (3.12.2)
@ -392,6 +394,10 @@ GEM
uglifier (2.1.1)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
unicorn (4.8.3)
kgio (~> 2.6)
rack
raindrops (~> 0.7)
virtus (1.0.2)
axiom-types (~> 0.1)
coercible (~> 1.0)
@ -494,4 +500,5 @@ DEPENDENCIES
thin
timecop (~> 0.6.1)
uglifier (>= 1.0.3)
unicorn
will_paginate (~> 3.0)

@ -0,0 +1,4 @@
web: bundle exec unicorn --config-file config/unicorn.rb --host ${HOST:="127.0.0.1"} --port ${PORT:="8080"} --env ${RAILS_ENV:="development"}
worker: bundle exec rake jobs:work
backup: ./packaging/scripts/backup
check: ./packaging/scripts/check

@ -41,7 +41,7 @@ begin
rescue
end
OpenProject::Application.config.secret_token = if Rails.env.development? or Rails.env.test?
OpenProject::Application.config.secret_token = if Rails.env.development? or Rails.env.test? or Rails.groups.include?('assets')
('x' * 30) # meets minimum requirement of 30 chars long
else
ENV['SECRET_TOKEN'] || secret_token

@ -0,0 +1,3 @@
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 1)
timeout Integer(ENV["WEB_TIMEOUT"] || 15)
preload_app false

@ -77,7 +77,7 @@ if User.admin.empty?
user.force_password_change = true
user.firstname = "OpenProject"
user.lastname = "Admin"
user.mail = "admin@example.net"
user.mail = ENV.fetch('ADMIN_EMAIL') { "admin@example.net" }
user.mail_notification = User::USER_MAIL_OPTION_NON.first
user.language = "en"
user.status = 1

@ -150,7 +150,7 @@ module OpenProject
def load_config_from_file(filename, env, config)
if File.file?(filename)
file_config = YAML::load_file(filename)
file_config = YAML::load(ERB.new(File.read(filename)).result)
unless file_config.kind_of? Hash
warn "#{filename} is not a valid OpenProject configuration file, ignoring."
else

@ -0,0 +1,22 @@
namespace :setting do
desc "Allow to set a Setting: rake setting:set[key1=value1,key2=value2]"
task :set => :environment do |t,args|
args.extras.each do |tuple|
key, value = tuple.split("=")
setting = Setting.find_by_name(key)
if setting.nil?
Setting.create! name: key, value: value
else
setting.update_attributes! value: value
end
end
end
desc "Allow to get a Setting: rake setting:get[key]"
task :get, [:key] => :environment do |t,args|
setting = Setting.find_by_name(args[:key])
unless setting.nil?
puts(setting.value)
end
end
end

@ -0,0 +1,4 @@
# Force the usage of config/database.yml instead of DATABASE_URL.
# Used so that query parameters from the DATABASE_URL are correctly used (e.g. SSL settings).
config = YAML.load(ERB.new(File.read(Rails.root.join("config/database.yml"))).result)[Rails.env.to_s]
ActiveRecord::Base.establish_connection config

@ -0,0 +1,11 @@
default:
rails_cache_store: <%= ENV.fetch('RAILS_CACHE_STORE') { :memcache }.to_sym %>
session_store: <%= ENV.fetch('SESSION_STORE') { :cache_store }.to_sym %>
email_delivery_method: <%= ENV.fetch('EMAIL_DELIVERY_METHOD') { :sendmail } %>
smtp_address: <%= ENV['SMTP_HOST'] %>
smtp_port: <%= ENV.fetch('SMTP_PORT') { 25 }.to_i %>
smtp_domain: <%= ENV.fetch('SMTP_DOMAIN') { ENV['HOSTNAME'] } %>
smtp_authentication: <%= ENV.fetch('SMTP_AUTHENTICATION') { :login }.to_sym %>
smtp_user_name: <%= ENV['SMTP_USERNAME'] %>
smtp_password: <%= ENV['SMTP_PASSWORD'] %>
attachments_storage_path: <%= ENV.fetch('ATTACHMENTS_STORAGE_PATH') { "/var/db/_APP_NAME_/files" } %>

@ -0,0 +1,3 @@
APP_NAME="_APP_NAME_"
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
15 1 * * * root ${APP_NAME} run rake -s db:sessions:expire[7] >> /var/log/${APP_NAME}/cron-clear-old-sessions.log 2>&1

@ -0,0 +1,2 @@
APP_NAME="_APP_NAME_"
*/10 * * * * root /opt/${APP_NAME}/packaging/scripts/create-svn-repositories >> /var/log/${APP_NAME}/cron-create-svn-repositories.log 2>&1

@ -0,0 +1,75 @@
#!/bin/sh
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
APP_NAME="_APP_NAME_"
CLI="${APP_NAME}"
APP_USER=$(${CLI} config:get APP_USER)
APP_GROUP=$(${CLI} config:get APP_GROUP)
# source debconf library
. /usr/share/debconf/confmodule
case "$1" in
configure)
# create attachments folder
attachments_path=$(${CLI} config:get ATTACHMENTS_STORAGE_PATH || echo "/var/db/${APP_NAME}/files")
mkdir -p "${attachments_path}"
chown ${APP_USER}.${APP_GROUP} "${attachments_path}"
${CLI} config:set ATTACHMENTS_STORAGE_PATH="${attachments_path}"
# set web concurrency
web_concurrency=$(${CLI} config:get WEB_CONCURRENCY || echo "2")
${CLI} config:set WEB_CONCURRENCY=${web_concurrency}
# set web timeout
web_timeout=$(${CLI} config:get WEB_TIMEOUT || echo "15")
${CLI} config:set WEB_TIMEOUT=${web_timeout}
# set SECRET_TOKEN env variable
secret_token=$(${CLI} config:get SECRET_TOKEN || ${CLI} run rake -s secret | tail -1)
${CLI} config:set SECRET_TOKEN="$secret_token"
# migrate
rake_commands="db:migrate db:seed"
${CLI} run rake ${rake_commands} || true
sys_api_key=$(${CLI} config:get SYS_API_KEY)
# set various settings
db_get ${APP_NAME}/server/hostname
if [ -z "$RET" ]; then web_hostname=$(hostname -f); else web_hostname="$RET"; fi
db_get ${APP_NAME}/server/ssl
if [ "$RET" = "true" ]; then web_protocol="https"; else web_protocol="http"; fi
${CLI} run rake setting:set[host_name=${web_hostname},protocol=${web_protocol},sys_api_enabled=1,sys_api_key=${sys_api_key}] 1>/dev/null
# scale
${CLI} scale web=1 worker=1 || true
# let the admin reboot when he's ready
;;
abort-upgrade|abort-remove|abort-deconfigure)
exit 0
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac

@ -0,0 +1,79 @@
#!/bin/bash
set -e
TARGET="/var/db/${APP_NAME}/backup"
mkdir -p "${TARGET}"
timestamp=$(date +"%Y%m%d%H%M%S")
echo -n "* Generating database backup..." >&2
tmpfile=$(mktemp)
database=$(ruby -ruri -e 'puts URI(ENV["DATABASE_URL"]).path[1..-1]')
ruby -ruri -rcgi -e '
uri = URI(ENV["DATABASE_URL"])
params = CGI.parse(uri.query || "")
config=<<CONFIG
[client]
password="#{uri.password}"
user="#{uri.user}"
host="#{uri.host}"
port="#{uri.port}"
CONFIG
config += %{ssl-key="#{params["sslkey"].first}"\n} if params.has_key?("sslkey")
config += %{ssl-cert="#{params["sslcert"].first}"\n} if params.has_key?("sslcert")
config += %{ssl-ca="#{params["sslca"].first}"\n} if params.has_key?("sslca")
puts config' > ${tmpfile}
dst="${TARGET}/mysql-dump-${timestamp}.sql.gz"
touch "$dst" && chmod 0640 "$dst"
mysqldump --defaults-file=${tmpfile} --single-transaction "${database}" | gzip > "$dst"
echo " done" >&2
echo "$dst"
rm -f ${tmpfile}
if [ -d "$SVN_REPOSITORIES" ]; then
dst="${TARGET}/svn-repositories-${timestamp}.tar.gz"
touch "$dst" && chmod 0640 "$dst"
echo -n "* Generating SVN repositories backup..." >&2
if tar czf "$dst" -C "${SVN_REPOSITORIES}" . ; then
echo " done" >&2
echo "$dst"
else
echo " failed" >&2
fi
else
echo "* No SVN repositories folder. Ignoring." >&2
fi
if [ -d "$ATTACHMENTS_STORAGE_PATH" ]; then
dst="${TARGET}/attachments-${timestamp}.tar.gz"
touch "$dst" && chmod 0640 "$dst"
echo -n "* Generating attachments backup..." >&2
if tar czf "$dst" -C "${ATTACHMENTS_STORAGE_PATH}" . ; then
echo " done" >&2
echo "$dst"
else
echo " failed" >&2
fi
else
echo "* No attachments folder. Ignoring." >&2
fi
if [ -d "/etc/${APP_NAME}/conf.d" ]; then
dst="${TARGET}/conf-${timestamp}.tar.gz"
touch "$dst" && chmod 0640 "$dst"
echo -n "* Saving configuration..." >&2
if tar czf "$dst" -C /etc/${APP_NAME}/conf.d . ; then
echo " done" >&2
echo "$dst"
else
echo " failed" >&2
fi
else
echo "* no configuration folder. Ignoring." >&2
fi

@ -0,0 +1,46 @@
#!/bin/bash
set -e
log_ok() {
echo -e "\e[32m[ok]\e[0m $1"
}
log_ko() {
echo -e "\e[31m[ko]\e[0m $1"
}
# try to get a setting to make sure database connection works
if rake setting:get[protocol] &>/dev/null; then
log_ok "MySQL configuration is working"
else
log_ko "MySQL connection is NOT working"
fi
if /etc/init.d/apache2 status &>/dev/null; then
log_ok "Apache2 is running"
else
log_ko "Apache2 is NOT running"
fi
if ps -u "$APP_USER" -f | grep -q "unicorn worker" ; then
log_ok "openproject server is running"
else
log_ko "openproject server is NOT running"
fi
if ps -u "$APP_USER" -f | grep -q "rake jobs:work" ; then
log_ok "openproject background job worker is running"
else
log_ko "openproject background job worker is NOT running"
fi
if [ -z "$ADMIN_EMAIL" ]; then
log_ko "no ADMIN_EMAIL set. Can't test email settings."
else
if $(pwd)/packaging/scripts/send-test-email ; then
log_ok "test email sent to ${ADMIN_EMAIL}"
else
log_ko "unable to send test email to ${ADMIN_EMAIL}"
fi
fi

@ -0,0 +1,21 @@
#!/bin/bash
APP_NAME="_APP_NAME_"
CLI="${APP_NAME}"
SVN_REPOSITORIES=$(${CLI} config:get SVN_REPOSITORIES)
PORT=$(${CLI} config:get PORT)
SYS_API_KEY=$(${CLI} config:get SYS_API_KEY)
APP_GROUP=$(${CLI} config:get APP_GROUP)
/opt/${APP_NAME}/bin/ruby /opt/${APP_NAME}/extra/svn/reposman.rb \
--openproject-host "http://127.0.0.1:${PORT}" \
--owner "www-data" \
--group "${APP_GROUP}" \
--public-mode '2750' \
--private-mode '2750' \
--svn-dir "${SVN_REPOSITORIES}" \
--url "file://${SVN_REPOSITORIES}" \
--key "${SYS_API_KEY}" \
--scm Subversion \
--verbose

@ -0,0 +1,42 @@
#!/usr/bin/env ruby
require 'net/smtp'
require 'time'
require 'securerandom'
require 'tempfile'
admin_email = ENV.fetch('ADMIN_EMAIL') { fail "no ADMIN_EMAIL set" }
smtp_domain = ENV.fetch('SMTP_DOMAIN') { "example.net" }
from = "no-reply@#{smtp_domain}"
delivery_method = ENV.fetch('EMAIL_DELIVERY_METHOD') { "sendmail" }
msgstr = <<END_OF_MESSAGE
From: OpenProject <#{from}>
To: #{admin_email}
Subject: Test message
Date: #{Time.now.httpdate}
Message-Id: <#{SecureRandom.hex}@#{smtp_domain}>
This is a test message to verify your OpenProject settings.
If you see this, this means OpenProject email settings are working properly.
END_OF_MESSAGE
if delivery_method == "sendmail"
puts "sending test email using sendmail..."
tmpfile = Tempfile.new("mail-test")
File.open(tmpfile.path, "w+") {|f| f << msgstr}
system("cat #{tmpfile.path} | sendmail -i -t") || exit(1)
else
puts "sending test email using SMTP..."
Net::SMTP.start(
ENV.fetch('SMTP_HOST'),
ENV.fetch('SMTP_PORT'),
ENV.fetch('SMTP_DOMAIN'),
ENV.fetch('SMTP_USERNAME'),
ENV.fetch('SMTP_PASSWORD'),
:login
) do |smtp|
smtp.send_message msgstr, from, admin_email
end
end

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# we need postgresql for asset precompilation
# see: https://packager.io/documentation
sudo service postgresql start
cp -f packaging/conf/configuration.yml config/configuration.yml
sed -i "s|config.serve_static_assets = false|config.serve_static_assets = true|" config/environments/production.rb
cp -f packaging/conf/000-establish-connection.rb config/initializers/
# replace every occurrence of _APP_NAME_ with the corresponding application name we're packaging
find packaging/ -type f -print0 | xargs -0 sed -i "s|_APP_NAME_|${APP_NAME}|"

@ -33,11 +33,13 @@ describe OpenProject::Configuration do
let(:config) { Hash.new }
before do
expect(YAML).to receive(:load_file).and_return({
'default' => {},
'test' => { 'somesetting' => 'foo' }
})
expect(File).to receive(:file?).with('file').and_return(true)
File.should_receive(:file?).with('file').and_return(true)
File.should_receive(:read).and_return("
default:
test:
somesetting: foo
")
OpenProject::Configuration.send(:load_config_from_file, 'file', 'test', config)
end

Loading…
Cancel
Save