Laravel deployment with GitHub Actions

Philo Hermans
25 Jan 202149:45

Summary

TLDRIn this debut YouTube video, Filo, a self-taught developer with 20 years of experience, guides viewers through deploying an application to multiple servers without downtime using GitHub Actions. He begins by creating a new GitHub repository and using Laravel for demonstration, though the method is adaptable to other frameworks. The video covers the steps of setting up GitHub workflows, configuring YAML files, and preparing the application for production. Filo demonstrates creating deployment artifacts, configuring PHP, and managing npm and composer dependencies. The video includes tips on creating a server list JSON file, handling artifacts, and ensuring a seamless deployment across multiple servers. Filo troubleshoots common issues, emphasizing best practices in deployment and server management.

Takeaways

  • ๐Ÿ˜„ Filo, a self-taught developer, shares his journey and expertise through his first YouTube video, focusing on deploying applications without downtime using GitHub Actions.
  • ๐Ÿ’ป GitHub Actions is introduced as a powerful tool to automate workflows, allowing deployment to multiple servers upon a commit to the master branch.
  • ๐Ÿ“ฒ Filo uses a Laravel application for demonstration but emphasizes that the process can be applied to any project, highlighting the versatility of GitHub Actions.
  • ๐Ÿ”ง The video tutorial covers the creation of a GitHub repository, setting up a workflow with YAML syntax, and preparing the application for the production environment.
  • ๐Ÿ›  Key steps in the workflow include checking out the code, compiling assets with NPM, configuring PHP, installing Composer dependencies, and creating a deployable artifact.
  • ๐Ÿ” Filo demonstrates how to dynamically name the deployment artifact using the commit hash for easier identification and manageability of releases.
  • ๐Ÿ”’ The process includes securely configuring server information within a JSON file, showcasing how to handle multiple deployment targets within GitHub Actions.
  • ๐Ÿšจ Challenges like password requirements and environment variable configurations are addressed, showing how to troubleshoot and adjust workflows.
  • ๐Ÿ”จ Filo navigates through server setup on DigitalOcean, including SSH access and configuring Nginx to point to the correct directory for the deployed application.
  • ๐Ÿ’ก The script concludes by detailing cleanup processes to maintain server health and demonstrating the deployment across multiple servers, showcasing scalability.

Q & A

  • What is the purpose of this video?

    -The purpose of this video is to demonstrate how to deploy a Laravel application to multiple servers without any downtime using GitHub Actions.

  • What is GitHub Actions, and how does it work in this context?

    -GitHub Actions is a feature that allows you to trigger workflows when specific GitHub events occur, such as pushing commits to a branch. In this video, it is used to automate the deployment process of a Laravel application to multiple servers.

  • What are the main steps involved in the deployment process demonstrated in the video?

    -The main steps include setting up the workflow, creating deployment artifacts, uploading artifacts to servers, extracting archives, running before and after hooks, activating the release by symlink swapping, and cleaning up old releases and artifacts.

  • How does the video handle the Laravel environment configuration during deployment?

    -The video creates an environment variable containing the Laravel environment configuration (including database settings, app name, etc.) as a GitHub secret. During deployment, it generates an .env file in the release directory by printing the contents of this secret.

  • What is the purpose of the 'before' and 'after' hooks in the deployment process?

    -The 'before' hook allows running commands before the release is activated, such as running database migrations or backups. The 'after' hook allows running commands after the release is activated, such as sending notifications.

  • How does the video handle shared storage between different releases?

    -The video creates a shared 'storage' directory outside of the release directories. During deployment, it removes the 'storage' directory from the release and symlinks it to the shared storage directory.

  • What is the purpose of the 'cleanup' step in the deployment process?

    -The 'cleanup' step removes old release directories and artifacts directories from the servers, keeping only a limited number of recent releases to conserve disk space.

  • How does the video handle deploying to multiple servers?

    -The video uses a deployment matrix configuration, which allows the deployment steps to be executed in parallel on multiple servers defined in a JSON configuration file.

  • What is the role of the 'symlink swap' technique used in the video?

    -The 'symlink swap' technique involves creating a symbolic link called 'current' that points to the new release directory. This allows switching to the new release without any downtime by simply updating the symlink.

  • What additional considerations should be taken into account when deploying to production servers?

    -The video mentions using repository secrets and SSH keys instead of hardcoding credentials in the configuration file. Additionally, it's recommended to follow best practices for security, monitoring, and error handling in a production environment.

Outlines

00:00

๐ŸŽฌ Introduction and Deploying an Application Using GitHub Actions

The host introduces himself and the topic of deploying an application across multiple servers without downtime using GitHub Actions. He creates a new private GitHub repository and initializes it with a plain Laravel installation. He then explains GitHub Actions and how they can be triggered by specific events like commits to the master branch.

05:02

๐Ÿ”ง Creating Deployment Artifacts

This paragraph covers steps involved in preparing the application for deployment. It includes installing npm dependencies, compiling CSS and JavaScript, configuring PHP version and extensions, installing Composer dependencies, creating a deployment archive with the commit hash as the file name, and uploading the artifact to GitHub.

10:03

โ˜๏ธ Setting Up Server Configuration

The host creates a JSON file to store server configurations like IP address, username, password, port, hooks for before and after deployment, and server path. He then provisions a new server on DigitalOcean and updates the server configuration file with the server's IP address and password.

15:04

๐Ÿ”‘ Exporting Deployment Matrix

This paragraph explains how to export the deployment configuration as a matrix to make it available within the GitHub Actions workflow. It involves creating a new step to read the JSON file, echo its contents with a specific syntax, and store it as an output for later reference.

20:06

๐Ÿ’ป Preparing Release on Server

This section covers downloading the deployment artifact from the previous job, uploading it to the configured servers using an action, extracting the archive, creating required directories for the Laravel application, and linking the storage directory to a shared location.

25:07

๐Ÿ—๏ธ Running Before Hooks and Setting Environment Variables

The host creates a new job to run before hooks defined in the server configuration. It involves setting up environment variables like the release path, active release path, storage path, and base path, making them available on the remote server, and executing commands specified in the before hooks.

30:08

๐Ÿš€ Activating the Release

This paragraph covers the steps to activate the new release, including symlinking the current directory to the new release, creating and linking the .env file with Laravel environment variables, linking the storage directory, and reloading PHP-FPM if necessary.

35:08

๐Ÿ”„ Running After Hooks

Similar to the before hooks, this section creates a new job to run after hooks defined in the server configuration. These hooks can be used to perform tasks like sending notifications after a successful deployment.

40:09

๐Ÿงน Cleaning Up Releases and Artifacts

To prevent disk space issues on the server, this paragraph introduces a cleanup step that removes old releases and artifacts, keeping only the most recent five releases and associated artifacts.

45:09

๐ŸŽ‰ Deploying to Multiple Servers

The host demonstrates deploying the Laravel application to multiple servers simultaneously using the configured matrix. He updates the application to display the server name on the welcome page, showcasing the successful deployment across all servers without downtime.

Mindmap

Keywords

๐Ÿ’กGitHub Actions

