Deploying .env file with Capistrano - ruby-on-rails

I want to upload .env file to my remote machine from local machine while deploying with Capistrano, but as I am not a Ruby pro I do not get the result I want. What I want to do is take my local .env and make it available on remote machine in the shared_path. Afterwards, just symlink it with the current_path.
namespace :env do
desc "We take local env and set up on remote"
task :setup do
on roles(:app), in: :sequence, wait: 5 do
puts File.read(".env"), "#{shared_path}/config/.env"
execute "ln -nfs #{shared_path}/config/.env #{current_path}/.env"
end
end
end
Now this code creates .env as an empty file. What I am doing wrong? Or should I just execute rsync or something with Capistrano in order to achieve what I want?

I don't think puts will work there.
Try the capistrano's upload method.
upload(from, to, options={}, &block)

Related

Why files in config directory in shared path are deleting when copying these files from shared path to release path using Capistrano?

I am deploying a Dockerized Ruby on Rails application in AWS.
I need to run the docker-compose commands on server via Capistrano script.
Scenario 1: When I am trying to run docker-compose build command after deploy.
namespace :deploy do
task :docker_compose_build do
on roles(:app, :web) do
within release_path do
execute "cd #{release_path} && docker-compose build"
end
end
end
end
after "deploy", "deploy:docker_compose_build"
I am getting error "Invalid file database.yml" within docker image. Getting this error because Capistrano create symlink of linked_files instead copying.
Scenario 2: Removed database.yml from linked_files and trying to copy this file as below.
namespace :deploy do
task :docker_prepare do
on roles(:app) do
within release_path do
fetch(:config_files).each do |file|
execute "cp #{shared_path}/config/#{file} #{release_path}/config/#{file}"
end
end
end
end
task :docker_compose_build do
on roles(:app, :web) do
within release_path do
execute "cd #{release_path} && docker-compose build"
end
end
end
end
after "deploy:symlink:linked_files", "deploy:docker_prepare"
after "deploy", "deploy:docker_compose_build"
database.yml file is copying from shared path to release path but It is deleting from shared.
I am not understanding why cp command is deleting the source file?
Can anyone please help me to resolve my problem?

execute bash script inside deploy.rb using capistrano

I am learning (by doing) Rails and Capistrano.
How can I execute a scrpit inside deploy.rb?
I came across run(command), exec(command), execute: or run:.
I don't have to specify :db or web so I have the following backbone:
task :myTask do
on roles(:app) do
execute "bash myScript.sh"
puts "#{:server} reports: #{myTask}"
end
end
Is this correct?
Is the ssh part of the whole process or I have to ssh in the command?
How do people develope deploy.rb without cap deploy every time they make a change?
Thank you!
Ruby allows you to run a shell script using backtick
for example
output = `pwd`
puts "output is #{output}"
see more https://ruby-doc.org/core-1.9.3/Kernel.html#method-i-60
This is what worked for me:
role :app, 'user#domain1.com'
on roles(:app) do
within 'remote_path' do
execute 'bash', ' myScript.sh'
end
end

Capistrano Deploy recipe to symlink Ruby on Rails folder public/images, not working

Every time I upload images it goes to public/images/upload then when I run a cap deploy they get erased since it creates a new current directory.
How do I instruct Capistrano to move the files in public/images/upload to the shared/images/ then symlink those images to the current(new) release ?
after "deploy:update_code", "deploy:symlink_shared"
after "deploy:restart", "deploy:cleanup"
namespace :deploy do
task :restart do
run "touch #{current_path}/tmp/restart.txt"
end
desc "Symlink shared configs and folders on each release."
task :symlink_shared do
run "ln -nfs #{shared_path}/images/upload #{release_path}/public/images/uploads"
end
end
Have try to expand shared directory list?
#deploy.rb
set :shared_children, shared_children + %w{public/images/uploads}
Edit : Remove you code and set shared_children variable.
After that make a cap deploy:setup so that updated your shared dir.

