I'm attempting to use Heroku's CI to run my Rails application's tests but it's running into a problem when attempting to load my structure.sql file.
-----> Preparing test database
Running: rake db:schema:load_if_ruby
db:schema:load_if_ruby completed (3.24s)
Running: rake db:structure:load_if_sql
psql:/app/db/structure.sql:28: ERROR: must be owner of extension plpgsql
rake aborted!
failed to execute:
psql -v ON_ERROR_STOP=1 -q -f /app/db/structure.sql d767koa0m1kne1
Please check the output above for any errors and make sure that `psql` is installed in your PATH and has proper permissions.
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/postgresql_database_tasks.rb:108:in `run_cmd'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/postgresql_database_tasks.rb:80:in `structure_load'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/database_tasks.rb:223:in `structure_load'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/database_tasks.rb:236:in `load_schema'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/database_tasks.rb:255:in `block in load_schema_current'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/database_tasks.rb:304:in `block in each_current_configuration'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/database_tasks.rb:303:in `each'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/database_tasks.rb:303:in `each_current_configuration'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/tasks/database_tasks.rb:254:in `load_schema_current'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/railties/databases.rake:290:in `block (3 levels) in <top (required)>'
/app/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.1/lib/active_record/railties/databases.rake:294:in `block (3 levels) in <top (required)>'
/app/vendor/bundle/ruby/2.4.0/gems/rake-12.0.0/exe/rake:27:in `<top (required)>'
Tasks: TOP => db:structure:load
(See full trace by running task with --trace)
!
! Could not prepare database for test
!
The relevant line here is:
psql:/app/db/structure.sql:28: ERROR: must be owner of extension plpgsql
rake aborted!
Structure.sql contains this line:
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
Any ideas on how to get this working on Heroku's CI?
Ended up overriding db:structure:dump to remove the COMMENT ON ... statements:
namespace :db do
namespace :structure do
task dump: [:environment, :load_config] do
filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
sql = File.read(filename).each_line.grep_v(/\ACOMMENT ON EXTENSION.+/).join
File.write(filename, sql)
end
end
end
Another workaround would be to add something like
if Rails.env.development?
ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = ["-v", "ON_ERROR_STOP=0"]
end
anywhere in the initialisation / tasks pipeline before the db:structure:load is executed.
If Kyle's solution isn't enough and the errors aren't caused only by comments on extensions, but actual extensions installations, you can still go the hard way and add this to an initializer:
# This is a temporary workaround for the Rails issue #29049.
# It could be safely removed when the PR #29110 got merged and released
# to use instead IGNORE_PG_LOAD_ERRORS=1.
module ActiveRecord
module Tasks
class PostgreSQLDatabaseTasks
ON_ERROR_STOP_1 = 'ON_ERROR_STOP=0'.freeze
end
end
end
Note: This isn't specific to Heroku but a broader Rails 5.1 issue
There are two solutions to this problem. First, as it was previously noted, is disabling the ON_ERROR_STOP feature. It'd help regardless of the environment. Custom rake task:
namespace :db do
namespace :structure do
# This little task is a workaround for a problem introduced in Rails5. Most specificaly here
# https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb#L77
# When psql encounters an error during loading of the structure it exits at once with error code 1.
# And this happens on heroku. It renders review apps and heroku CI unusable if you use a structure instead of a schema.
# Why?
# Our `db/structure.sql` contains entries like `CREATE EXTENSION` or `COMMENT ON EXTENSION`.
# Zylion of extensions on heroku are loaded in template0, so "our" db also has them, but because of that
# only a superuser (or owner of template0) has access to them - not our heroku db user. For that reason
# we can neither create an extension (it already exists, but that is not a problem, because dump contains IF NOT EXIST)
# nor comment on it (and comments don't have IF NOT EXIST directive). And that's an error which could be safely ignored
# but which stops loading of the rest of the structure.
desc "Disable exit-on-error behaviour when loading db structure in postgresql"
task disable_errors: :environment do
ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = ["-v", "ON_ERROR_STOP=0"]
end
end
end
# And use it like so:
bin/rails db:structure:disable_errors db:structure:load
Another option, in my opinion, superior if it comes only to Heroku, would be using PostgreSQL in in-dyno plan (https://devcenter.heroku.com/articles/heroku-ci-in-dyno-databases), which is basically a DB instance sitting within dyno, thus we have full access to it. Also, the test suite should be significantly faster because we use a localhost connection, not over the wire. To enable it, change your app.json content to have entries like so:
{
"environments": {
"test": {
"addons": [
"heroku-postgresql:in-dyno"
]
}
}
}
I have a really simple job:
class MyJob
#queue = :high
def self.perform(user_id)
user = User.find(user_id)
MyMailer.send_email(user).deliver
end
end
If I run it manually MyJob.perform(some_id)it works perfect. However, when Rescue is executing it, it returns this error:
Exception
Errno::ENOENT Error
No such file or directory - getcwd
shared/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_view/template/resolver.rb:221:in `expand_path' shared/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_view/template/resolver.rb:221:in `initialize' shared/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_view/template/resolver.rb:251:in `new' shared/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_view/template/resolver.rb:251:in `instances' shared/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_view/lookup_context.rb:16:in `<class:LookupContext>' shared/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_view/lookup_context.rb:12:in `<module:ActionView>' shared/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_view/lookup_context.rb:5:in `<top (required)>' shared/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/abstract_controller/view_paths.rb:45:in `lookup_context' shared/bundle/ruby/1.9.1/gems/actionmailer-3.2.12/lib/action_mailer/base.rb:456:in `process' shared/bundle/ruby/1.9.1/gems/actionmailer-3.2.12/lib/action_mailer/base.rb:452:in `initialize' shared/bundle/ruby/1.9.1/gems/actionmailer-3.2.12/lib/action_mailer/base.rb:439:in `new' shared/bundle/ruby/1.9.1/gems/actionmailer-3.2.12/lib/action_mailer/base.rb:439:in `method_missing' releases/1111111111111/app/jobs/my_job.rb:6:in `perform'
Have any ideas why might be happening?
Thanks!
Yes Sky. You are right about it needing to be restarted.
Some people received this error after trying to run from an already deleted directory.
I received this error after switching databases and leaving the server running. The old server info was still showing up but I was getting this error. Restarted my rails server and everything works fine with the new db.
Basically it means that there is a significant state change on the server, and your environment needs to be reset/restarted.
I started having this same issue on my production environment. After some investigation I found that this was caused by my resque workers failing to be properly restarted on each capistrano deployment.
I have such trouble with Jenkins.
I'm trying to test PDF generation using RSpec.
RSpec test failing, when trying to open receuntly generated PDF file. (File is saving into /tmp directory)
//TEST
pdf_generator = PdfGenerator::InvoicePdf.new(invoice)
pdf_file_path = pdf_generator.to_pdf
and I get error(in Jenkins only):
Failures:
1) OrdersController GET show while authorized as customer INVOICE .generate_pdf pdf contains correct text
Failure/Error: pdf_file_path = pdf_generator.to_pdf
Errno::ENOENT:
No such file or directory - /var/lib/jenkins/jobs/TicketCo for Gerrit/workspace/tmp/1371464314.pdf
# ./lib/pdf_generator/invoice_pdf.rb:80:in `to_pdf'
# ./spec/controllers/orders_controller_spec.rb:413:in `block (5 levels) in <top (required)>'
and here is the line in method, which causes error:
def to_pdf
Prawn::Document.generate(temp_pdf_file_path)
....
end
Can someone help me with this trouble ?
Maybe I need to change PDF path for Jenkins ?
I got an answer. If you have such problem just create /tmp folder in Jenkins workspace. In configurate tab you can add this command
mkdir -p tmp
Total newbie at cronjobs and that kinda stuff, never done it before, so now I tried to get my hands dirty using whenever as a plugin, after seeing it on RailsCasts.
So I am trying to run a cron job for my Ruby application, but it seems like it's not working, maybe becuase of the code or maybe because of me using Windows 7?
Here is the code from my Server model
def self.ping
Server.all.each do |t|
if t.name.serverUp?
#response = 'Up'
else
#response = 'Down'
end
self.update_attribute(:serverStatus, #response.to_s)
end
end
def serverUp?
if system 'ping '+name.to_s+' -n 1 > nul'
#response = 'Up'
else
#response = 'Down'
end
self.update_attribute(:serverStatus, #response.to_s)
#response
end
And here is the code from my schedule.rb file which has the cron job in it
#every 2.minutes do
# runner "Server.last.name = 'Works'"
# runner "for x in Server.all.each {x.serverUp?}", environment =>"development"
#end
every 2.minutes do
runner "Server.ping", environment =>"development"
end
I tried both methods out, (the latter I used most recently, to which I created the self.ping method in the Server model.
So when I run whenever in my rails directory, this is the output I get:
PS C:\SIS> whenever
0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58 * * * * /bin/bash -l -c 'cd C:/SIS
&& script/rails runner -e production '\''Server.ping'\'''
## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated.
## [message] Run `whenever --help' for more options.
1st) Funnily enough, the environment doesn't seem to have changed to development even though I stated it in the code.
2nd) The crontab file wasn't updated (I don't even know if there existed one to begin with?)
So I tried to create a crontab whenever file by running whenever -w ping, but the results was
PS C:\SIS> whenever -w ping
[fail] Couldn't write crontab; try running `whenever' with no options to ensure your schedule file is valid.
So this is my problem, any help would be appreciated.
Edit: Ok, I decided to use rufus-scheduler in order to update my Server list frequently. I tested out whether it would work to create a new server into the table every mintues, and that seemed to work.
However, because I wasn't able to stop it from creating servers, I removed it from the bundle, deleted the 'task_scheduler' file and then re-installed it and done everything like before.
However, when I now try to run the server, I get the following error:
C:/SIS/config/initializers/task_scheduler.rb:1:in '<top (required)>': undefined method 'start_new' for Rufus::Scheduler:
Module (NoMethodError)
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:235:in 'load'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:235:in 'block in load'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:225:in 'block in load_dependency'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:596:in 'new_constants_in'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:225:in 'load_dependency'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:235:in 'load'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/engine.rb:201:in 'block (2 levels) in <class:Engine>'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/engine.rb:200:in 'each'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/engine.rb:200:in 'block in <class:Engine>'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/initializable.rb:25:in 'instance_exec'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/initializable.rb:25:in 'run'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/initializable.rb:50:in 'block in run_initializers'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/initializable.rb:49:in 'each'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/initializable.rb:49:in 'run_initializers'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/application.rb:134:in 'initialize!'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/application.rb:77:in 'method_missing'
from C:/SIS/config/environment.rb:5:in '<top (required)>'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:in 'require'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:in 'block in require'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:225:in 'block in load_dependency'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:596:in 'new_constants_in'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:225:in 'load_dependency'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:in 'require'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/application.rb:103:in 'require_environment!'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/commands.rb:22:in '<top (required)>'
from script/rails:6:in 'require'
from script/rails:6:in '<main>'
The code in the task_scheduler is as follows:
scheduler = Rufus::Scheduler.start_new
scheduler.every '1m' do
# Server.all.each do
# |server| server.name.serverUp?
# end
Server.ping
end
Not sure which of the two methods to use, hence I commented the first one out.
Help would be greatly appreciated.
Thanks in advance
Edit
Ok, finally solved it, had to put require 'rubygems'
require 'rufus/scheduler' on the top of my code.
Now it works fine :-)
Cron is a Unix program. It doesn't exist on Windows.
Although it's nowhere near as flexible as cron, windows has the AT command which may be able to solve your problems, however you can only schedule it to run at most once a day. To see how to use AT run AT /? on your command line.
For much more fine-grained control over running tasks you can use the GUI based windows task scheduler. you can find this in Control Panel -> System and Security -> Administrative Tools -> Task Scheduler
I had the same problem, this is how I solved it:
I created a small EXE in AutoIT, the exe will read the names of files/urls to execute from an ini file (config.ini)
I named the EXE CRON.exe and had it start via schedulled tasks.
The files/urls in the config.ini can be either other executables or urls, the script will work out how to run each type.
AutoIT is a very simple scripting language, you can see my CRON.exe code below:
$iniFile='config.ini'
$i=0
While 1
$i+=1
$file=IniRead($iniFile, 'crons', $i, 'NULL')
If $file='NULL' Then ExitLoop
If StringInStr($file, 'http://') Then
InetGet($file, #TempDir, 1)
Else
$wd=StringSplit($file, '\', 3)
$workingDir=''
For $i=0 To UBound($wd)-2
$workingDir&=$wd[$i]&'\'
Next
RunWait($file, $workingDir)
EndIf
WEnd
Example of ini file:
[CRONS]
;paths of the files to execute
1=C:\anotherEXE.exe
2=http://mySite.com/myCron.php
All files are executed in order with no overlap, you can optionally change the AutoIT code to use Run instead of RunWait if you want to execute all files at the same time.
Yes I agree with Jorg M, cron job is unix program and also rufus scheduler internally call cron unix process so stay away from both and you should use delayed job ActiveRecord which help you to do the same.
This is as per my experience, there could other way but this is best which I ever used.
Best Luck
I have following code in my deploy.rb
namespace :app do
desc "copies the configuration frile from ~/shared/config/*.yml to ~/config"
task :copy_config_files,:roles => :app do
run "cp -fv #{deploy_to}/shared/config/hoptoad.rb #{release_path}/config/initializers"
run "cp -fv #{deploy_to}/shared/config/app_config.yml #{release_path}/config/app_config.yml"
end
end
I thought it would be a good idea to keep my deploy.rb file clean and I attempted to move above code to capistrano_utilities.rb under config. I am using Rails application. And I added following line of code to deploy.rb
require File.expand_path(File.dirname(__FILE__) + "/../lib/capistrano_utilities")
Now I am getting following error.
undefined method `namespace' for main:Object (NoMethodError)
The value of self in the deploy.rb is Capistrano::Configuration . While the value of self in capistrano_utilities is Main. So I understand why I am getting namespace method error. What is the fix for this problem?
In your config/deploy.rb, try load instead of require. Also, capistrano already runs as if you're at the RAILS_ROOT, so there's no need to use __FILE__:
load "lib/capistrano_utilities"
In a capistrano config file, load is redefined to load another configuration file into the current configuration. When passing a path to it, it actually calls load_from_file (a private method defined by capistrano) that just reads the file from disk and instance_eval's it.
Check your Capfile on Rails.root.
if you use capistrano 3, you see this line;
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }
Now, put your file on "lib/capistrano/tasks/capistrano_utilities.cap" and it will be loaded.