GitHub Actions is a CI/CD (Continuous Integration and Continuous Deployment) platform that allows developers to automate their software development workflows directly within GitHub. In the context of the video, GitHub Actions is used to automate the deployment process of an application to multiple servers without downtime. The script demonstrates how GitHub Actions can trigger workflows based on specific events, such as a push to the master branch, to build the product and upload it to multiple servers, illustrating its utility for seamless, automated deployment.

๐Ÿ’กDeployment

Deployment in software development refers to the process of making an application available for use. The video focuses on deploying a Laravel application across multiple servers without any downtime, highlighting the importance of deployment in maintaining the availability and reliability of web applications. The use of GitHub Actions for automated deployment processes is discussed, showcasing how deployment strategies can be automated to ensure consistent and error-free application releases.

๐Ÿ’กLaravel

Laravel is a web application framework with expressive, elegant syntax. In the script, a plain Laravel installation serves as the example project for demonstrating the deployment process. This choice illustrates Laravel's popularity and utility as a PHP framework for building modern web applications. The video covers specific steps related to Laravel deployment, such as compiling CSS and JavaScript, and configuring PHP, underscoring the framework's requirements in real-world deployment scenarios.

๐Ÿ’กYAML Syntax

YAML Syntax refers to the data serialization format used for writing configuration files, which is both human-readable and machine-processable. In the context of the video, GitHub Actions workflows are defined using YAML syntax, showcasing how deployment workflows are configured. The script provides an example of creating a YAML file to define triggers, jobs, and steps for the deployment process, highlighting YAML's role in specifying the operational details of GitHub Actions workflows.

๐Ÿ’กCI/CD

CI/CD stands for Continuous Integration and Continuous Deployment, a set of practices designed to automate the integration of code changes into a shared repository and to ensure that applications are reliably released to production without downtime. The video emphasizes the CI/CD aspect by using GitHub Actions to automate the build and deployment process of a Laravel application to multiple servers, showcasing how CI/CD methodologies can streamline software development workflows.

๐Ÿ’กWorkflow

In the context of GitHub Actions, a workflow is an automated process that you set up in your GitHub repository to build, test, package, release, or deploy any project on GitHub. The script outlines the creation of a workflow file using YAML syntax to define the deployment process, including jobs like setting up the environment, compiling assets, and uploading the build to servers. This highlights the flexibility and power of GitHub Actions to automate complex software development tasks.

๐Ÿ’กArtifact

An artifact is a file or collection of files produced during a workflow run, such as a compiled application, logs, or binary files, which can be stored and retrieved for future use. The video describes the process of creating a deployment artifact (a compressed archive of the application) and uploading it to GitHub for distribution to servers. This demonstrates how artifacts play a crucial role in CI/CD pipelines by enabling the sharing of output between different stages of the deployment process.

๐Ÿ’กZero Downtime Deployment

Zero Downtime Deployment refers to updating applications and services without affecting the availability and access for users. The video's primary focus is demonstrating how to deploy a Laravel application to multiple servers using GitHub Actions without causing any downtime, illustrating strategies like artifact creation and server configuration to ensure the application remains accessible during the deployment process.

๐Ÿ’กSSH (Secure Shell)

SSH, or Secure Shell, is a cryptographic network protocol used for secure access to remote servers. In the deployment process described in the video, SSH is used to securely connect to servers, execute commands, and transfer files. This showcases SSH's importance in deploying applications, as it ensures secure communication and operations between the local machine and remote servers.

๐Ÿ’กEnvironment Variables

Environment variables are dynamic values which affect the behavior of running processes on a computer. They are used to manage application configurations separate from application code. The video explains how environment variables, like the commit hash or database passwords, are used within GitHub Actions workflows and SSH commands to dynamically configure the application deployment process. This highlights their utility in customizing and securing the deployment environment.

Highlights

The video demonstrates how to deploy a Laravel application to multiple servers without downtime using GitHub Actions.

It covers setting up a GitHub Actions workflow file, creating deployment artifacts, configuring servers, uploading artifacts to servers, and activating the new release.

The workflow includes steps for installing dependencies, compiling assets, setting up PHP, installing Composer packages, and creating a deployment archive.

It demonstrates how to export server configuration details (IP addresses, credentials, paths, hooks) to the workflow.

The video shows how to upload the deployment archive to servers using an action and extract the contents into a new release directory.

It covers setting up a shared storage directory for Laravel, linking it to the new release, and creating necessary directories.

The workflow includes running before and after hooks, allowing custom commands to be executed on servers before and after the new release is activated.

It demonstrates how to create and link the Laravel environment file with sensitive configuration values from GitHub Secrets.

The video shows how to symlink the new release directory to the 'current' directory, effectively activating the new release.

It includes steps to clean up old release and artifact directories on servers, keeping only the most recent releases.

The video showcases deploying the Laravel application to multiple servers simultaneously using GitHub Actions' parallel execution.

It highlights the importance of using repository secrets and SSH keys for production environments instead of hardcoding sensitive information.

The video emphasizes the benefits of having a single source of truth for environment configuration files instead of scattered files across releases.

It encourages users to follow along with any project, not just Laravel applications, and adjust the steps accordingly.

The video encourages viewers to support the channel by liking and subscribing, and provides an opportunity for viewers to ask questions in the comments section.

Transcripts

play00:00

hey youtube in this video we're going to

play00:01

take a look at deploying a layer of

play00:03

application towards multiple servers

play00:05

without any downtime using github

play00:07

actions before we dive in

play00:09

my name is filo and you're actually

play00:10

watching my very first youtube video

play00:12

about which i'm both excited

play00:13

and also a little bit nervous i'm a

play00:15

self-taught developer and my journey

play00:17

started 20 years ago with frontpage

play00:20

anyone who remembers that kinda makes me

play00:23

feel old

play00:24

anyways i've decided to dedicate 2021

play00:26

towards sharing what i've learned over

play00:27

the years

play00:28

learning how to program getting started

play00:29

as a freelancer but also co-founding a

play00:32

startup

play00:32

and the roller coaster that awaits you

play00:34

when you get your first investment

play00:36

but let's leave that for future videos

play00:38

and get started with deploying our

play00:40

application

play00:40

towards multiple servers without any

play00:42

downtime using data

play00:46

[Music]

play00:56

action

play00:59

let's start with a quick introduction to

play01:00

github actions

play01:02

github actions allow you to trigger a

play01:04

workflow when specific github events

play01:06

occur

play01:07

for example you can run a test suite

play01:09

when a pull request is made

play01:10

or in our case create a build of our

play01:12

product and upload it to multiple

play01:14

servers

play01:15

when the commit is pushed to our master

play01:16

branch

play01:19

our first step is to create a new

play01:20

repository on github

play01:23

so i'm going to create a new repository

play01:25

called hello world

play01:26

i'm going to make it private and i'm

play01:29

going to create it

play01:33

okay so in this example i'm going to use

play01:35

a plain

play01:36

laravel installation but you can use any

play01:39

project that you want

play01:40

whether it's a wordpress website a

play01:42

static website

play01:43

it doesn't really matter you can just

play01:45

follow along and

play01:46

adjust accordingly

play01:50

so i'm going to switch over to my

play01:52

terminal

play01:53

and i'm going to use the laravel

play01:54

installer to install

play01:56

a plain version of the framework

play02:01

next i'm going to add our data

play02:02

