{"id":14508,"date":"2016-08-30T12:15:12","date_gmt":"2016-08-30T09:15:12","guid":{"rendered":"https:\/\/www.webcodegeeks.com\/?p=14508"},"modified":"2016-08-26T19:51:17","modified_gmt":"2016-08-26T16:51:17","slug":"getting-started-laravel-codeship-part-ii","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/","title":{"rendered":"Getting Started With Laravel On Codeship &#8211; Part II"},"content":{"rendered":"<p>In <a href=\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship\/\">the first part of this series<\/a>, I stepped through the basics of creating a continuous-deployment pipeline for a Laravel-based application using Codeship. We had a look at the application\u2019s overall structure, its configuration, created database migrations, and created some acceptance tests. We finished up by working through an initial Codeship project creation, so that the test-suite could be run whenever a push was made to the project\u2019s \u2248master branch in its GitHub repository.<\/p>\n<p>As I mentioned at the end of that article, it wasn\u2019t the whole story. We\u2019ve only gotten halfway down our continuous deployment pipeline. What\u2019s missing is the part where we actually deploy the application to a production (or testing or staging) server. That\u2019s what we\u2019re going to do in this, the second and final, part of the series.<\/p>\n<p>Specifically, we\u2019ll cover how to refactor the application, so that it uses a PostgreSQL database, instead of SQLite. I\u2019ll demonstrate how to update the environment configuration, so that it includes the relevant variables necessary to test the build, using Codeship\u2019s PostgreSQL database, available in all projects.<\/p>\n<p>We\u2019ll wrap things up by deploying the project to a DigitalOcean droplet. We\u2019ll also see how to use ElephantSQL as our host, instead of a PostgreSQL installation on the droplet.<\/p>\n<p>Let\u2019s get started.<\/p>\n<h2>Updating the Environment Configuration<\/h2>\n<p>The first thing we need to do is update the environment configuration variables. Specifically, we need to change the database-related ones and then add some extra variables to support the deployment process.<\/p>\n<p>Did you know that every Codeship build contains <a href=\"https:\/\/codeship.com\/documentation\/databases\/postgresql\/\">an installation of PostgreSQL<\/a>? Codeship provides support for versions 9.2\u20139.5, as at the time of writing.<\/p>\n<p>Regardless of what version you need, it\u2019s easy to access. The port number you use has symmetry with the PostgreSQL version number. So, version 9.2 is available on port 5432, version 9.3 is available on port 5433, and so on.<\/p>\n<p>So the first thing we\u2019re going to do is change the <code>DB_CONNECTION<\/code> environment variable to be <code>pgsql<\/code> and add a new variable, called <code>DB_PORT<\/code>, giving it the value <code>5435<\/code>.<\/p>\n<p>With that done, we need to add two extra variables, so that we can authenticate with the database. These are <code>DB_USERNAME<\/code> and <code>DB_PASSWORD<\/code>. The values for these settings will be set from two pre-existing environment variables. These are <code>$PG_USER<\/code> and <code>$PG_PASSWORD<\/code>. Add these in, and we\u2019ve made the required changes for the database.<\/p>\n<p>Now we need to add a further set of environment variables to support the deployment tool we\u2019ll use, which we\u2019ll see shortly. The deployment environment variables we\u2019ll need are:<\/p>\n<ul>\n<li><strong>REPOSITORY:<\/strong> The git repository storing our code<\/li>\n<li><strong>RELEASES:<\/strong> The number of deployed releases to keep<\/li>\n<li><strong>DEPLOY_DIR:<\/strong> The directory to deploy the code<\/li>\n<li><strong>DEPLOY_USER:<\/strong> The operating system user who will run the deploy<\/li>\n<li><strong>PRODUCTION_IP_ADDRESS:<\/strong> The IP address of the server to deploy to<\/li>\n<\/ul>\n<p>A quick note on the <code>DEPLOY_USER<\/code> setting: Make sure that they have permissions to write to the directory, and that there is a public key for that user stored on your GitHub account. This way, they can access the repository, if it\u2019s private.<\/p>\n<h2>Updating the Setup Commands<\/h2>\n<p>With the new environment variables set, we need to update the Setup Commands. We\u2019re not going to do much, other than to remove one line \u2014 <code>touch database\/database.sqlite<\/code> \u2014 which set up the SQLite database file.<\/p>\n<p>We\u2019re not using SQLite in testing anymore, so we don\u2019t need that configuration. Under <code>Project Settings -&gt; Test -&gt; Setup Commands<\/code>, remove that line from the configuration.<\/p>\n<h2>Updating The Code<\/h2>\n<p>With these changes made, we need to make a few small updates to the application code and configuration so that it uses PostgreSQL instead of SQLite.<\/p>\n<p>First, we need to create a copy of <code>.env<\/code> that will be copied to somewhere on our hosting server, say <code>\/opt\/application\/config<\/code>. In there, we need to set <code>DB_CONNECTION<\/code> to have the value <code>pgsql<\/code>. With that done, copy it to your web host.<\/p>\n<p>The reason for this is that we\u2019re not going to store it under version control. If we did, there\u2019s a risk that, at some stage, the credentials may leak out. Plus, storing it under version control violates <a href=\"https:\/\/12factor.net\/config\">one of the tenets of a Twelve-Factor app<\/a>.<\/p>\n<p>The next change is optional, depending on how you\u2019re going to handle caching. By default, Laravel uses a filesystem cache. If we continue down that road, the build will fail when we deploy the application. The reason is because <code>bootstrap\/cache<\/code> is listed in <code>.gitignore<\/code>. Given that, it won\u2019t exist when a deploy is run, leading to an error when that directory is attempted to be used.<\/p>\n<p>So, you have two choices. You can add extra configuration and environment variables to use a caching service. Or you can remove <code>bootstrap\/cache<\/code> from <code>.gitignore<\/code>.<\/p>\n<h3>ElephantSQL<\/h3>\n<p>As I mentioned <a href=\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship\/\">in part one<\/a>, in this, the final post in the series, we\u2019re going to be using an external service, <a href=\"https:\/\/www.elephantsql.com\/\">ElephantSQL<\/a>.<\/p>\n<p>I\u2019ll assume that you don\u2019t already have an account with them, and step through the process of setting one up. Happily, their interface makes it almost trivial. What\u2019s more, they have a free plan, so that you don\u2019t have to pay anything to give them a try.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephantsql-tiny-turtle-plan.png\"><img decoding=\"async\" class=\"aligncenter wp-image-14510\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephantsql-tiny-turtle-plan.png\" alt=\"elephantsql-tiny-turtle-plan\" width=\"860\" height=\"643\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephantsql-tiny-turtle-plan.png 2596w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephantsql-tiny-turtle-plan-300x224.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephantsql-tiny-turtle-plan-768x574.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephantsql-tiny-turtle-plan-1024x765.png 1024w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<ol>\n<li>In your browser, navigate to <a href=\"http:\/\/www.elephantsql.com\/plans.html\">www.elephantsql.com\/plans.html<\/a>.<\/li>\n<li>Scroll down and click <strong>Try now for FREE<\/strong>, under the Tiny Turtle option. You\u2019ll be taken to a login and signup page.<\/li>\n<li>Under <strong>Sign up<\/strong>, you\u2019ll see a section titled <strong>Sign up or login<\/strong>. Click the button labeled <strong>Sign in with GitHub<\/strong>. You\u2019ll be asked to authorize ElephantSQL\u2019s access to your GitHub repositories. <a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/github-authorize-access.png\"><img decoding=\"async\" class=\"aligncenter wp-image-14511\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/github-authorize-access.png\" alt=\"github-authorize-access\" width=\"860\" height=\"643\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/github-authorize-access.png 2596w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/github-authorize-access-300x224.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/github-authorize-access-768x574.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/github-authorize-access-1024x765.png 1024w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/li>\n<li>Click <strong>Authorize application<\/strong>. With that completed, you\u2019ll be redirected and logged in to your ElephantSQL dashboard.<\/li>\n<li>Click the blue <strong>Create<\/strong> button on the right-hand side.<\/li>\n<li>Add a name for your database, pick a data center, and click <strong>Create<\/strong>. You\u2019ll see your database in the list.<\/li>\n<li>Finally, we need to get the connection details, so that we can update our environment settings. Click <strong>Details<\/strong>, and make a note of the URL, hostname, database and usernames, and password. <a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephant-sql-instances.png\"><img decoding=\"async\" class=\"aligncenter wp-image-14512\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephant-sql-instances.png\" alt=\"elephant-sql-instances\" width=\"860\" height=\"643\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephant-sql-instances.png 2596w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephant-sql-instances-300x224.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephant-sql-instances-768x574.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2016\/08\/elephant-sql-instances-1024x765.png 1024w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/li>\n<li>With those at hand, you need to add them to the production server configuration environment. I have a sample in the next section. You also need to set them in your environment settings.<\/li>\n<\/ol>\n<p>I know, this has largely been taken care of quite effortessly so far. But this part takes a little bit of manual intervention, depending on how you\u2019re handling server provisioning. The simplest way that I can recommend is by using <a href=\"https:\/\/www.ansible.com\/\">Ansible<\/a>.<\/p>\n<p>If you\u2019d like a more comprehensive guide, check out <a href=\"https:\/\/blog.codeship.com\/packer-ansible\/\">Using Packer and Ansible to Build Immutable Infrastructure<\/a> by Marko Locher, here on the Codeship blog. Whichever way you go, ensure that those environment variables are set in your production environment.<\/p>\n<h2>The Deployment Server<\/h2>\n<p>Before we get on to working through how we\u2019re going to deploy the code, we need to cover the deployment server and its requirements.<\/p>\n<p>Make sure that the server supports either PHP 5.6 or 7.0 and has the pgsql extension installed and enabled. It also needs to have a recent version of Git installed.<\/p>\n<p>Next, make sure that the NIGINX or Apache virtual host configuration is set up to host a Laravel application. Also, make sure that that the <em>DB_<\/em> environment variables, which I showed you how to set earlier, have been set.<\/p>\n<p>If you have all that done, there are no other critical services, packages, or configurations required. Here\u2019s a minimal, sample, Apache VirtualHost configuration:<\/p>\n<pre class=\"brush:php\">&lt;VirtualHost *:80&gt;\r\n    ServerAdmin webmaster@localhost\r\n    DocumentRoot \/var\/www\/html\/current\/public\r\n\r\n    ErrorLog ${APACHE_LOG_DIR}\/error.log\r\n    CustomLog ${APACHE_LOG_DIR}\/access.log combined\r\n\r\n    SetEnv DB_USERNAME your_database_username\r\n    SetEnv DB_PASSWORD your_database_password\r\n    SetEnv DB_DATABASE your_database_name\r\n    SetEnv DB_HOST your_database_hostname\r\n\r\n    &lt;Location \/&gt;\r\n            RewriteEngine On\r\n            RewriteCond %{REQUEST_FILENAME} -s [OR]\r\n            RewriteCond %{REQUEST_FILENAME} -l [OR]\r\n            RewriteCond %{REQUEST_FILENAME} -d\r\n            RewriteRule ^.*$ - [NC,L]\r\n            RewriteRule ^.*$ \/index.php [NC,L]\r\n    &lt;\/Location&gt;\r\n\r\n&lt;\/VirtualHost&gt;<\/pre>\n<h2>Deploying the Application<\/h2>\n<p>Now that the environment configuration is ready to go, we need to step through the deployment process. Like all things in PHP, there are a host of ways in which you can do it.<\/p>\n<p>There\u2019s <a href=\"https:\/\/www.phing.info\">Phing<\/a>, Capistrano, SCP, Rsync over SSH, and so on. But the one that I\u2019m going to be covering is a newer tool, one written specifically in PHP, called <a href=\"http:\/\/deployer.org\">Deployer<\/a>.<\/p>\n<p>Deployer is a handy library that works in a similar way to Phing, <a href=\"http:\/\/www-rohan.sdsu.edu\/doc\/make.html\">Make<\/a>, and <a href=\"http:\/\/ant.apache.org\">Ant<\/a>. You create one or more tasks that have to be run during deployment. You provide details of the deployment server you\u2019re going to deploy on, whether that\u2019s one server (such as production) or multiple (such as <em>testing<\/em>, <em>production<\/em>, and <em>staging<\/em>).<\/p>\n<p>Then you run the deployment. All the tasks are run in the order in which you\u2019ve specified them. All going well, the deployment works just as you expected.<\/p>\n<p>What\u2019s extra nice about Deployer, aside from being written in PHP, is that it comes with a series of prepackaged tasks and it supports rollback and deployment versioning. As far as its prepackaged tasks, there are task recipes for working with Composer-based builds as well as a variety of services and tools, such as <em>New Relic<\/em>, <em>RabbitMQ<\/em>, <em>Slack<\/em>, and <em>HipChat<\/em>.<\/p>\n<p>To make Deployer available, copy the phar version to your repository by calling:<\/p>\n<pre class=\"brush:php\">wget http:\/\/deployer.org\/deployer.phar<\/pre>\n<p>This will bring in the latest version (3.3.0 at the time of writing). Next, we need to create a Deployer configuration file called <code>deploy.php<\/code> in the root of our project. It\u2019s a little lengthy, so I\u2019ll work through it a piece at a time.<\/p>\n<pre class=\"brush:php\">require __DIR__ . 'vendor\/autoload.php';\r\nrequire __DIR__ . 'vendor\/deployer\/deployer\/recipe\/composer.php';\r\n\r\nset(\"sudo_for_composer_is_wrong\", true);<\/pre>\n<p>First, we import the classes we\u2019ll be using and specify that we\u2019re not going to attempt to use sudo with Composer.<\/p>\n<pre class=\"brush:php\">server('digitalocean', getenv('PRODUCTION_IP_ADDRESS'))\r\n    -&gt;user(getenv('DEPLOY_USER'))\r\n    -&gt;password(getenv('DEPLOY_PASSWORD'))\r\n    -&gt;stage('production')\r\n    -&gt;env('deploy_path', getenv('DEPLOY_DIR'));<\/pre>\n<p>Next, we create a server configuration; in this case just one, called production. In the call to <code>server()<\/code>, we specify the hostname and IP address of the server.<\/p>\n<p>We next call <code>user()<\/code> and <code>password()<\/code> to authenticate to the server as a given user. Alternatively, we could use a combination of <code>user()<\/code> and <code>identityFile()<\/code> to instead use SSH public keys. We then use <code>stage()<\/code> to give a name to the server and provide a custom environment variable, by making a call to <code>env()<\/code>.<\/p>\n<pre class=\"brush:php\">set('repository', getenv('REPOSITORY'));\r\nset('keep_releases', getenv('RELEASES'));<\/pre>\n<p>Next, we set the repository where the code is located, as well as the number of releases to keep in addition to the current one, by making two calls to the <code>set()<\/code> method. This is responsible for setting Deployer configuration settings.<\/p>\n<p>At this point, you can now see where all of the extra environment variables we added before will be used. By default, unless we set it explicitly, Deployer will keep up to five releases of our application. I know that we set <code>RELEASES<\/code> to five.<\/p>\n<p>But I wanted to be explicit, particularly since this is a key setting. If something goes wrong, we can quickly roll back. Ideally, we\u2019ll never have to do that, but it\u2019s crucial to have it there should we need to.<\/p>\n<pre class=\"brush:php\">task('deploy:copy-env-file', function () {\r\n    $deployPath = '\/var\/www\/html\/current\/';\r\n    $envFile = '\/path\/to\/your\/.env\/file';\r\n    run(\"cp {$envFile} {$deployPath}\");\r\n})-&gt;desc(\"Copy the env file\");\r\n\r\ntask('deploy:database-migrations', function () {\r\n    $deployPath = '\/var\/www\/html\/current\/';\r\n    cd($deployPath);\r\n    run(\"php artisan migrate\");\r\n})-&gt;desc(\"Run the database migrations\");\r\n\r\ntask('deploy:done', function () {\r\n    write('Deploy done!');\r\n})-&gt;desc(\"Run artisan make\");\r\n\r\ntask('deploy', [\r\n    'deploy:prepare',\r\n    'deploy:release',\r\n    'deploy:update_code',\r\n    'deploy:copy-env-file',\r\n    'deploy:vendors',\r\n    'deploy:symlink',\r\n    'cleanup',\r\n    'deploy:database-migrations',\r\n])-&gt;desc(\"The main deployment process\");<\/pre>\n<p>Now we write some custom tasks and compose the deployment pipeline. A task is composed of three parts:<\/p>\n<ul>\n<li>A name<\/li>\n<li>A callback, or list of tasks, which handles the task\u2019s work<\/li>\n<li>A task description, which is optional<\/li>\n<\/ul>\n<p>In the first task, we\u2019re copying the environment file to our new installation. In the second task, we\u2019re running the database migrations on our database hosted on ElephpantSQL. And in the third task, we\u2019re creating a message to provide visual confirmation of the fact that the deployment is completed.<\/p>\n<p>Now for the deployment pipeline. In this one, I\u2019ve passed an array of pre-existing tasks (or recipes) to run which form the deployment process, along with our three custom tasks.<\/p>\n<p>These will prepare the release, check out the latest version from the repository, run a composer update, symlink the latest copy as the current version, and remove any unnecessary releases, if there are more than the required number still present.<\/p>\n<pre class=\"brush:php\">\/\/ The task to run after deployment\r\nafter('deploy', 'deploy:done');<\/pre>\n<p>Now for the last step. Here, we\u2019re specifying what to do when a release finishes. In this case, we\u2019re running our custom notification task, which we saw just a moment ago.<\/p>\n<h2>The Deployment Pipeline<\/h2>\n<p>We now have one final task to take care of before we can run the deployment: create a deployment pipeline.<\/p>\n<ol>\n<li>Under <strong>Project Settings -&gt; Deployment<\/strong>, click <strong>Custom Script<\/strong>. You\u2019ll see a text box, similar to what we\u2019ve seen previously when setting the Test configuration.<\/li>\n<li>Add the following, adding in the details for your deployment server.<\/li>\n<\/ol>\n<pre class=\"brush:php\">export PRODUCTION_IP_ADDRESS=\r\nexport DEPLOY_USER=\r\nexport DEPLOY_PASSWORD=\r\nexport DEPLOY_DIR=\r\nphp deployer.phar deploy production<\/pre>\n<p>This will export the environment settings that the deployer needs and then run the deployer binary, calling the deploy method, and specifying that the server we\u2019ll be deploying to is named <code>production<\/code>. That will then run the deployment pipeline which we established, and finalize the deployment.<\/p>\n<h2>Deploying the Application<\/h2>\n<p>With all that done, we\u2019re now ready to deploy our application. Assuming you\u2019ve not pushed the change to the application to the repository yet, push them now, and a new build will be triggered.<\/p>\n<p>A few minutes after you\u2019ve pushed the code, the build will be triggered. If all goes well, your shiny Laravel application will be deployed.<\/p>\n<h2>Conclusion<\/h2>\n<p>And that is how you can set up a deployment pipeline for Laravel with Codeship. Admittedly, it\u2019s a bit of a long pipeline, but it\u2019s completely transparent as to what\u2019s going on and how it\u2019s been setup. There are a number of moving parts, but when combined together, they work very well.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"https:\/\/blog.codeship.com\/getting-started-with-laravel-on-codeship-part-ii\/\">Getting Started With Laravel On Codeship &#8211; Part II<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/join-us\/wcg\/\">WCG partner<\/a>\u00a0Matthew Setter\u00a0at the <a href=\"http:\/\/blog.codeship.com\/\">Codeship Blog<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the first part of this series, I stepped through the basics of creating a continuous-deployment pipeline for a Laravel-based application using Codeship. We had a look at the application\u2019s overall structure, its configuration, created database migrations, and created some acceptance tests. We finished up by working through an initial Codeship project creation, so that &hellip;<\/p>\n","protected":false},"author":119,"featured_media":930,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"class_list":["post-14508","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-php"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Getting Started With Laravel On Codeship - Part II - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"In the first part of this series, I stepped through the basics of creating a continuous-deployment pipeline for a Laravel-based application using\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Getting Started With Laravel On Codeship - Part II - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"In the first part of this series, I stepped through the basics of creating a continuous-deployment pipeline for a Laravel-based application using\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2016-08-30T09:15:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Matthew Setter\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@settermjd\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matthew Setter\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/\"},\"author\":{\"name\":\"Matthew Setter\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/b05e82f4b706b29d2bfb20134e3d2f35\"},\"headline\":\"Getting Started With Laravel On Codeship &#8211; Part II\",\"datePublished\":\"2016-08-30T09:15:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/\"},\"wordCount\":2185,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg\",\"articleSection\":[\"PHP\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/\",\"name\":\"Getting Started With Laravel On Codeship - Part II - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg\",\"datePublished\":\"2016-08-30T09:15:12+00:00\",\"description\":\"In the first part of this series, I stepped through the basics of creating a continuous-deployment pipeline for a Laravel-based application using\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PHP\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/php\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Getting Started With Laravel On Codeship &#8211; Part II\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/b05e82f4b706b29d2bfb20134e3d2f35\",\"name\":\"Matthew Setter\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/93462db49ad0350a33d70149761702068941d2e0c07150ae8c32df9512fc2bde?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/93462db49ad0350a33d70149761702068941d2e0c07150ae8c32df9512fc2bde?s=96&d=mm&r=g\",\"caption\":\"Matthew Setter\"},\"description\":\"Matthew Setter is a developer and technical writer. He creates web-based applications and technical content that engage developers with platforms, technologies, applications, and tools.\",\"sameAs\":[\"https:\/\/x.com\/settermjd\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/matthew-setter\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Getting Started With Laravel On Codeship - Part II - Web Code Geeks - 2026","description":"In the first part of this series, I stepped through the basics of creating a continuous-deployment pipeline for a Laravel-based application using","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/","og_locale":"en_US","og_type":"article","og_title":"Getting Started With Laravel On Codeship - Part II - Web Code Geeks - 2026","og_description":"In the first part of this series, I stepped through the basics of creating a continuous-deployment pipeline for a Laravel-based application using","og_url":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2016-08-30T09:15:12+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg","type":"image\/jpeg"}],"author":"Matthew Setter","twitter_card":"summary_large_image","twitter_creator":"@settermjd","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Matthew Setter","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/"},"author":{"name":"Matthew Setter","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/b05e82f4b706b29d2bfb20134e3d2f35"},"headline":"Getting Started With Laravel On Codeship &#8211; Part II","datePublished":"2016-08-30T09:15:12+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/"},"wordCount":2185,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg","articleSection":["PHP"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/","url":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/","name":"Getting Started With Laravel On Codeship - Part II - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg","datePublished":"2016-08-30T09:15:12+00:00","description":"In the first part of this series, I stepped through the basics of creating a continuous-deployment pipeline for a Laravel-based application using","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/php-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/php\/getting-started-laravel-codeship-part-ii\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"PHP","item":"https:\/\/www.webcodegeeks.com\/category\/php\/"},{"@type":"ListItem","position":3,"name":"Getting Started With Laravel On Codeship &#8211; Part II"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/b05e82f4b706b29d2bfb20134e3d2f35","name":"Matthew Setter","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/93462db49ad0350a33d70149761702068941d2e0c07150ae8c32df9512fc2bde?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/93462db49ad0350a33d70149761702068941d2e0c07150ae8c32df9512fc2bde?s=96&d=mm&r=g","caption":"Matthew Setter"},"description":"Matthew Setter is a developer and technical writer. He creates web-based applications and technical content that engage developers with platforms, technologies, applications, and tools.","sameAs":["https:\/\/x.com\/settermjd"],"url":"https:\/\/www.webcodegeeks.com\/author\/matthew-setter\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/14508","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/119"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=14508"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/14508\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/930"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=14508"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=14508"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=14508"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}