Laravel deployment with GitHub Actions
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
🎬 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.
🔧 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.
☁️ 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.
🔑 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.
💻 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.
🏗️ 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.
🚀 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.
🔄 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.
🧹 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.
🎉 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
💡Deployment
💡Laravel
💡YAML Syntax
💡CI/CD
💡Workflow
💡Artifact
💡Zero Downtime Deployment
💡SSH (Secure Shell)
💡Environment Variables
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
hey youtube in this video we're going to
take a look at deploying a layer of
application towards multiple servers
without any downtime using github
actions before we dive in
my name is filo and you're actually
watching my very first youtube video
about which i'm both excited
and also a little bit nervous i'm a
self-taught developer and my journey
started 20 years ago with frontpage
anyone who remembers that kinda makes me
feel old
anyways i've decided to dedicate 2021
towards sharing what i've learned over
the years
learning how to program getting started
as a freelancer but also co-founding a
startup
and the roller coaster that awaits you
when you get your first investment
but let's leave that for future videos
and get started with deploying our
application
towards multiple servers without any
downtime using data
[Music]
action
let's start with a quick introduction to
github actions
github actions allow you to trigger a
workflow when specific github events
occur
for example you can run a test suite
when a pull request is made
or in our case create a build of our
product and upload it to multiple
servers
when the commit is pushed to our master
branch
our first step is to create a new
repository on github
so i'm going to create a new repository
called hello world
i'm going to make it private and i'm
going to create it
okay so in this example i'm going to use
a plain
laravel installation but you can use any
project that you want
whether it's a wordpress website a
static website
it doesn't really matter you can just
follow along and
adjust accordingly
so i'm going to switch over to my
terminal
and i'm going to use the laravel
installer to install
a plain version of the framework
next i'm going to add our data
repository to our
local environment so we can easily push
to get
up when we make changes
now let's add the code that we have so
far
and let's push it up to get up
okay so we have our repository set up
now we can move over to
creating our workflow let's open up our
editor
and let's create our first workflow file
github actions uses a yaml syntax to
define the events jobs and steps
these yaml files are stored in our
repository in a directory called
github slash workflows so let's create
that now
create a new file type dot github
slash workflows you can name your
workflow file
anything you want in this case i'm going
to name it
deploy application.yml like i mentioned
github uses a yaml syntax so we're going
to
first define a name i'm going to call
our workflow
deploy application next we want to
define
the trigger that's going to trigger this
workflow
so i'm going to say on push
and i only want this event to trigger
when a push has been made
on the master branch
next we're going to start with our first
job we basically want to prepare our
application
so that it's ready to be run on the
production environment
in this case we're using laravel so we
want to make sure that we compile our
css
our javascript and install our php
composer dependencies let's start off by
giving an
identifier to a job let's call it create
deployment
artifacts
next we're going to provide it with a
name that's going to be displayed in the
github interface let's call it
create deployment artifacts next we're
going to define our runner
our runner is basically a server that
has the github actions
runner application installed in this
case we're going to make use of a
runner that is hosted by github and
we're going to choose ubuntu
latest now we can continue by defining
the steps that we want to execute
on our runner in this case on the ubuntu
latest environment so we're going to
start off by
importing our repository code by default
it's a
empty os so it's just ubuntu with
no source code whatsoever so in our
first step
we're going to make use of an existing
action
in this case the checkout action which
is provided by github which allows you
to check out your source code
into your runner with just a single line
of code
so now that we have our source code we
can continue by
pulling in our npm dependencies
compile our css and javascript
so start off by giving it a name
and next we're going to use the run
parameter
to define a command that we want to run
inside our
runner which is ubuntu latest
so be using the pipe character you can
enter
multiple lines so in this case we want
to do npm install
and npm run production this will install
our npm dependencies and compile our css
and javascript
let's push the changes that we have so
far up to get up and let's see
what happens
when you switch to get up you'll notice
this orange indicator
this indicator tells you that a workflow
is currently running
so when you click actions you will get
an overview of
all your previous workflows that have
been executed and the ones that are
currently
running and as you can see our workflow
is currently in progress
click it you will get some more
information about the different jobs
which
exist inside this workflow in this case
our
create deployment artifacts with the
power of video editing
i'll make sure that i cut out any
waiting time so you
don't have to wait for every workflow to
be completed
our first workflow has just completed
let's take a look and see what has
happened
here you get an overview of all the
different steps inside
the create deployment artifacts job you
can see that it has
a setup job which is defined by github
and you can see that it's downloading
the required actions that we define in
our workflow
in this case it's calling the checkout
action
you can see that it checked out our
hello world repository
next we got our compile css and
javascript step
and you can see that it downloaded our
npm dependencies
and it successfully compiled our
javascript and css
okay next up want to make sure that our
runner is configured with the correct
version of php in this case we're going
to configure it with
php version 8 and we're going to make
sure that
certain hp extensions are enabled which
are
required by level in this case we're
going to make use of
a community build action this action is
going to help us to configure
php inside our runner with just a few
lines of code
so let's reference the action that we
want to use and let's provide it with
your required input parameters
let's define our version of php which is
8.0
and now let's define the extensions
which we want to include
in this case level requires mb string
c type file info
openssl
video emath
json tokenizer
and xml
let's commit these changes and push them
up to get up and
see if it works switch back to our
actions
and as you can see a new workflow has
been queued
let's forward to the output of our php
configuration
you can see that it found version php8
it set up composer which we need to
install our dependencies
and then enable the extensions which we
defined in our yaml file
so now that we have php configured and
composer installed we can install our
composer dependencies
so let's create a new step and let's
call it install composer dependencies
next we want to run a command inside our
runner
we can do composer install no dev
because we don't want any depth
dependencies on production
we add the no interaction flag because
it's an automated process
and we want to state that we prefer the
distribution source
okay so let's quickly commit these
changes and take a look
again going to speed up this a little
bit in post production
and there you can see our php composer
dependencies have been
installed successfully okay great
our build is complete so now we can
prepare it to be shipped to our
remote server in this case i want to
create an archive
of the entire application so we just
have one file to work with
okay let's name our next step let's call
it create deployment artifact
followed by the command that we want to
run inside a runner
in this case we're going to create a
archive
we're going to use the tar command with
the c flag
to tell it to create a new archive we're
going to use the z flag to tell that we
want to use
g zero compression and we're going to
use the f
flag to define that we want to have the
output
in a file
let's name the file app.gz
now what will happen it will create an
archive from all the files
in our current directory and as you
remember we've
installed npm dependencies that we
actually only needed
to create this build so we want to make
sure that these files are not included
in our archive
we can achieve this by using a exclude
flag
and we can define a pattern that we want
to use
to exclude for example the git directory
or in this case
the node modules directory let's push
these changes up to github and verify
that the results are as
we expect
the job has been completed you can see
that the command has
successfully executed since we're
pushing this file up to our remote
server
the file name app.gz is a little bit
unclear
we're not sure which release is actually
inside
so i want to make sure that we can
identify each release
by naming the file of our archive and
make sure that it's equal to the commit
hash
we can do this by using a get up action
syntax
which is available in these specific
yemo files
so start off by renaming our app
and use a an environment variable that
will be equal to our commit hash
now this environment variable doesn't
exist yet so we need to make sure that
the runner knows what the github
commit hash is
we can achieve this by using the
environment flag
so we're going to tell it that the
environment variable github
sha is equal to the commit hash
if you want to know more about the
available properties that you can
reference
be sure to check out the documentation
on github.com
so let's reference the commit hash and
that's it we can now continue with our
next step which is
uploading our deployment artifact okay
let's define our next step
and we'll start off again by providing
it with a name let's call it
store artifact for distribution
next we're going to use a getup action
again
just like the checkout action github
also has a
specific action which allows you to
upload
build artifacts
we're going to use the uses key to
reference actions
slash upload this action requires a
couple of parameters
so we're going to use with to define
these parameters
we're going to start off by a name this
is going to be the name of our artifact
that we can use for later reference
for example in a future step we want to
download these artifacts
and we need to reference the name that
we define right here
so let's call it app dash build
next we need to tell the upload artifact
action
to tell where we can find our file that
we want to upload
so we're going to reference the archive
file we've created earlier
the commit hash as our file name plus
star.gz
let's commit our changes to git up and
verify that everything works
okay so our workflow is running let me
quickly fast forward to the end of the
job
okay there we go as you can see we now
have one artifact
with the name app built and it's a
little over 3.6
megabyte okay so now we can work on
uploading our artifact to our servers
but at the moment
we don't have any information about our
service just yet
so in this case i want to create a new
json file
which will contain a list of our servers
with the required information
like ip address authentication like
username and password
and a bunch of other configurations so
let's start off by creating a
new file in the root of our repository
called deploymentconfig.json
start by giving our server a name and
it's just for easy reference so when we
take a look at the github ui we can
easily spot it
followed by the ip address of our server
next we got our username let's
enter root let's add a password as well
i'm going to set it to git up actions
for now
next we got our port which is 22 for ssh
i want to be able to set a hook before
and after the deployment on each server
so we're going to add a
before hook option where we can enter
any command that we want to run before
our release is activated
for example we can run a database
migration or
run a database backup you name it
when a release is complete we might want
to send out a
select notification so let's create an
after hook configuration option as well
next we want to set up a server path
which
is where our website will be located so
in this case
i'm using engine x i'm going to point
the directory
to far slash www
html i don't have a server set up just
yet
so let's head over to digitalocean to
quickly configure a server
if you already have a server up running
that's totally fine you can just skip
ahead to the next part
so let's start by creating a new server
i'm going to use a
marketplace image which has linux mysql
and php pre-installed
select the type of server we want to use
i'm going to choose amsterdam for my
region
and i'm going to use password
authentication
for this example but i highly recommend
that you use ssh keys in production
okay so the password that i've entered
earlier in the server configuration does
not meet
the password requirements from the
digital ocean
so let's make this one a bit more
complicated
let's make sure that we also update our
password in our configuration file
okay so let's leave the host name as it
is
and that's it let's create our server
okay let's copy the ip address and let's
see if we can ssh into our server
there we go that seems to work
now let's quickly verify that our server
can be reached
and that our web server is up and
running there we go that seems to be
working as well by the end of this video
we will have achieved the
following directory structure now i want
to point out the
current and releases directories
the releases directory contain the
releases that we upload
these are our unarchived artifacts
when the archiving is done we swap out
the
current directory and point it to the
new release
so the current directory doesn't really
exist it's more like a
shortcut into our release directory
so we need to make sure that our engine
x configuration is pointed to this
current directory
so let's ssh into our server and make a
change to the
engine x server configuration let's
change the
root directory of our web server and
open
the current directory now in our case
we're deploying a laravel application
which comes with a specific public
directory and we need to point our web
server
to that directory so let's append public
as well
let's save our changes and restart nginx
and if you reload the browser then you
can see that the changes have been made
to the nginx configuration
but that it currently cannot find that
directory
let's update our configuration file with
the ip address of our server
in this example we just have one server
that we're going to work with but you
can add as many as you like although
github does has a limit when it comes to
the deployment matrix in which we're
going to talk next
and this has a specific limit of 265.
so if you exceed that limit then you'll
probably have to look at a different
solution
okay so before we can continue we need
to export our configuration file that
contains our servers
and make it available inside our
workflow
in order to do this we need to add an
additional step
let's create a new step and let's name
it export
deployment matrix
and basically what we're going to do is
use the runner
to load the contents of the deployment
configuration file echo it out
to the command line interface and use a
special syntax
so github understands that we want to
make this information available inside
our workflow
since you want to reference the output
of this specific job later
on we want to provide it with an id so
let's name it
export deployment matrix
next we'll define our command
let's create a json variable and assign
it to the contents of our deployment
config.json file
so this doesn't work really well with
multi-line json files
so i found a piece of code which
basically
escapes the multi-line json file that we
have
and make sure that it works so now we're
going to echo out our json
but we're going to prepend it with a
specific name
which allows github to read it
so we can do set output
we're gonna provide it with a name we're
gonna call it
deployment matrix next we're gonna
provide it with the value
in this case our json string okay now we
need to tell github that we want to
store this information so we can use it
for later reference
so scroll back to the top
and add a new input parameter called
outputs to the create deployment
artifact step
provided with a key that we can use for
later reference in this case we're going
to call it
deployment matrix
next we'll use github specific context
information that we've used earlier to
get the git comment hash and now we're
going to reference
steps followed by the id of our step in
this case
export deployment matrix
output followed by the name that we've
provided in the echo statement
which is deployment matrix
okay we're all good to go to move on to
our next job
in this case preparing the release on
our server
so let's name it prepare release on
server
now we're gonna define that this runs on
the latest version of ubuntu as well
next we're gonna use the needs parameter
to make sure that our previous step has
been completed
otherwise they will run asynchronous
and now we're going to work on our
matrix
so we use the strategy input parameter
use the matrix keyword to build a matrix
configuration
you can basically see this as a for each
loop
the steps that we define in this job are
going to be repeated
on the objects with inside the matrix
in this case this is going to be our
server configuration
so we're going to load the json which we
exported in our previous step
into the repair release on server step
okay so the matrix is going to loop
through our json file and we want to
provide a name that we can use to
reference the information in our json
file
in this case we got a list of servers so
let's use the keyword
server the matrix
expects a array to be provided
at the moment we have a json string
so we're going to use the function
called from.json provided with the
output of our previous step
we can do this by referencing of the
chain so we're going to say needs
dot create deployment artifacts dot
outputs
dot deployment matrix which matches up
with the
output variable that we defined earlier
now that we have our matrix setup we can
continue
with setting up the steps for this
specific
job so we want to start out by
downloading the artifact from our
previous step
so again we're going to use a github
specific action
which is called action slash download
artifact so this action
only requires one input parameter which
is the name of our artifact
so let's enter app dash build
let's commit the changes to get up and
take a look
okay so our export deployment matrix
step has failed
let's take a look at our workflow file
to see what's wrong
ah it looks that i forgot a quote
let's try that again
and there you go this time it has
completed successfully
and on the left hand side you can
actually see that it has successfully
read our matrix as you can see that it's
saying prepare release on servers and
you can actually see that it's
referencing
server one with the ip address
again this includes the
credentials as well so in production
make sure that you use
repository secrets and ssh keys
okay so we got our artifact downloaded
next we can upload it to our servers
again we're going to make use of a
community build action
which allows us to upload our zip file
to our servers
first let's create our next step let's
name it upload
followed by the users parameter to
provide the action that we want to use
in this case apple boy
scp action by the way if you want you
can copy and paste the name of your
action
and just head over to github.com the
name of your action
and you actually see the source code of
the action which is being run behind the
scenes
so here you can see these actions allow
for copying files and artifacts via ssh
and on this page you can see the usage
input
variables and code examples on how to
specifically use this
action okay let's head back to phpstorm
and provide the necessary input
parameters
i'm going to start off with the host
which is going to be equal to the server
ip
we've got the server ip in our
deployment config so we only need to
reference it here
we can use the server object inside our
matrix to be defined above
so in this case matrix.server.ip
which will reference the ip address
inside our deployment config
let's repeat this process for the
username
password
or next we're going to define the source
which is going to be the file that we
want to upload
so this is going to be equal to the
commit hash so again we reference github
dot sha we append
the file extension which is dot tar.gz
next we're gonna define the target this
is going to be equal to the directory
where we want to upload the file on a
remote server
so in this case matrix.server.path
to reference the server path that we
define in our deployment configuration
now let's make sure that our artifacts
are grouped nicely together inside a
single directory
so let's append the server path with a
new directory name
called artifacts this will be equal to
far slash www.html
artifacts let's commit our changes and
push them together
let's verify that our action is working
and that our artifact is uploaded to our
server
let's fast forward to the end of this
workflow
there we go it successfully executed the
transfer
to our server let's ssh into our server
and verify that the file's there so i'm
going to check
inside our var slash www
html directory to see if our file's
there
it looks like something went wrong
because we only got our index.html
so let's take a look and it seems that
i've got a w
inside the server configuration where we
define our server path
let's commit the changes and try this
again
the workflow has successfully completed
the upload has been completed
and it looks like that it created the
folder in the correct place
so let's check our server and there we
go our artifacts directory is there
and it does contain our archive with our
current release
okay so we got our file on our server
now we need to extract it
so that we have a release to actually
work with
so let's create a new step let's name it
extract archive and create directories
so in order to extract our archive we
need to ssh into our remote server
we're going to use a another action by
the same author
called appleboy slash ssh action
which will allow us to execute remote
commands
on our server i'm going to copy and
paste the hostname username password
import
since those are exactly the same as in
our previous step
next we'll use the script input
parameter to define the commands that we
want to run on a remote server
let's kick off by creating a new
directory that will hold
our current release let's use the make
their command
to create the directory if it doesn't
exist yet let's reference our
server path followed by the releases
directory
followed by the commit hash now this
github underscore sha environment
variable doesn't exist yet
so let's make sure that we pass it
inside our
input parameters for this specific
action so let's set the n
flag and let's define github underscore
sha
to be equal to the commit hash of this
release
environment variable will now be
available inside our runner
we want to make sure that it's also
available for us inside
our remote server
we can do this by providing a
environment input variable
for our action so now this environment
firewall should be available on a remote
server
let's extract the contents of our
archive into the release directory we
just created
we can use the tar command to extract
our archive
so let's do tar x z f
followed by the path to our archive file
which is equal to
our server path followed by the
artifacts directory
followed by the mid hedge of our current
release
and of course the file extension which
is dottar.gc
next we'll add the c flag
to make sure that the tar command
understands that we want to extract
contents
into the releases directory which again
is our server path followed by slash
releases
slash our release commit hash
time to commit our changes again and
push them up to get up to verify that
everything works
let's fast forward again to the output
of our workflow
okay it seems that our job has filled so
let's take a look what's going on
cannot find our archive and it seems
that the name is incorrect because those
brackets shouldn't be in there so let's
take a look at our workflow
and there you go i made a mistake right
there the dollar sign
should be before the bracket so let's
change it
let's push the changes to get up and
let's try again
this time the job has successfully
completed so let's ssh into a remote
server
check the release directory and make
sure that our files are there
and there we go our laravel application
has been extracted
into the release directory let's head
back to phpstorm and continue with our
workflow
we're going to make some specific
changes for our larva application
if you don't use level you can still
follow along we're going to work on
something which allows us to share
storage between different releases if
you're unfamiliar with laravel
basically it ships with a storage
directory inside our repository this
directory is somewhat empty
but on our production release we might
actually have files in there
and of course we don't want to overwrite
our files on our server
so let's make sure that the storage
directory is removed from
our release so we can link it up to our
shared storage directory so we use
the rm command to remove this directory
which is located in our server path
followed by
our releases directory our release
commit hash followed by the name of the
directory which is storage next we'll
replicate the storage directory
structure
but outside of our release and again
using the make their command to make a
storage directory inside the storage
directory we're going to
create a couple of new folders which are
required for the laravel framework in
order to
function in this case app
public framework
and logs our framework directory
requires a couple of
extra directories let's make sure these
directories exist as well
in this case cache sessions testing
and views finally we need to make sure
that the storage directory
and all sub-directories are writable
so let's make sure that we provide the
path to our storage directory
and continue with our next show so in
our next step we are going to run our
before hooks
which allows to execute any commands
before our release is activated
let's identify our next job by calling
it run
before hooks
and of course let's give it a name as
well if you want to make your steps
easier to read you can actually
reference your matrix object within the
name
as well so for example we could do
matrix server.name to get the name of
the server
and add beforehook so in the github ui
we'll get
server one beforehand which makes it
easier to identify on which server
the actual job is running we're gonna
repeat a couple of things of course
again we're gonna make sure that it's
running on the latest version of ubuntu
we're gonna define our needs parameter
to
tell it that we want to have our create
deployment artifacts and our prepare
release on server
jobs to be completed we're going to
reference our
matrix again and let's just copy and
paste it from our previous step
let's name our step run before hooks
let's save ourselves some time by
copying the step from our previous job
to execute a command on a remote server
next we'll add the script tag again
followed by the before hook from
our server configuration by referencing
our matrix objects so let's do
matrix.server.for hooks
inside our server configuration we can
now define our beforehooks
these beforeholds will be executed
before we activate release
so you might like go into a certain
directory and execute a clone
it would be pretty nice if we don't have
to do things like
far slash www etc
but we can reference a environment
variable which makes it a bit easier for
us for example
we could do c d release path in order to
get in our current release directory
this won't work just yet
we need to make sure that the
environment variable actually exists so
let's define our environment variable
which we called release underscore path
we'll reference the server path followed
by the releases directory
followed by the directory name which is
equal to our release commit hash
okay next we want to set an environment
variable that we can use to reference
the path to our active release
so let's name this environment variable
active underscore
release underscore buff followed again
by the server path
followed by the current directory
next we also have a storage path which
is the path to our storage directory
and the base path which is nothing else
than our
server path now let's make sure that
these environment variables are actually
available on a remote server by again
going to the
input variables for our ssh action
and defining the ends input variable
followed by
the environment variables that we want
to make available in this case our
release hash
our release path our active release path
our storage path
and our base path now we of course want
to make sure that this actually works so
let's head over to our deployment
configuration
and echo out the github commit hash
time to push our change up to get up and
take a look it seems something went
wrong
the workflow is not valid job run
beforehand depends on unknown job
prepare release on server
so let's take a look and it seems i've
got an
s right there let's try again
this time our workflow has successfully
completed let's verify that our commands
are successfully executed
that looks good let's verify on our
server and our storage directory is
there and you can see by the green
highlight that
the write permission is set correctly
next we got our before hook let's open
it up and there you can see
we echoed out the github commit hash and
on line 30 you can see that it is equal
to 884 etc so that is working as well
our environment variable is available on
a remote server now it's time to work on
the most exciting step
activating our release let's just copy
paste to run before hook step since the
active release app is
going to be a couple of ssh commands as
well
let's rename it to activate release
of course make sure that our run before
hooks has actually completed before we
run this job
change name to activate release as well
let's change the step name okay i think
i spot a mistake that i made in the
previous
job and there should actually be a
single dollar sign
instead of two so let's make sure that
we update this across the file
i think we got them all let's replace it
with a single dollar sign
and two brackets
okay so now we want to make sure that
our current directory is pointing to
our new release we can do this by sim
linking
we're gonna simulate the current
directory
to the directory that holds the current
release
we'll use the ln command to set up a
symbolic link
the s-flag means it's a symbolic link
the n flag tells it that it's just
treated
as a normal file or directory and
dash f tells it to force or overwrite a
link if it already exists
this is then followed by the path to our
new release
and we want to make sure that it's
linked up to our slash current directory
or as we referenced before as the
environment variable
active and the score release and square
path in case you are using
engine x with php fpm you need to make
sure that php is actually reloaded
otherwise it will not pick up the
changes when we swap out a symbolic link
so we'll do this by doing surface hpa
fpm
reload time to verify that everything
works so let's push this up to get up
and take a look
at our job in this case it has
successfully executed commands on our
server it has set up the link
and it has reloaded php8 let's verify
this on our remote server
and there we go as you can see our
current directory is currently
simulink to the release that we just
deployed
let's see the interrupt current
directory to verify that our application
is of course actually there and there
you go
if you would head over to our browser
you can see that it isn't working just
yet
this is because we still need to set up
a couple of things in order for this
level application
to run successfully if you're unfamiliar
with laravel
it ships with a environment
configuration file
this file basically contains things like
the application name the url
database settings etc etc this file
needs to exist and needs to have a
couple of configuration options defined
in order for our framework to work
let's kick off by creating a environment
variable that's called laravel and score
n
and let's make sure that equals to the
level and secret
secret again is a keyword that is
context specific to this creative action
and we can define our secrets within the
github ui
so head over to your repository go to
settings secrets
new secret let's enter the same name
that we defined in our workflow file
which is laravel and screen
and i'm just going to copy and paste in
a example environment file that ships
with laravel and i just
changed the app name and the environment
to production now during each deployment
we want to make sure that our
environment file is updated
it doesn't exist right now so let's make
sure that it does
we will use the printf command to echo
the contents of our secret
into our environment file which is going
to be located
in our base path
of slash.nfc this file needs to be
inside our release
so we're going to use the link command
again but this time we're going to link
the environment file
from our base path to our release path
i could argue why not create this
environment file inside the release
directory well that will result in a lot
of environment files
scattered across all our different
releases i prefer to have a single file
which is a single source of truth
this makes it easier to work with since
we're here let's link up the storage
directory as well
we'll use the ln command and reference
the storage path
followed by the release path which
basically means that we now have a
storage directory available in a release
which is simulink to the storage
directory inside our base path
let's trigger the workflow and verify
the results on our server
okay everything has successfully
completed
let's take a look at our website and
unfortunately
it seems that it's still not working
let's go back to our server and take a
look
our files are there the end files is
there it's correctly linked
current directory is there
but the environment file is empty
let's see our level and is defined
i've got to pass the environment
variable to our remote server
so let's give this another try
okay our workflow has successfully
completed
but it's still not working
let's verify that there are environment
files there
okay that seems to work
but it's not yet working okay i quickly
paused the video for a second
i forgot to update my engine x
configuration
this server is proficient with php 7.4
which i upgraded to
version 8 but i've got to update the
engine x configuration
that was still referencing to php 7.4
so let's change it reload nginx and try
again
and yet it's still not working
let's dive back into the server and
check the error log
so larval is complaining about the fact
that we provide a
envelope cache path so
it seems that i forgot to create a
additional directory inside our storage
framework
cache directory which is a data
directory
so let's quickly create this right here
make sure that it has correct file
permissions
and refresh and there you go we have
successfully deployed
our laravel application so we've
manually
fixed it on our server but of course you
want to make sure that it is fixed in
our workflow as well
so let's head over back to phpstorm
scroll up and let's make sure that the
data directory
is created inside the cache directory
let's copy and paste our previous
command and let's adjust it accordingly
and next up we got our after hook
so to make things a bit easier let's
just copy and paste our before hook
since it's
almost the same
let's make sure that our activates
release job has finished before we
triggered the after hook
by adding it to our nice array
next we'll update the identifier to run
after hook
we update the name as well and the name
of the step
and finally let's make sure that we
reference the after hooks from our
server configuration
okay great our after hook is done as
well let's continue with a little bit of
a cleanup
every time this workflow is triggered it
will upload our artifacts
now if you do this 100 times this will
mean you have 100 artifacts
and these artifacts take up disk space
and you probably don't want to end up
with your server crashing in the middle
tonight because
it has run out of disk space so let's
make sure that we
clean up the releases and artifacts
directory
let's copy and paste our run after hook
shop and let's make some changes
let's change the identifier to cleanup
update the
name accordingly and the step name as
well
of course make sure that our after hook
has completed before we are running the
clean up
we don't need the environment variables
that we created earlier so let's remove
them
and replace them with two new
environment variables
we want one environment variable to
reference our
releases directory and another
environment variable that
references our artifacts directory
now we need to make sure that these two
environment variables are passed to a
remote server so
update the ends input variable of our
ssh action
let's cd into our releases directory and
list all the releases by time and date
next we'll use the till command to
offset this list by 5
and return any remaining directories
that might exist
we'll use remove command to remove any
directories that are returned by the
tail command
now we want to replicate this behavior
for our artifacts directory as well so
let's copy
and paste this line and update the
environment variable to reference
our artifacts path time to commit this
to git up and
trigger workflow to verify if this works
let's fast forward again to the output
of our workflow so
our commands have been successfully
executed on a remote server so let's
verify this by
let's verify this by listing our
releases and of course
our artifacts as well as you can see
there are five remaining of each
and all the additional files have been
removed
that's it we've successfully deployed
our laravel application
to a remote server without any downtime
in this video we've used a single server
when we deploy our application
i've duplicated the server that we've
been using three times so we have a
total of four
and i've updated our server
configuration to include these
additional servers
by default github actions run in
parallel
which is quite nice as you can see right
here it's executing the prepare release
job
on all our servers simultaneously
to see this in action i've also updated
our level application
to include the server name on the
welcome page so if we take a look you
can see that the documentation title has
uploaded to server 1
server 3 server 2
and server 4. i hope you enjoyed this
video and
if you'd like to see more of these be
sure to support me by clicking the like
button
and subscribing to my channel i truly
appreciate all the support
oh by the way if you have any questions
drop your comment below and i'll get
back to you
関連動画をさらに表示
Hosting Your Resume on AWS EC2 with a CI/CD Setup Using GitHub Actions | AWS Project Demo
How To Deploy Serverless SAM Using Code Pipeline (5 Min) | Using AWS Code Build & Code Commit
AWS CodePipeline tutorial | Build a CI/CD Pipeline on AWS
How to run your own local Telegram Bot API server in Python [PTB v13]
How GitHub Actions 10x my productivity
How to deploy your websites to Cloudflare's Pages Platform for free
5.0 / 5 (0 votes)