repository to our

play02:04

local environment so we can easily push

play02:07

to get

play02:08

up when we make changes

play02:11

now let's add the code that we have so

play02:14

far

play02:17

and let's push it up to get up

play02:22

okay so we have our repository set up

play02:25

now we can move over to

play02:26

creating our workflow let's open up our

play02:30

editor

play02:30

and let's create our first workflow file

play02:34

github actions uses a yaml syntax to

play02:36

define the events jobs and steps

play02:38

these yaml files are stored in our

play02:40

repository in a directory called

play02:42

github slash workflows so let's create

play02:46

that now

play02:47

create a new file type dot github

play02:50

slash workflows you can name your

play02:53

workflow file

play02:54

anything you want in this case i'm going

play02:57

to name it

play02:58

deploy application.yml like i mentioned

play03:01

github uses a yaml syntax so we're going

play03:04

to

play03:04

first define a name i'm going to call

play03:07

our workflow

play03:08

deploy application next we want to

play03:11

define

play03:11

the trigger that's going to trigger this

play03:14

workflow

play03:15

so i'm going to say on push

play03:19

and i only want this event to trigger

play03:20

when a push has been made

play03:22

on the master branch

play03:26

next we're going to start with our first

play03:28

job we basically want to prepare our

play03:30

application

play03:31

so that it's ready to be run on the

play03:34

production environment

play03:36

in this case we're using laravel so we

play03:38

want to make sure that we compile our

play03:39

css

play03:40

our javascript and install our php

play03:44

composer dependencies let's start off by

play03:48

giving an

play03:48

identifier to a job let's call it create

play03:51

deployment

play03:52

artifacts

play03:56

next we're going to provide it with a

play03:57

name that's going to be displayed in the

play03:59

github interface let's call it

play04:02

create deployment artifacts next we're

play04:05

going to define our runner

play04:06

our runner is basically a server that

play04:08

has the github actions

play04:09

runner application installed in this

play04:12

case we're going to make use of a

play04:14

runner that is hosted by github and

play04:16

we're going to choose ubuntu

play04:17

latest now we can continue by defining

play04:21

the steps that we want to execute

play04:23

on our runner in this case on the ubuntu

play04:26

latest environment so we're going to

play04:28

start off by

play04:30

importing our repository code by default

play04:33

it's a

play04:34

empty os so it's just ubuntu with

play04:37

no source code whatsoever so in our

play04:41

first step

play04:41

we're going to make use of an existing

play04:43

action

play04:44

in this case the checkout action which

play04:47

is provided by github which allows you

play04:49

to check out your source code

play04:50

into your runner with just a single line

play04:53

of code

play04:54

so now that we have our source code we

play04:56

can continue by

play04:57

pulling in our npm dependencies

play05:01

compile our css and javascript

play05:04

so start off by giving it a name

play05:08

and next we're going to use the run

play05:10

parameter

play05:11

to define a command that we want to run

play05:14

inside our

play05:15

runner which is ubuntu latest

play05:18

so be using the pipe character you can

play05:21

enter

play05:22

multiple lines so in this case we want

play05:24

to do npm install

play05:26

and npm run production this will install

play05:30

our npm dependencies and compile our css

play05:34

and javascript

play05:37

let's push the changes that we have so

play05:38

far up to get up and let's see

play05:41

what happens

play05:45

when you switch to get up you'll notice

play05:47

this orange indicator

play05:49

this indicator tells you that a workflow

play05:51

is currently running

play05:53

so when you click actions you will get

play05:55

an overview of

play05:56

all your previous workflows that have

play05:58

been executed and the ones that are

play06:00

currently

play06:01

running and as you can see our workflow

play06:04

is currently in progress

play06:06

click it you will get some more

play06:08

information about the different jobs

play06:10

which

play06:10

exist inside this workflow in this case

play06:13

our

play06:14

create deployment artifacts with the

play06:16

power of video editing

play06:17

i'll make sure that i cut out any

play06:19

waiting time so you

play06:20

don't have to wait for every workflow to

play06:22

be completed

play06:24

our first workflow has just completed

play06:27

let's take a look and see what has

play06:30

happened

play06:31

here you get an overview of all the

play06:33

different steps inside

play06:34

the create deployment artifacts job you

play06:37

can see that it has

play06:38

a setup job which is defined by github

play06:41

and you can see that it's downloading

play06:43

the required actions that we define in

play06:44

our workflow

play06:45

in this case it's calling the checkout

play06:48

action

play06:49

you can see that it checked out our

play06:51

hello world repository

play06:54

next we got our compile css and

play06:55

javascript step

play06:57

and you can see that it downloaded our

play06:59

npm dependencies

play07:02

and it successfully compiled our

play07:05

javascript and css

play07:07

okay next up want to make sure that our

play07:09

runner is configured with the correct

play07:11

version of php in this case we're going

play07:14

to configure it with

play07:15

php version 8 and we're going to make

play07:17

sure that

play07:18

certain hp extensions are enabled which

play07:21

are

play07:21

required by level in this case we're

play07:24

going to make use of

play07:25

a community build action this action is

play07:28

going to help us to configure

play07:30

php inside our runner with just a few

play07:33

lines of code

play07:34

so let's reference the action that we

play07:35

want to use and let's provide it with

play07:37

your required input parameters

play07:40

let's define our version of php which is

play07:43

8.0

play07:45

and now let's define the extensions

play07:48

which we want to include

play07:51

in this case level requires mb string

play07:55

c type file info

play07:59

openssl

play08:02

video emath

play08:07

json tokenizer

play08:11

and xml

play08:14

let's commit these changes and push them

play08:16

up to get up and

play08:17

see if it works switch back to our

play08:21

actions

play08:22

and as you can see a new workflow has

play08:25

been queued

play08:27

let's forward to the output of our php

play08:30

configuration

play08:32

you can see that it found version php8

play08:36

it set up composer which we need to

play08:38

install our dependencies

play08:40

and then enable the extensions which we

play08:42

defined in our yaml file

play08:45

so now that we have php configured and

play08:48

composer installed we can install our

play08:50

composer dependencies

play08:52

so let's create a new step and let's

play08:53

call it install composer dependencies

play08:56

next we want to run a command inside our

play08:59

runner

play09:00

we can do composer install no dev

play09:03

because we don't want any depth

play09:04

dependencies on production

play09:07

we add the no interaction flag because

play09:09

it's an automated process

play09:11

and we want to state that we prefer the

play09:13

distribution source

play09:17

okay so let's quickly commit these

play09:18

changes and take a look

play09:22

again going to speed up this a little

play09:24

bit in post production

play09:27

and there you can see our php composer

play09:30

dependencies have been

play09:31

installed successfully okay great

play09:34

our build is complete so now we can

play09:37

prepare it to be shipped to our

play09:39

remote server in this case i want to

play09:41

create an archive

play09:42

of the entire application so we just

play09:44

have one file to work with

play09:48

okay let's name our next step let's call

play09:50

it create deployment artifact

play09:53

followed by the command that we want to

play09:54

run inside a runner

play09:56

in this case we're going to create a

play09:58

archive

play09:59

we're going to use the tar command with

play10:01

the c flag

play10:03

to tell it to create a new archive we're

play10:05

