1 00:00:00,410 --> 00:00:03,470 In the last video we set up Capistrano to deploy our RailsApp 2 00:00:03,470 --> 00:00:05,130 at our production server. 3 00:00:05,130 --> 00:00:06,100 But unfortunately, 4 00:00:06,100 --> 00:00:10,920 it's failing with the error database "guestbook_production" does not exist. 5 00:00:10,920 --> 00:00:12,780 Just as there are many different RailsApps, 6 00:00:12,780 --> 00:00:15,980 there are many different database setups, each one a little bit different. 7 00:00:15,980 --> 00:00:19,222 So setting up your database is something that's unique to your app, 8 00:00:19,222 --> 00:00:23,170 some early practical for Capistrano to do it for you by default. 9 00:00:23,170 --> 00:00:26,850 So we're going to need to provide our own test to create the database. 10 00:00:26,850 --> 00:00:31,060 What we need to do is on the remote server we need to change into the app directory 11 00:00:31,060 --> 00:00:33,750 and run the rails task db:setup. 12 00:00:33,750 --> 00:00:37,435 So we're going to create a Capistrano Task to do this for us. 13 00:00:37,435 --> 00:00:42,185 There's one more file that the cap install command created for us. 14 00:00:42,185 --> 00:00:48,377 It's a sub directory here in the lib directory for our app called Capistrano. 15 00:00:48,377 --> 00:00:51,267 And then there's another subdirectory called tasks. 16 00:00:51,267 --> 00:00:55,577 Here we an create files that describe tasks that Capistrano can carry out for 17 00:00:55,577 --> 00:00:57,027 us on remote servers. 18 00:00:57,027 --> 00:01:01,457 So I'm going to create a new file within this tasks subdirectory, and 19 00:01:01,457 --> 00:01:06,848 I'm going to call it deploy_initial.rake. 20 00:01:06,848 --> 00:01:10,890 Notice that it's important it end in .rake and not .rb, or 21 00:01:10,890 --> 00:01:13,430 Capistrano won't detect it. 22 00:01:13,430 --> 00:01:18,060 The reason it uses a .rake extension is because Capistrano is an extension 23 00:01:18,060 --> 00:01:23,230 of the domain specific language for rake, which standards for Ruby make. 24 00:01:23,230 --> 00:01:28,640 Rake is an older library that's used to build and deploy other Ruby applications. 25 00:01:28,640 --> 00:01:34,030 So Capistrano tasks get defined in files with the same extension, .rake. 26 00:01:34,030 --> 00:01:37,070 So create that file, and we want to be able to 27 00:01:37,070 --> 00:01:41,900 run this task from the command line with a name of deploy:initial. 28 00:01:41,900 --> 00:01:46,290 So, first thing I'm going to do is run the namespace method. 29 00:01:47,800 --> 00:01:50,030 And I'm going to create a namespace named deploy. 30 00:01:52,380 --> 00:01:55,690 Many other tasks also exist within the deploy namespace. 31 00:01:55,690 --> 00:01:58,870 So this task will just get added to that group. 32 00:01:58,870 --> 00:02:03,300 Namespace method takes a block, and every task that we define within that 33 00:02:03,300 --> 00:02:06,210 block will get added to the deploy namespace. 34 00:02:06,210 --> 00:02:07,820 Now to create our actual task. 35 00:02:07,820 --> 00:02:12,740 I'm gonna start with a description for that task, by calling the desc method, and 36 00:02:12,740 --> 00:02:18,444 the description method takes a string, which I'm going to say "Runs rails 37 00:02:18,444 --> 00:02:22,110 db:setup". 38 00:02:22,110 --> 00:02:24,090 Following your call to description, 39 00:02:24,090 --> 00:02:28,300 you call the task method to define the actual task. 40 00:02:28,300 --> 00:02:31,420 It takes a symbol with the name of the task you're gonna create. 41 00:02:31,420 --> 00:02:36,155 And I'm going to name this task create_db. 42 00:02:37,280 --> 00:02:41,810 The need provided lock to the task method with the actual statements that will get 43 00:02:41,810 --> 00:02:44,030 run when it's executing the task. 44 00:02:44,030 --> 00:02:46,620 I want to execute a command on the remote server, so 45 00:02:46,620 --> 00:02:48,850 I'm going to call the execute method. 46 00:02:48,850 --> 00:02:52,720 This is provided by Capistrano, and the first argument to execute should be 47 00:02:52,720 --> 00:02:55,180 a symbol with the name of the command you want to run. 48 00:02:55,180 --> 00:02:59,680 We want to run the rails command so I'm going to say symbol, rails. 49 00:02:59,680 --> 00:03:02,560 Then you can provide a string with any arguments that you wanna 50 00:03:02,560 --> 00:03:03,485 pass to that command. 51 00:03:03,485 --> 00:03:09,895 So I'm going to have it run the task db:setup. 52 00:03:09,895 --> 00:03:13,535 Basically this task as I've defined it will be the equivalent of connecting to 53 00:03:13,535 --> 00:03:18,915 the remote server via SSH and running rails db:setup. 54 00:03:18,915 --> 00:03:19,995 So I'll go then save that. 55 00:03:19,995 --> 00:03:24,987 And if we go back to the terminal I can get a list of all the tasks that have been 56 00:03:24,987 --> 00:03:26,505 defined for this app. 57 00:03:26,505 --> 00:03:29,899 I'm running bundle exec cap and 58 00:03:29,899 --> 00:03:36,580 passing at the -T flag, to get a list of all the tasks. 59 00:03:36,580 --> 00:03:39,770 And if we scroll up the list, we can see. 60 00:03:42,028 --> 00:03:45,776 Our new create_db task here in the deploy namespace, and 61 00:03:45,776 --> 00:03:51,180 there is the description we provided for it, Runs rails db:setup. 62 00:03:51,180 --> 00:03:52,960 So let's try running this new task now. 63 00:03:52,960 --> 00:03:55,980 I'm gonna run bundle exec cap. 64 00:03:57,440 --> 00:03:59,320 Specify the stage which is production. 65 00:04:01,340 --> 00:04:06,700 And then I'll specify the deploy namespace and the name of our task create_db. 66 00:04:06,700 --> 00:04:10,740 But if I try running it we get an error. 67 00:04:10,740 --> 00:04:14,720 It says that any call to the execute method should be wrapped in an on scope, 68 00:04:14,720 --> 00:04:17,140 and it gives an example of what it's looking for. 69 00:04:17,140 --> 00:04:21,440 So here within our task that we've defined, we need to say on roles and 70 00:04:21,440 --> 00:04:24,350 whatever server roles we need this to run on. 71 00:04:24,350 --> 00:04:27,880 Provide a block, and then we can call our execute command. 72 00:04:27,880 --> 00:04:30,400 There's a reason it wants us to specify a role. 73 00:04:30,400 --> 00:04:34,030 If we ever split our app up to run on separate app and database servers, 74 00:04:34,030 --> 00:04:36,880 we only want this task to run on the database server. 75 00:04:36,880 --> 00:04:40,200 So we need to go in and specify that this should run on the db role. 76 00:04:40,200 --> 00:04:42,390 I'm gonna go back to our editor. 77 00:04:44,280 --> 00:04:48,660 And here within our task block I'm going to say that this should only run on 78 00:04:48,660 --> 00:04:52,210 the roles, and this will actually be a single role, db. 79 00:04:52,210 --> 00:04:53,290 The symbol db. 80 00:04:56,100 --> 00:05:02,210 Then I need to provide a block, and the statements 81 00:05:02,210 --> 00:05:07,060 within that block will only run on servers that match that particular role. 82 00:05:07,060 --> 00:05:08,460 So let's save that. 83 00:05:08,460 --> 00:05:11,570 Go back to our shell and try running the deployment command again. 84 00:05:13,330 --> 00:05:14,160 It fails again. 85 00:05:14,160 --> 00:05:19,310 This time saying it could not locate the Gemfile or bundle directory. 86 00:05:19,310 --> 00:05:22,960 And the reason it can't find the Gemfile is because it hasn't changed into the app 87 00:05:22,960 --> 00:05:26,790 directory prior to trying to run the bundle command. 88 00:05:26,790 --> 00:05:30,280 So, to fix this, we're gonna go back into our task in the editor. 89 00:05:30,280 --> 00:05:34,420 And surrounding the call the execute, we're going to call the within method. 90 00:05:34,420 --> 00:05:36,629 Within takes an argument, 91 00:05:36,629 --> 00:05:39,980 the string representing the path that you want it run within. 92 00:05:39,980 --> 00:05:46,600 So, we're going to call the release_path method here, which 93 00:05:46,600 --> 00:05:51,370 is a Capistrano method representing the directory that we're releasing our app to. 94 00:05:52,380 --> 00:05:57,600 Within takes a block and everything within that block our execute command here, 95 00:05:57,600 --> 00:06:00,520 will be executed within the directory we specified. 96 00:06:01,880 --> 00:06:05,070 So the net effect here is that we'll change into the release path and 97 00:06:05,070 --> 00:06:06,790 then execute this command. 98 00:06:06,790 --> 00:06:09,490 That should fix the error we were seeing. 99 00:06:09,490 --> 00:06:14,090 Okay so let's save this and try running our deployment command again. 100 00:06:14,090 --> 00:06:16,230 This time it fails with another error. 101 00:06:16,230 --> 00:06:18,030 It says directory does not exist. 102 00:06:18,030 --> 00:06:20,020 Home deploy guest book current. 103 00:06:21,580 --> 00:06:25,320 The problem is that we set our task up to run within the release path, but 104 00:06:25,320 --> 00:06:29,040 the release path doesn't exist at the time that our task is running. 105 00:06:29,040 --> 00:06:32,680 What we really need is to run this task after the app is cloned but 106 00:06:32,680 --> 00:06:35,830 before the deploy migrate task runs. 107 00:06:35,830 --> 00:06:40,070 A normal Capistrano deployment actually consists of a bunch of sub-tasks 108 00:06:40,070 --> 00:06:41,910 that run one after the other. 109 00:06:41,910 --> 00:06:45,220 There's a task that runs when the deployment is just starting. 110 00:06:45,220 --> 00:06:48,850 There's another that runs while the app code is being updated, yet 111 00:06:48,850 --> 00:06:52,620 another that runs while the app is being published, and 112 00:06:52,620 --> 00:06:56,430 a couple more tasks that run as the deployment is finishing. 113 00:06:56,430 --> 00:07:00,628 If you run bundle exec cap -T, capital T, 114 00:07:00,628 --> 00:07:06,351 to get a list of the tasks, you can find still other hooks. 115 00:07:08,266 --> 00:07:12,852 These are tasks that kicked off during various parts of the deployment, 116 00:07:12,852 --> 00:07:14,506 including the migrate and 117 00:07:14,506 --> 00:07:19,470 migrating tasks which happen when the database is being migrated. 118 00:07:19,470 --> 00:07:24,420 So we're going to set up a deploy initial task that sets the deploy create db 119 00:07:24,420 --> 00:07:27,530 task to run before the deploy migrate task. 120 00:07:27,530 --> 00:07:29,380 And then i'll kick off a normal deployment. 121 00:07:30,890 --> 00:07:34,750 So here within the deploy namespace, we're gonna create another task. 122 00:07:34,750 --> 00:07:36,500 We'll add a description for it first. 123 00:07:37,810 --> 00:07:41,760 This task is going to perform our first deploy to a server. 124 00:07:41,760 --> 00:07:45,140 And since it's our first deploy, we're going to know that we need to create 125 00:07:45,140 --> 00:07:49,248 the database, which is why we'll be kicking off the create_db task. 126 00:07:49,248 --> 00:07:57,085 So performs first deploy to a server. 127 00:07:57,085 --> 00:07:58,870 Now for the actual task. 128 00:08:00,537 --> 00:08:02,647 Would call it deploy initial. 129 00:08:05,681 --> 00:08:09,575 Task method takes a block with the actual statements that should be run when it's 130 00:08:09,575 --> 00:08:10,700 kick off. 131 00:08:10,700 --> 00:08:13,670 And we can use a Capistrano method called before 132 00:08:13,670 --> 00:08:17,090 to set up one task to be run before another one is. 133 00:08:17,090 --> 00:08:22,690 So before we run the deploy migrate task, 134 00:08:22,690 --> 00:08:26,840 we're going to wanna kick off the deploy create db task. 135 00:08:28,160 --> 00:08:32,600 And now that we've set create_db to be run before deploy migrate, 136 00:08:32,600 --> 00:08:35,000 we can safely invoke another task. 137 00:08:36,410 --> 00:08:39,260 The same deploy task that we've been running from the command line. 138 00:08:40,300 --> 00:08:44,470 So let's go back to the command line and try kicking that task off. 139 00:08:44,470 --> 00:08:52,889 Bundle exec cap production deploy:initial 140 00:08:57,662 --> 00:09:00,390 It runs, checks out the app from get as usual. 141 00:09:02,040 --> 00:09:03,620 Sets up the directories it needs. 142 00:09:04,630 --> 00:09:05,800 Runs bundler install, 143 00:09:05,800 --> 00:09:10,230 which is faster this time since all the dependent gems are already installed. 144 00:09:10,230 --> 00:09:12,780 Compiles assets like CSS and JavaScript. 145 00:09:14,730 --> 00:09:16,739 And that's called by pretty quick but 146 00:09:16,739 --> 00:09:19,955 it actually invoked our create_db task here at the bottom. 147 00:09:22,895 --> 00:09:25,330 Unfortunately while running it, we got an error. 148 00:09:25,330 --> 00:09:28,110 We see, Peer authentication failed for user "jay". 149 00:09:28,110 --> 00:09:32,100 Well that's strange because it's supposed to be running as the deploy user, 150 00:09:32,100 --> 00:09:34,670 that's what has access to our database. 151 00:09:34,670 --> 00:09:37,410 Here on the next line it says, Couldn't create database. 152 00:09:38,720 --> 00:09:42,210 And if we go and look at our database configuration within our Rails app, 153 00:09:42,210 --> 00:09:44,760 we'll have a guess as to what the problem is. 154 00:09:44,760 --> 00:09:49,340 In the production environment, we are configured to use the deploy username. 155 00:09:49,340 --> 00:09:51,280 But up here in development, 156 00:09:51,280 --> 00:09:54,980 we're set up to use the username jay, our developer username. 157 00:09:54,980 --> 00:09:58,850 The problem is we haven't specified a Rails environment to run our command in 158 00:09:58,850 --> 00:10:02,760 and so it's running in the development environment by default and therefore using 159 00:10:02,760 --> 00:10:05,960 the wrong username and trying to connect to the wrong database name. 160 00:10:07,220 --> 00:10:11,100 So we need to set the Rails ENV environment variable while running 161 00:10:11,100 --> 00:10:11,800 this command. 162 00:10:13,640 --> 00:10:17,290 We can do that using the Capistrano with method. 163 00:10:17,290 --> 00:10:23,060 With takes a hash with its keys as the names of environment variables. 164 00:10:23,060 --> 00:10:27,960 So we're going to specify that the rails_env environment variable, 165 00:10:27,960 --> 00:10:33,660 should be set to whatever the value of the rails_env Capistrano variable is set to. 166 00:10:33,660 --> 00:10:36,200 We retrieve that using the fetch method. 167 00:10:38,200 --> 00:10:42,490 And we specify that it should fetch the rails_env Capistrano variable. 168 00:10:42,490 --> 00:10:45,630 So that'll set the rails_env environment variable properly. 169 00:10:46,880 --> 00:10:51,510 With takes a block, any commands that you want to execute with those 170 00:10:51,510 --> 00:10:54,590 environment variables active should be placed inside it. 171 00:10:54,590 --> 00:10:59,390 So that's where we place our execute :rails, "db:setup" command. 172 00:10:59,390 --> 00:11:01,793 So now for deploying to a staging environment, 173 00:11:01,793 --> 00:11:05,397 rails environment will be set staging it for deploying to production, 174 00:11:05,397 --> 00:11:08,640 the rails environment will be set production. 175 00:11:08,640 --> 00:11:10,030 So let's save this. 176 00:11:10,030 --> 00:11:14,590 Go back to our console, and give this command another try. 177 00:11:16,170 --> 00:11:18,358 cap production deploy initial. 178 00:11:24,008 --> 00:11:27,190 It will go through the same steps as before and 179 00:11:27,190 --> 00:11:32,670 this time when it gets to the create db_task it runs successfully. 180 00:11:32,670 --> 00:11:37,240 After the create db task runs it then runs the migrations and 181 00:11:37,240 --> 00:11:39,167 then completes the remainder of the deployment.