Continuous Deployment on Shared Hosting with GitHub Actions
Tags: github, laravel, devops, vue
Published: 2021-05-02 09:32:46


<!-- Start with introduction -->
##Introduction
In this fast-paced world, where everything seems to be happening quickly, it is paramount for early as well as frequent deployment of websites/apps to keep up with the competition. There are various ways of deploying your web apps to your server but will shall be looking at how GitHub actions can help us continuously deploy our web app with minimal effort. 


<!-- Continuous deployment -->
##What is Continuous Deployment
First of all, what is continuous deployment you ask? According to [Search IT operations](https://searchitoperations.techtarget.com/definition/continuous-deployment)

>Continuous deployment is a strategy for software releases wherein any code commit that passes the automated testing phase is automatically released into the production environment, making changes that are visible to the software's users.

We will not cover tests in this post (but in a later post). As you can see from the definition, simply commit and then all your changes are on the production server.


<!-- Shared hosting explained -->
##What is Shared Hosting
There are different hosting choices with the popular ones now being shared hosting and cloud hosting. 

>A shared web hosting service is a web hosting service where many websites reside on one web server connected to the Internet.
This is the cheapest way to host your website since the different users split the cost of the web server but it also has drawbacks since the resources are split across a number of users as well.

<!-- explain why its a bore to continuously transfer using ftp or upload -->
I have been using shared hosting for a long time and I got bored with transferring my files via FTP every time I made changes. I then resorted to using [GitHub](https://github.com/) where I pushed my code to the repo then pulled it from my shared hosting. I still was not satisfied. I used [GitFtp](https://github.com/git-ftp/git-ftp/blob/master/man/git-ftp.1.md) which was alright. Until I learned about CI/CD in my [Azubi Africa](https://azubiafrica.org/) class.


<!-- GitHub Actions to the rescue -->
##GitHub Actions to the rescue
After further research, came across GitHub actions. According to their [site](https://docs.github.com/en/actions):

>Automate, customize, and execute your software development workflows right in your repository with GitHub Actions. You can discover, create, and share actions to perform any job you'd like, including CI/CD, and combine actions in a completely customized workflow.


<!-- write the workflow -->
##The Workflow
Let us get to the juicy bit by doing some actual work.
###Setting up GitHub actions
(This is assuming you already have a repository in your GitHub account that you want to link to your shared hosting. if not, click [here](https://docs.github.com/en/github/getting-started-with-github/create-a-repo)).

* Open your repository on GitHub and head over to `Actions` tab.
![Actions tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nz2r7n2ol9lmdoufieb.PNG 
"Press the actions tab")

* Click on the `set up a workflow yourself → ` as shown below.
![Set up workflow yourself](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a75hv8mivxjewwrx3z6o.PNG "Press the set up a workflow yourself")

* Delete all the contents of main.yml on the page as shown below:
![Delete contents](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zh0zns1emgnoflkerjip.PNG "Delete all contents in the main.yml file")

* Replace the file with below contents (note this is for a project in Laravel with a Vue frontend)

```yaml
name: Deploy Site on push
on:
  push:
    branches:
      - master
jobs:
  web-deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
    - name: Get the latest code
      uses: actions/checkout@v2.3.2
    - uses: actions/setup-node@master
    - name: Installing project dependencies
      run: npm install
    - name: Building the project
      run: npm run production
    - name: Copy .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
    - name: Install Dependencies
      run: composer update --ignore-platform-reqs
    - name: Generate key
      run: php artisan key:generate
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
    - name: 📂 Sync files
      uses: SamKirkland/FTP-Deploy-Action@4.0.0
      with:
        server: ${{ secrets.LARAVEL_SITE_SERVER}}
        username: ${{ secrets.LARAVEL_SITE_USER}}
        password: ${{ secrets.LARAVEL_SITE_PASS}}
```
<!-- explain the workflow -->

Let me now explain block by block what is going on
```yaml
name: Deploy Site on push
```

This is the name of the workflow. GitHub displays the names of your workflows on your repository’s actions page after you write it.


```yaml
on:
  push:
    branches:
      - master
```

This is where the GitHub action system is told when to run the workflow. The above snippet triggers the workflow when one pushes to the `master branch`. For more on the On key, click [here](https://docs.github.com/en/actions/learn-github-actions/introduction-to-github-actions#:~:text=GitHub%20Actions%20are%20event%2Ddriven,executes%20a%20software%20testing%20script.)

```yaml
jobs:
  web-deploy:
    name: Deploy
    runs-on: ubuntu-latest
```

*jobs* - Groups together all the jobs that run in the workflow file.
 
*web-deploy* - Defines the name of the web-deploy job stored within the jobs section.

*runs-on: ubuntu-latest* - Configures the job to run on an Ubuntu Linux runner. This means that the job will execute on a fresh virtual machine hosted by GitHub.

```yaml
steps:
    - name: Get the latest code
      uses: actions/checkout@v2.3.2
    - uses: actions/setup-node@master
    - name: Installing project dependencies
      run: npm install
    - name: Building the project
      run: npm run production
```
_Remember that the steps are inside the job block._

*steps* - Groups together all the steps that run in the web-deploy job. Each item nested under this section is a separate action or shell command.

*name* - For identification of the separate action.

*uses: actions/checkout@v2.3.2* - The uses keyword tells the job to retrieve v2 of the community action named actions/checkout@v2.3.2. This is an action that checks out your repository and downloads it to the runner, allowing you to run actions against your code (such as testing tools). You must use the checkout action any time your workflow will run against the repository's code or you are using an action defined in the repository.

*uses: actions/setup-node@master* - This action installs the node software package on the runner, giving you access to the npm command.

*run: npm install* - The run keyword tells the job to execute a command on the runner. In this case, you are using npm to install the package node dependecies.

*run: npm run production* - This builds the Vue frontend project.

```yaml

- name: Copy .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: '8.0'
    - name: Install Dependencies
      run: composer update --ignore-platform-reqs
    - name: Generate key
      run: php artisan key:generate
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
```
*run: php -r "file_exists('.env') || copy('.env.example', '.env');* - This creates a .env file if it does not already exist (this is important as this is automatically added to the .gitignore file).

*run: composer update --ignore-platform-reqs* - This is used to install and update the composer packages.

*run: php artisan key:generate* - This generates a key for the Laravel project.

*run: chmod -R 777 storage bootstrap/cache* - This changes permissions for the specified folder.

```yaml
- name: 📂 Sync files
      uses: SamKirkland/FTP-Deploy-Action@4.0.0
      with:
        server: ${{ secrets.LARAVEL_SITE_SERVER}}
        username: ${{ secrets.LARAVEL_SITE_USER}}
        password: ${{ secrets.LARAVEL_SITE_PASS}}
```

This is where the files are now transferred to the shared hosting server. Get your FTP details from your [shared hosting](https://docs.cpanel.net/cpanel/files/ftp-accounts/). Then go to `your repo>settings>secrets` then add the three secrets namely: server, username and then password. This action is courtesy of [SamKirkland](https://github.com/SamKirkland/FTP-Deploy-Action).


For more information on GitHub actions, [click here](https://docs.github.com/en/actions/learn-github-actions/introduction-to-github-actions#:~:text=GitHub%20Actions%20are%20event%2Ddriven,executes%20a%20software%20testing%20script.)

Enjoy 😎