going to use the z flag to tell that we

play10:07

want to use

play10:07

g zero compression and we're going to

play10:10

use the f

play10:10

flag to define that we want to have the

play10:13

output

play10:14

in a file

play10:18

let's name the file app.gz

play10:24

now what will happen it will create an

play10:26

archive from all the files

play10:28

in our current directory and as you

play10:31

remember we've

play10:32

installed npm dependencies that we

play10:34

actually only needed

play10:36

to create this build so we want to make

play10:38

sure that these files are not included

play10:40

in our archive

play10:42

we can achieve this by using a exclude

play10:45

flag

play10:46

and we can define a pattern that we want

play10:49

to use

play10:50

to exclude for example the git directory

play10:52

or in this case

play10:54

the node modules directory let's push

play10:57

these changes up to github and verify

play11:00

that the results are as

play11:02

we expect

play11:09

the job has been completed you can see

play11:11

that the command has

play11:12

successfully executed since we're

play11:15

pushing this file up to our remote

play11:17

server

play11:18

the file name app.gz is a little bit

play11:21

unclear

play11:21

we're not sure which release is actually

play11:24

inside

play11:25

so i want to make sure that we can

play11:27

identify each release

play11:28

by naming the file of our archive and

play11:31

make sure that it's equal to the commit

play11:32

hash

play11:34

we can do this by using a get up action

play11:37

syntax

play11:38

which is available in these specific

play11:41

yemo files

play11:43

so start off by renaming our app

play11:46

and use a an environment variable that

play11:49

will be equal to our commit hash

play11:52

now this environment variable doesn't

play11:54

exist yet so we need to make sure that

play11:57

the runner knows what the github

play12:00

commit hash is

play12:03

we can achieve this by using the

play12:05

environment flag

play12:08

so we're going to tell it that the

play12:10

environment variable github

play12:12

sha is equal to the commit hash

play12:16

if you want to know more about the

play12:17

available properties that you can

play12:19

reference

play12:20

be sure to check out the documentation

play12:22

on github.com

play12:26

so let's reference the commit hash and

play12:29

that's it we can now continue with our

play12:31

next step which is

play12:33

uploading our deployment artifact okay

play12:36

let's define our next step

play12:38

and we'll start off again by providing

play12:39

it with a name let's call it

play12:41

store artifact for distribution

play12:46

next we're going to use a getup action

play12:49

again

play12:49

just like the checkout action github

play12:51

also has a

play12:52

specific action which allows you to

play12:54

upload

play12:56

build artifacts

play12:59

we're going to use the uses key to

play13:01

reference actions

play13:03

slash upload this action requires a

play13:07

couple of parameters

play13:09

so we're going to use with to define

play13:11

these parameters

play13:12

we're going to start off by a name this

play13:15

is going to be the name of our artifact

play13:17

that we can use for later reference

play13:21

for example in a future step we want to

play13:22

download these artifacts

play13:24

and we need to reference the name that

play13:26

we define right here

play13:28

so let's call it app dash build

play13:32

next we need to tell the upload artifact

play13:35

action

play13:36

to tell where we can find our file that

play13:38

we want to upload

play13:40

so we're going to reference the archive

play13:42

file we've created earlier

play13:43

the commit hash as our file name plus

play13:46

star.gz

play13:48

let's commit our changes to git up and

play13:50

verify that everything works

play13:53

okay so our workflow is running let me

play13:55

quickly fast forward to the end of the

play13:57

job

play13:58

okay there we go as you can see we now

play14:01

have one artifact

play14:03

with the name app built and it's a

play14:05

little over 3.6

play14:07

megabyte okay so now we can work on

play14:10

uploading our artifact to our servers

play14:12

but at the moment

play14:13

we don't have any information about our

play14:16

service just yet

play14:18

so in this case i want to create a new

play14:20

json file

play14:21

which will contain a list of our servers

play14:24

with the required information

play14:25

like ip address authentication like

play14:28

username and password

play14:30

and a bunch of other configurations so

play14:32

let's start off by creating a

play14:34

new file in the root of our repository

play14:37

called deploymentconfig.json

play14:42

start by giving our server a name and

play14:45

it's just for easy reference so when we

play14:46

take a look at the github ui we can

play14:48

easily spot it

play14:50

followed by the ip address of our server

play14:54

next we got our username let's

play14:58

enter root let's add a password as well

play15:04

i'm going to set it to git up actions

play15:06

for now

play15:08

next we got our port which is 22 for ssh

play15:13

i want to be able to set a hook before

play15:16

and after the deployment on each server

play15:19

so we're going to add a

play15:21

before hook option where we can enter

play15:24

any command that we want to run before

play15:26

our release is activated

play15:28

for example we can run a database

play15:29

migration or

play15:31

run a database backup you name it

play15:34

when a release is complete we might want

play15:36

to send out a

play15:37

select notification so let's create an

play15:40

after hook configuration option as well

play15:43

next we want to set up a server path

play15:46

which

play15:47

is where our website will be located so

play15:50

in this case

play15:50

i'm using engine x i'm going to point

play15:53

the directory

play15:54

to far slash www

play15:57

html i don't have a server set up just

play16:00

yet

play16:01

so let's head over to digitalocean to

play16:04

quickly configure a server

play16:06

if you already have a server up running

play16:07

that's totally fine you can just skip

play16:09

ahead to the next part

play16:12

so let's start by creating a new server

play16:14

i'm going to use a

play16:15

marketplace image which has linux mysql

play16:19

and php pre-installed

play16:24

select the type of server we want to use

play16:26

i'm going to choose amsterdam for my

play16:28

region

play16:31

and i'm going to use password

play16:33

authentication

play16:34

for this example but i highly recommend

play16:36

that you use ssh keys in production

play16:40

okay so the password that i've entered

play16:42

earlier in the server configuration does

play16:43

not meet

play16:44

the password requirements from the

play16:46

digital ocean

play16:47

so let's make this one a bit more

play16:48

complicated

play16:51

let's make sure that we also update our

play16:53

password in our configuration file

play17:00

okay so let's leave the host name as it

play17:02

is

play17:03

and that's it let's create our server

play17:09

okay let's copy the ip address and let's

play17:12

see if we can ssh into our server

play17:15

there we go that seems to work

play17:21

now let's quickly verify that our server

play17:23

can be reached

play17:24

and that our web server is up and

play17:25

running there we go that seems to be

play17:28

working as well by the end of this video

play17:32

we will have achieved the

play17:33

following directory structure now i want

play17:36

to point out the

play17:37

current and releases directories

play17:40

the releases directory contain the

play17:42

releases that we upload

play17:45

these are our unarchived artifacts

play17:49

when the archiving is done we swap out

play17:52

the

play17:52

current directory and point it to the

play17:55

new release

play17:56

so the current directory doesn't really

play17:57

exist it's more like a

play17:59

shortcut into our release directory

play18:02

so we need to make sure that our engine

play18:04

x configuration is pointed to this

play18:06

current directory

play18:08

so let's ssh into our server and make a

play18:11

change to the

play18:12

engine x server configuration let's

play18:15

change the

play18:16

root directory of our web server and

play18:18

open

play18:19

the current directory now in our case

play18:21

we're deploying a laravel application

play18:23

which comes with a specific public