capistrano put() and upload() both failing

With capistrano, I am deploying a Rails application from Mac OS X 10.5 to CentOS 5.2
Note that deploy.rb and the server environment have not changed in over a year.
There is a task within our deploy.rb file called upload:
put(File.read( file ),"#{shared_path}/#{filename}", :via => :scp)
This fails each and every time with the following exception:
No such file or directory - /srv/ourapp/releases/20100104194410/config/database.yml
My local copy of config/database.yml is failing to upload properly. I've verified it's not our internet connection, as this happens on three different connections and two different systems.
I've also tried to swap out put() for upload() but get the same result; also, dropping :via => :scp, and/or trying to force :sftp instead similarly fails.
Relevant info:
$ cap -V
Capistrano v2.5.10
$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9.6.0]
If I understand your question correctly, it sounds like Capistrano is successfully uploading the files, but Rails is failing to start because it can't find the deploy.yml file. This might be happening during the Capistrano deploy as part of the deploy:restart task, making it look like a Capistrano error.
Based on the information you've given Capistrano is uploading the file to /svr/ourapp/shared/ and Rails is almost definitely looking for it in /svr/ourapp/releases/20100104194410/config/.
If that's the case, what you'll need to do is create a task which symlinks the shared database file to the expected location then add a hook so that task will be run after finalize_update. For instance:
task :symlink_database do
run "ln -s #{shared_path}/database.yml #{latest_release}/config/database.yml"
end
after 'deploy:finalize_update', :symlink_database
namespace :deploy do
task :upload_settings, :roles => :app do
run "mkdir -p #{shared_path}/config/"
top.upload "config/database.yml", "#{shared_path}/config/database.yml", :via => :scp
end
task :symlink_yml, :roles => :app do
run "ln -sf #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
end
after 'deploy:setup', 'deploy:upload_settings'
after 'deploy:update_code', 'deploy:symlink_yml'
This is purely from a server-side view, but have you checked to make sure that the user you're using to upload has proper permissions for the directory?
Doing a recursive change for the user (or group) depending on your server environment should fix this.
chown -R user_name_here /srv/ourapp/releases/
chgrp -R group_name_here /srv/ourapp/releases/
You might also want to clean up any code repositories e.g. git gc or svn cleanup. As well as updating any symbolic links.
The "No such file or directory" error occurs when you are trying to copy a file to a destination path that does not exist. As far as I know, the put and upload methods of Capistrano merely attempt to transfer the file, but do not make the required path. Is it possible that the config/ directory, or even the shared_path itself, has not been created when you are trying to upload this file?

How do I "copy unless later version exists" in Capistrano?

I want to protect my database.yml file by keeping it out of version control. Thus, I have two tasks in my Capistrano deploy recipe:
task :copy_db_config do
# copy local config file if it exists and is more
# recent than the remote one
end
task :symlink_db_config do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
Can you help fill in the first task?
I don't have functioning code for you here and now but..
you can the the local timestamp by using ruby. File class has a function ctime which let's You know when it was changed.
Run the same command on the servers database.yml
If the local one is newest, capistrano has a method for secure upload
upload("products.txt", "/home/medined", :via => :scp)
I had the same problem, but I approached it differently. Maybe it will be helpful.
The setup task copies database.yml.example to database.yml. The deploy task does not touch database.yml. I have separate tasks for changing the database names, usernames, and passwords. Here's an example:
desc "Change the database name"
task :change_db_database, :roles => :app do
database = prompt('Enter new database name: ')
run <<-CMD
cd #{shared_path}/config &&
perl -i -pe '$env = $1 if /^(\\w+)/; s/database:.*/database: #{database}/ if $env eq "#{ENV['CONNECTION'] || ENV['TARGET']}"' database.yml
CMD
end
I run these after setup but before the first deploy on new boxes. Then any time after that when I need to change database parameters, I use these tasks instead of copying in a new file.

Resources