play18:25

directory and we need to point our web

play18:28

server

play18:28

to that directory so let's append public

play18:31

as well

play18:32

let's save our changes and restart nginx

play18:37

and if you reload the browser then you

play18:39

can see that the changes have been made

play18:40

to the nginx configuration

play18:42

but that it currently cannot find that

play18:44

directory

play18:46

let's update our configuration file with

play18:48

the ip address of our server

play18:51

in this example we just have one server

play18:53

that we're going to work with but you

play18:54

can add as many as you like although

play18:57

github does has a limit when it comes to

play18:59

the deployment matrix in which we're

play19:00

going to talk next

play19:02

and this has a specific limit of 265.

play19:05

so if you exceed that limit then you'll

play19:07

probably have to look at a different

play19:09

solution

play19:10

okay so before we can continue we need

play19:12

to export our configuration file that

play19:14

contains our servers

play19:16

and make it available inside our

play19:18

workflow

play19:19

in order to do this we need to add an

play19:21

additional step

play19:23

let's create a new step and let's name

play19:24

it export

play19:26

deployment matrix

play19:29

and basically what we're going to do is

play19:31

use the runner

play19:32

to load the contents of the deployment

play19:35

configuration file echo it out

play19:38

to the command line interface and use a

play19:41

special syntax

play19:42

so github understands that we want to

play19:43

make this information available inside

play19:45

our workflow

play19:47

since you want to reference the output

play19:50

of this specific job later

play19:52

on we want to provide it with an id so

play19:54

let's name it

play19:55

export deployment matrix

play19:58

next we'll define our command

play20:03

let's create a json variable and assign

play20:06

it to the contents of our deployment

play20:08

config.json file

play20:14

so this doesn't work really well with

play20:15

multi-line json files

play20:17

so i found a piece of code which

play20:20

basically

play20:21

escapes the multi-line json file that we

play20:23

have

play20:24

and make sure that it works so now we're

play20:26

going to echo out our json

play20:28

but we're going to prepend it with a

play20:30

specific name

play20:32

which allows github to read it

play20:35

so we can do set output

play20:38

we're gonna provide it with a name we're

play20:40

gonna call it

play20:42

deployment matrix next we're gonna

play20:44

provide it with the value

play20:46

in this case our json string okay now we

play20:49

need to tell github that we want to

play20:51

store this information so we can use it

play20:53

for later reference

play20:54

so scroll back to the top

play20:58

and add a new input parameter called

play21:00

outputs to the create deployment

play21:02

artifact step

play21:04

provided with a key that we can use for

play21:06

later reference in this case we're going

play21:08

to call it

play21:08

deployment matrix

play21:11

next we'll use github specific context

play21:15

information that we've used earlier to

play21:18

get the git comment hash and now we're

play21:20

going to reference

play21:21

steps followed by the id of our step in

play21:24

this case

play21:26

export deployment matrix

play21:31

output followed by the name that we've

play21:34

provided in the echo statement

play21:39

which is deployment matrix

play21:47

okay we're all good to go to move on to

play21:50

our next job

play21:51

in this case preparing the release on

play21:53

our server

play21:56

so let's name it prepare release on

play21:59

server

play22:03

now we're gonna define that this runs on

play22:05

the latest version of ubuntu as well

play22:08

next we're gonna use the needs parameter

play22:09

to make sure that our previous step has

play22:11

been completed

play22:12

otherwise they will run asynchronous

play22:17

and now we're going to work on our

play22:19

matrix

play22:20

so we use the strategy input parameter

play22:25

use the matrix keyword to build a matrix

play22:27

configuration

play22:30

you can basically see this as a for each

play22:31

loop

play22:34

the steps that we define in this job are

play22:36

going to be repeated

play22:37

on the objects with inside the matrix

play22:40

in this case this is going to be our

play22:41

server configuration

play22:43

so we're going to load the json which we

play22:46

exported in our previous step

play22:48

into the repair release on server step

play22:50

okay so the matrix is going to loop

play22:52

through our json file and we want to

play22:55

provide a name that we can use to

play22:56

reference the information in our json

play22:58

file

play22:59

in this case we got a list of servers so

play23:01

let's use the keyword

play23:03

server the matrix

play23:06

expects a array to be provided

play23:10

at the moment we have a json string

play23:14

so we're going to use the function

play23:15

called from.json provided with the

play23:18

output of our previous step

play23:21

we can do this by referencing of the

play23:23

chain so we're going to say needs

play23:25

dot create deployment artifacts dot

play23:27

outputs

play23:29

dot deployment matrix which matches up

play23:32

with the

play23:33

output variable that we defined earlier

play23:38

now that we have our matrix setup we can

play23:41

continue

play23:41

with setting up the steps for this

play23:44

specific

play23:45

job so we want to start out by

play23:49

downloading the artifact from our

play23:50

previous step

play23:52

so again we're going to use a github

play23:54

specific action

play23:55

which is called action slash download

play23:58

artifact so this action

play24:01

only requires one input parameter which

play24:04

is the name of our artifact

play24:06

so let's enter app dash build

play24:10

let's commit the changes to get up and

play24:12

take a look

play24:18

okay so our export deployment matrix

play24:20

step has failed

play24:21

let's take a look at our workflow file

play24:22

to see what's wrong

play24:27

ah it looks that i forgot a quote

play24:30

let's try that again

play24:36

and there you go this time it has

play24:38

completed successfully

play24:40

and on the left hand side you can

play24:42

actually see that it has successfully

play24:44

read our matrix as you can see that it's

play24:46

saying prepare release on servers and

play24:48

you can actually see that it's

play24:49

referencing

play24:50

server one with the ip address

play24:53

again this includes the

play24:57

credentials as well so in production

play25:00

make sure that you use

play25:01

repository secrets and ssh keys

play25:06

okay so we got our artifact downloaded

play25:08

next we can upload it to our servers

play25:11

again we're going to make use of a

play25:12

community build action

play25:15

which allows us to upload our zip file

play25:18

to our servers

play25:20

first let's create our next step let's

play25:21

name it upload

play25:23

followed by the users parameter to

play25:26

provide the action that we want to use

play25:27

in this case apple boy

play25:29

scp action by the way if you want you

play25:32

can copy and paste the name of your

play25:34

action

play25:35

and just head over to github.com the

play25:37

name of your action

play25:38

and you actually see the source code of

play25:40

the action which is being run behind the

play25:42

scenes

play25:43

so here you can see these actions allow

play25:45

for copying files and artifacts via ssh

play25:49

and on this page you can see the usage

play25:51

input

play25:52

variables and code examples on how to

play25:54

specifically use this

play25:56

action okay let's head back to phpstorm

play25:59

and provide the necessary input

play26:01

parameters

play26:02

i'm going to start off with the host

play26:04

which is going to be equal to the server

play26:05

ip

play26:07

we've got the server ip in our

play26:09

deployment config so we only need to

play26:10

reference it here

play26:12

we can use the server object inside our

play26:14

matrix to be defined above

play26:16

so in this case matrix.server.ip

play26:20

which will reference the ip address

play26:23

inside our deployment config

play26:28

let's repeat this process for the

play26:30

username

play26:36

password

play26:40

or next we're going to define the source

play26:43

which is going to be the file that we

play26:45

want to upload

play26:48

so this is going to be equal to the

play26:49

commit hash so again we reference github

play26:52

dot sha we append

play26:55

the file extension which is dot tar.gz

play27:01

next we're gonna define the target this

play27:03

is going to be equal to the directory

play27:05

where we want to upload the file on a

play27:07

remote server

play27:09

so in this case matrix.server.path

play27:12

to reference the server path that we

play27:14

define in our deployment configuration

play27:17

now let's make sure that our artifacts

play27:18

are grouped nicely together inside a

play27:20

single directory

play27:21

so let's append the server path with a

play27:24

new directory name

play27:25

called artifacts this will be equal to

play27:28

far slash www.html

play27:33

artifacts let's commit our changes and

play27:35

push them together

play27:36

let's verify that our action is working

play27:39

and that our artifact is uploaded to our

play27:40

server

play27:41

let's fast forward to the end of this

play27:43

workflow

play27:45

there we go it successfully executed the

play27:47

transfer

play27:48

to our server let's ssh into our server

play27:52

and verify that the file's there so i'm

play27:55

going to check

play27:56

inside our var slash www

play27:59

html directory to see if our file's

play28:01

there

play28:03

it looks like something went wrong

play28:05

because we only got our index.html

play28:07

so let's take a look and it seems that

play28:10

i've got a w

play28:11

inside the server configuration where we

play28:14

define our server path

play28:16

let's commit the changes and try this

play28:18

again

play28:23

the workflow has successfully completed

play28:25

the upload has been completed

play28:28

and it looks like that it created the

play28:29

folder in the correct place

play28:32

so let's check our server and there we

play28:34

go our artifacts directory is there

play28:37

and it does contain our archive with our

play28:40

current release

play28:42

okay so we got our file on our server

play28:44

now we need to extract it

play28:46

so that we have a release to actually

play28:48

work with

play28:50

so let's create a new step let's name it

play28:53

extract archive and create directories

play28:56

so in order to extract our archive we

play28:58

need to ssh into our remote server

play29:01

we're going to use a another action by

play29:03

the same author

play29:04

called appleboy slash ssh action

play29:08

which will allow us to execute remote

play29:10

commands

play29:11

on our server i'm going to copy and

play29:13

paste the hostname username password

play29:15

import

play29:16

since those are exactly the same as in

play29:19

our previous step

play29:23

next we'll use the script input

play29:25

parameter to define the commands that we

play29:27

want to run on a remote server

play29:30

let's kick off by creating a new

play29:31

directory that will hold

play29:33

our current release let's use the make

play29:36

their command

play29:37

to create the directory if it doesn't

play29:39

exist yet let's reference our

play29:41

server path followed by the releases

play29:44

directory

play29:45

followed by the commit hash now this

play29:49

github underscore sha environment

play29:51

variable doesn't exist yet

play29:53

so let's make sure that we pass it

play29:55

inside our

play29:56

input parameters for this specific

play29:58

action so let's set the n

play30:00

flag and let's define github underscore

play30:03

sha

play30:05

to be equal to the commit hash of this

play30:07

release

play30:09

environment variable will now be

play30:11

available inside our runner

play30:13

we want to make sure that it's also

play30:14

available for us inside

play30:16

our remote server

play30:19

we can do this by providing a

play30:21

environment input variable

play30:23

for our action so now this environment

play30:26

firewall should be available on a remote

play30:27

server

play30:29

let's extract the contents of our

play30:31

archive into the release directory we

play30:33

just created

play30:35

we can use the tar command to extract

play30:38

our archive

play30:40

so let's do tar x z f

play30:43

followed by the path to our archive file

play30:46

which is equal to

play30:47

our server path followed by the

play30:49

artifacts directory

play30:50

followed by the mid hedge of our current

play30:53

release

play30:54

and of course the file extension which

play30:56

is dottar.gc

play30:58

next we'll add the c flag

play31:02

to make sure that the tar command

play31:03

understands that we want to extract

play31:04

contents

play31:05

into the releases directory which again

play31:09

is our server path followed by slash

play31:10

releases

play31:12

slash our release commit hash

play31:16

time to commit our changes again and

play31:18

push them up to get up to verify that

play31:20

everything works

play31:25

let's fast forward again to the output

play31:28

of our workflow

play31:30

okay it seems that our job has filled so

play31:32

let's take a look what's going on

play31:34

cannot find our archive and it seems

play31:36

that the name is incorrect because those

play31:38

brackets shouldn't be in there so let's

play31:40

take a look at our workflow

play31:42

and there you go i made a mistake right

play31:44

there the dollar sign

play31:46

should be before the bracket so let's

play31:47

change it

play31:49

let's push the changes to get up and

play31:51

let's try again

play31:54

this time the job has successfully

play31:56

completed so let's ssh into a remote

play31:58

server

play31:58

check the release directory and make

play32:00

sure that our files are there

play32:02

and there we go our laravel application

play32:04

has been extracted

play32:05

into the release directory let's head

play32:08

back to phpstorm and continue with our

play32:10

workflow

play32:12

we're going to make some specific

play32:13

changes for our larva application

play32:15

if you don't use level you can still

play32:17

follow along we're going to work on

play32:18

something which allows us to share

play32:20

storage between different releases if

play32:23

you're unfamiliar with laravel

play32:25

basically it ships with a storage

play32:26

directory inside our repository this

play32:29

directory is somewhat empty

play32:30

but on our production release we might

play32:32

actually have files in there

play32:34

and of course we don't want to overwrite

play32:36

our files on our server

play32:38

so let's make sure that the storage

play32:39

directory is removed from

play32:41

our release so we can link it up to our

play32:43

shared storage directory so we use

play32:46

the rm command to remove this directory

play32:49

which is located in our server path

play32:51

followed by

play32:52

our releases directory our release

play32:56

commit hash followed by the name of the

play33:00

directory which is storage next we'll

play33:03

replicate the storage directory

play33:04

structure

play33:05

but outside of our release and again

play33:07

using the make their command to make a

play33:10

storage directory inside the storage

play33:12

directory we're going to

play33:13

create a couple of new folders which are

play33:15

required for the laravel framework in

play33:17

order to

play33:17

function in this case app

play33:21

public framework

play33:24

and logs our framework directory

play33:27

requires a couple of

play33:28

extra directories let's make sure these

play33:31

directories exist as well

play33:32

in this case cache sessions testing

play33:36

and views finally we need to make sure

play33:38

that the storage directory

play33:40

and all sub-directories are writable

play33:43

so let's make sure that we provide the

play33:45

path to our storage directory

play33:46

and continue with our next show so in

play33:49

our next step we are going to run our

play33:51

before hooks

play33:52

which allows to execute any commands

play33:54

before our release is activated

play33:56

let's identify our next job by calling

play33:59

it run

play33:59

before hooks

play34:02

and of course let's give it a name as

play34:04

well if you want to make your steps

play34:06

easier to read you can actually

play34:07

reference your matrix object within the

play34:09

name

play34:10

as well so for example we could do

play34:12

matrix server.name to get the name of

play34:14

the server

play34:16

and add beforehook so in the github ui

play34:19

we'll get

play34:19

server one beforehand which makes it

play34:22

easier to identify on which server

play34:24

the actual job is running we're gonna

play34:27

repeat a couple of things of course

play34:28

again we're gonna make sure that it's

play34:29

running on the latest version of ubuntu

play34:32

we're gonna define our needs parameter

play34:35

to

play34:35

tell it that we want to have our create

play34:37

deployment artifacts and our prepare

play34:38

release on server

play34:40

jobs to be completed we're going to

play34:42

reference our

play34:43

matrix again and let's just copy and

play34:46

paste it from our previous step

play34:51

let's name our step run before hooks

play34:54

let's save ourselves some time by

play34:56

copying the step from our previous job

play34:59

to execute a command on a remote server

play35:07

next we'll add the script tag again

play35:10

followed by the before hook from

play35:12

our server configuration by referencing

play35:14

our matrix objects so let's do

play35:17

matrix.server.for hooks

play35:19

inside our server configuration we can

play35:21

now define our beforehooks

play35:24

these beforeholds will be executed

play35:25

before we activate release

play35:28

so you might like go into a certain

play35:30

directory and execute a clone

play35:31

it would be pretty nice if we don't have

play35:33

to do things like

play35:35

far slash www etc

play35:38

but we can reference a environment

play35:40

variable which makes it a bit easier for

play35:42

us for example

play35:43

we could do c d release path in order to

play35:46

get in our current release directory

play35:47

this won't work just yet

play35:49

we need to make sure that the

play35:50

environment variable actually exists so

play35:52

let's define our environment variable

play35:54

which we called release underscore path

play35:56

we'll reference the server path followed

play35:58

by the releases directory

play35:59

followed by the directory name which is

play36:02

equal to our release commit hash

play36:04

okay next we want to set an environment

play36:05

variable that we can use to reference

play36:07

the path to our active release

play36:09

so let's name this environment variable

play36:11

active underscore

play36:12

release underscore buff followed again

play36:15

by the server path

play36:17

followed by the current directory

play36:20

next we also have a storage path which

play36:22

is the path to our storage directory

play36:25

and the base path which is nothing else

play36:27

than our

play36:28

server path now let's make sure that

play36:30

these environment variables are actually

play36:32

available on a remote server by again

play36:34

going to the

play36:35

input variables for our ssh action

play36:38

and defining the ends input variable

play36:41

followed by

play36:41

the environment variables that we want

play36:43

to make available in this case our

play36:44

release hash

play36:45

our release path our active release path

play36:48

our storage path

play36:49

and our base path now we of course want

play36:51

to make sure that this actually works so

play36:53

let's head over to our deployment

play36:54

configuration

play36:55

and echo out the github commit hash

play36:58

time to push our change up to get up and

play37:00

take a look it seems something went

play37:02

wrong

play37:03

the workflow is not valid job run

play37:05

beforehand depends on unknown job

play37:06

prepare release on server

play37:08

so let's take a look and it seems i've

play37:12

got an

play37:12

s right there let's try again

play37:16

this time our workflow has successfully

play37:18

completed let's verify that our commands

play37:21

are successfully executed

play37:22

that looks good let's verify on our

play37:24

server and our storage directory is

play37:26

there and you can see by the green

play37:27

highlight that

play37:28

the write permission is set correctly

play37:32

next we got our before hook let's open

play37:34

it up and there you can see

play37:36

we echoed out the github commit hash and

play37:40

on line 30 you can see that it is equal

play37:42

to 884 etc so that is working as well

play37:46

our environment variable is available on

play37:48

a remote server now it's time to work on

play37:49

the most exciting step

play37:51

activating our release let's just copy

play37:54

paste to run before hook step since the

play37:56

active release app is

play37:58

going to be a couple of ssh commands as

play38:02

well

play38:04

let's rename it to activate release

play38:12

of course make sure that our run before

play38:14

hooks has actually completed before we

play38:16

run this job

play38:19

change name to activate release as well

play38:26

let's change the step name okay i think

play38:28

i spot a mistake that i made in the

play38:30

previous

play38:30

job and there should actually be a

play38:33

single dollar sign

play38:34

instead of two so let's make sure that

play38:36

we update this across the file

play38:43

i think we got them all let's replace it

play38:45

with a single dollar sign

play38:48

and two brackets

play38:53

okay so now we want to make sure that

play38:55

our current directory is pointing to

play38:57

our new release we can do this by sim

play39:00

linking

play39:02

we're gonna simulate the current

play39:03

directory

play39:05

to the directory that holds the current

play39:07

release

play39:09

we'll use the ln command to set up a

play39:11

symbolic link

play39:13

the s-flag means it's a symbolic link

play39:16

the n flag tells it that it's just

play39:19

treated

play39:19

as a normal file or directory and

play39:23

dash f tells it to force or overwrite a

play39:27

link if it already exists

play39:29

this is then followed by the path to our

play39:32

new release

play39:33

and we want to make sure that it's

play39:34

linked up to our slash current directory

play39:37

or as we referenced before as the

play39:40

environment variable

play39:41

active and the score release and square

play39:43

path in case you are using

play39:45

engine x with php fpm you need to make

play39:48

sure that php is actually reloaded

play39:50

otherwise it will not pick up the

play39:52

changes when we swap out a symbolic link

play39:56

so we'll do this by doing surface hpa

play39:59

fpm

play39:59

reload time to verify that everything

play40:01

works so let's push this up to get up

play40:03

and take a look

play40:04

at our job in this case it has

play40:07

successfully executed commands on our

play40:08

server it has set up the link

play40:10

and it has reloaded php8 let's verify

play40:13

this on our remote server

play40:16

and there we go as you can see our

play40:18

current directory is currently

play40:19

simulink to the release that we just

play40:21

deployed

play40:23

let's see the interrupt current

play40:24

directory to verify that our application

play40:26

is of course actually there and there

play40:29

you go

play40:30

if you would head over to our browser

play40:31

you can see that it isn't working just

play40:33

yet

play40:35

this is because we still need to set up

play40:36

a couple of things in order for this

play40:38

level application

play40:39

to run successfully if you're unfamiliar

play40:42

with laravel

play40:43

it ships with a environment

play40:45

configuration file

play40:47

this file basically contains things like

play40:48

the application name the url

play40:50

database settings etc etc this file

play40:54

needs to exist and needs to have a

play40:55

couple of configuration options defined

play40:57

in order for our framework to work

play41:00

let's kick off by creating a environment

play41:02

variable that's called laravel and score

play41:04

n

play41:05

and let's make sure that equals to the

play41:08

level and secret

play41:10

secret again is a keyword that is

play41:12

context specific to this creative action

play41:14

and we can define our secrets within the

play41:17

github ui

play41:18

so head over to your repository go to

play41:20

settings secrets

play41:22

new secret let's enter the same name

play41:25

that we defined in our workflow file

play41:27

which is laravel and screen

play41:29

and i'm just going to copy and paste in

play41:31

a example environment file that ships

play41:33

with laravel and i just

play41:34

changed the app name and the environment

play41:36

to production now during each deployment

play41:38

we want to make sure that our

play41:40

environment file is updated

play41:43

it doesn't exist right now so let's make

play41:44

sure that it does

play41:46

we will use the printf command to echo

play41:49

the contents of our secret

play41:53

into our environment file which is going

play41:55

to be located

play41:57

in our base path

play42:01

of slash.nfc this file needs to be

play42:03

inside our release

play42:04

so we're going to use the link command

play42:06

again but this time we're going to link

play42:08

the environment file

play42:10

from our base path to our release path

play42:15

i could argue why not create this

play42:16

environment file inside the release

play42:18

directory well that will result in a lot

play42:21

of environment files

play42:22

scattered across all our different

play42:24

releases i prefer to have a single file

play42:27

which is a single source of truth

play42:30

this makes it easier to work with since

play42:32

we're here let's link up the storage

play42:34

directory as well

play42:35

we'll use the ln command and reference

play42:37

the storage path

play42:38

followed by the release path which

play42:39

basically means that we now have a

play42:41

storage directory available in a release

play42:44

which is simulink to the storage

play42:46

directory inside our base path

play42:49

let's trigger the workflow and verify

play42:51

the results on our server

play42:58

okay everything has successfully

play42:59

completed

play43:02

let's take a look at our website and

play43:04

unfortunately

play43:05

it seems that it's still not working

play43:08

let's go back to our server and take a

play43:10

look

play43:14

our files are there the end files is

play43:16

there it's correctly linked

play43:19

current directory is there

play43:23

but the environment file is empty

play43:27

let's see our level and is defined

play43:31

i've got to pass the environment

play43:33

variable to our remote server

play43:37

so let's give this another try

play43:46

okay our workflow has successfully

play43:48

completed

play43:49

but it's still not working

play43:53

let's verify that there are environment

play43:54

files there

play43:56

okay that seems to work

play44:00

but it's not yet working okay i quickly

play44:03

paused the video for a second

play44:06

i forgot to update my engine x

play44:08

configuration

play44:09

this server is proficient with php 7.4

play44:12

which i upgraded to

play44:13

version 8 but i've got to update the

play44:16

engine x configuration

play44:18

that was still referencing to php 7.4

play44:22

so let's change it reload nginx and try

play44:25

again

play44:26

and yet it's still not working

play44:29

let's dive back into the server and

play44:30

check the error log

play44:34

so larval is complaining about the fact

play44:36

that we provide a

play44:37

envelope cache path so

play44:40

it seems that i forgot to create a

play44:42

additional directory inside our storage

play44:44

framework

play44:45

cache directory which is a data

play44:48

directory

play44:49

so let's quickly create this right here

play44:56

make sure that it has correct file

play44:57

permissions

play45:00

and refresh and there you go we have

play45:02

successfully deployed

play45:04

our laravel application so we've

play45:06

manually

play45:07

fixed it on our server but of course you

play45:08

want to make sure that it is fixed in

play45:10

our workflow as well

play45:11

so let's head over back to phpstorm

play45:15

scroll up and let's make sure that the

play45:17

data directory

play45:18

is created inside the cache directory

play45:21

let's copy and paste our previous

play45:23

command and let's adjust it accordingly

play45:26

and next up we got our after hook

play45:30

so to make things a bit easier let's

play45:32

just copy and paste our before hook

play45:34

since it's

play45:34

almost the same

play45:38

let's make sure that our activates

play45:39

release job has finished before we

play45:41

triggered the after hook

play45:47

by adding it to our nice array

play45:50

next we'll update the identifier to run

play45:54

after hook

play45:56

we update the name as well and the name

play45:58

of the step

play46:04

and finally let's make sure that we

play46:06

reference the after hooks from our

play46:08

server configuration

play46:11

okay great our after hook is done as

play46:12

well let's continue with a little bit of

play46:15

a cleanup

play46:17

every time this workflow is triggered it

play46:18

will upload our artifacts

play46:21

now if you do this 100 times this will

play46:23

mean you have 100 artifacts

play46:25

and these artifacts take up disk space

play46:28

and you probably don't want to end up

play46:30

with your server crashing in the middle

play46:32

tonight because

play46:33

it has run out of disk space so let's

play46:36

make sure that we

play46:36

clean up the releases and artifacts

play46:38

directory

play46:41

let's copy and paste our run after hook

play46:43

shop and let's make some changes

play46:50

let's change the identifier to cleanup

play46:52

update the

play46:53

name accordingly and the step name as

play46:56

well

play46:58

of course make sure that our after hook

play47:00

has completed before we are running the

play47:02

clean up

play47:10

we don't need the environment variables

play47:12

that we created earlier so let's remove

play47:14

them

play47:15

and replace them with two new

play47:17

environment variables

play47:18

we want one environment variable to

play47:21

reference our

play47:22

releases directory and another

play47:25

environment variable that

play47:26

references our artifacts directory

play47:30

now we need to make sure that these two

play47:32

environment variables are passed to a

play47:34

remote server so

play47:35

update the ends input variable of our

play47:38

ssh action

play47:39

let's cd into our releases directory and

play47:42

list all the releases by time and date

play47:44

next we'll use the till command to

play47:46

offset this list by 5

play47:48

and return any remaining directories

play47:50

that might exist

play47:52

we'll use remove command to remove any

play47:54

directories that are returned by the

play47:55

tail command

play47:57

now we want to replicate this behavior

play47:59

for our artifacts directory as well so

play48:01

let's copy

play48:02

and paste this line and update the

play48:04

environment variable to reference

play48:06

our artifacts path time to commit this

play48:08

to git up and

play48:10

trigger workflow to verify if this works

play48:13

let's fast forward again to the output

play48:15

of our workflow so

play48:18

our commands have been successfully

play48:20

executed on a remote server so let's

play48:22

verify this by

play48:23

let's verify this by listing our

play48:25

releases and of course

play48:27

our artifacts as well as you can see

play48:30

there are five remaining of each

play48:32

and all the additional files have been

play48:34

removed

play48:36

that's it we've successfully deployed

play48:38

our laravel application

play48:39

to a remote server without any downtime

play48:42

in this video we've used a single server

play48:45

when we deploy our application

play48:48

i've duplicated the server that we've

play48:49

been using three times so we have a

play48:51

total of four

play48:52

and i've updated our server

play48:53

configuration to include these

play48:55

additional servers

play48:57

by default github actions run in

play48:59

parallel

play49:01

which is quite nice as you can see right

play49:02

here it's executing the prepare release

play49:05

job

play49:05

on all our servers simultaneously

play49:09

to see this in action i've also updated

play49:11

our level application

play49:12

to include the server name on the

play49:15

welcome page so if we take a look you

play49:18

can see that the documentation title has

play49:20

uploaded to server 1

play49:22

server 3 server 2

play49:27

and server 4. i hope you enjoyed this

play49:29

video and

play49:30

if you'd like to see more of these be

play49:32

sure to support me by clicking the like

play49:34

button

play49:34

and subscribing to my channel i truly

play49:36

appreciate all the support

play49:38

oh by the way if you have any questions

play49:40

drop your comment below and i'll get

play49:42

back to you

Rate This
โ˜…
โ˜…
โ˜…
โ˜…
โ˜…

5.0 / 5 (0 votes)

Related Tags
Web DevelopmentDevOpsLaravelDeploymentGitHub ActionsContinuous IntegrationContinuous DeploymentTutorialBeginner FriendlySelf-Taught