learning to work with Actions
GitHub Actions is a platform that allows you to automate workflows directly in your repository. You can create, customize, run, combine, and share actions to perform any job, including CI/CD. Thus, using the tool you can simplify and customize software development.
Key terms in GitHub Actions are workflow, task, and action. A workflow is a set of actions performed in response to events, such as commits or requests to merge branches. Each task in a workflow runs on a virtual machine and can involve multiple steps. Actions are custom steps that can be reused across different workflows, making it easy to create and maintain automated tasks.
Preparing the server
First of all, let's prepare
which will host our demo project. To do this, we will take the following steps.
In the control panel, create an account or log in if you already have an account. Inside we select Cloud platform → Servers and press Create a server.
In the settings, specify an arbitrary name and set the minimum configuration. The application does not require a lot of power to run.
Select all the necessary parameters and click
Create a server
.
We return to the control panel and go to the console of the created server. To log in you need a login (root) and password. Click LMB on the icon Hotkeys and add the generated password.
That's all for now with setting up the server. We'll return to it when we automate the deployment of the frontend and backend.
1. Automation of code review (eslint/tests)
Let's start by setting up GitHub Actions to run automatically eslint
and tests with each command push
or pull request
.
Setting up the file structure
The first step you need to take to get started with actions is to create a special directory
workflows
where we will store configuration files for GitHub Actions.
Go to the project directory and prepare the necessary paths:
cd /path/to/your/project
mkdir -p .github/workflows
Elementary action
Now we can create our first configuration file. Let's create a simple action. So we will first get acquainted with the capabilities of GitHub Actions, and only then we will move on to writing full-fledged logic.
Let's start with the file TEST.yml
:
name: TEST
on: [push]
jobs:
our-first-job:
runs-on: ubuntu-latest
steps:
- name: Run console log
run: echo "Hello GitHub Actions!"
On the first line using the key
name
we set a name for the action. Next in the key value
on
we describe the events upon the occurrence of which it should occur. Record
on: [push]
says that the reaction will be to all push commands in the repository – regardless of the branch to which the changes came. We'll also discuss how to make the adjustment more precise.
Keyword jobs
describes the “tasks” that GitHub must perform: one or more. In our example our-first-job
– arbitrary name.
And now we come to the instructions themselves. Here we describe the steps that make up the task and the operating system required to carry them out.
Full action
Let's move on to creating an action, where we will describe the checks that must be performed before merging the code with any branch. Let's name the file
CI.yml
:
name: CI
on: [pull_request]
jobs:
check-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20.12.2'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
check-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20.12.2'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
The configuration file above will run the linter and tests every time you open
pull request
.
Here the instructions are more complicated, because plugins are used:
actions/checkout@v4
— helps to access code from the repository in the context of our task;actions/setup-node@v4
— is responsible for installing the node of the required version.
If we translate the instructions into understandable language, we have literally written down the following steps.
- Launch the latest Ubuntu
- Do it
git clone
from our repository. - Install a node.
- Install the project dependencies.
- Run the command.
Flexible event setup
We can configure our action more flexibly, for example, so that it fires only for certain branches:
on:
push:
branches: [main, dev]
pull_request:
branches: [main]
The fragment above says that the action will occur when
push
in the branch
main
And
dev
as well as when creating
pull request
V
main
.
2. Automatic frontend deployment
Now let's look at how to set up automatic delivery of a front-end application to the server using GitHub Actions. Let’s use a not-so-usual method—we’ll write a Bash script and place it on the server to connect remotely and run the script as needed through “actions.”
Preparing the server
First of all, we need to prepare our server. To do this, we will download the necessary software (Nginx, NVM, Git) and configure SSH keys for a secure connection.
Install server nginx
It's simple – just enter the command:
sudo apt install nginx
To get NVM (Node Version Manager), you need to download and run the installation script:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
Next, we determine the location of the settings directory:
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
Install Git:
sudo apt install git
Let's create SSH keys to work with
git clone
. You will be required to enter a file name and password.
ssh-keygen -t ed25519 -C "Ваш любой комментарий"
The -t option specifies the encryption algorithm. We won’t dwell on his choice in detail; those interested can take a look
to the discussion on StackExchange
which compares the features of various ciphers, including the widely used RSA.
The comment is not required, but is useful when there are a lot of generated pairs.
Two keys should appear: private and public. To make sure of this, let's go to the directory where the SSH keys are stored:
cd /root/.ssh/
In the same directory we will create or add a file
config
to clarify which key is used to connect to GitHub. Let's use the simplest editor
nano
:
nano config
We add an entry that links the host and the keys used. Field
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/<your-private-key>
StrictHostKeyChecking no
A small digression about SSH keys
It's time to clear up one confusing point. Our instructions interact with two pairs of SSH keys at once:
- created locally on your computer to connect to the VPS;
- located on the VPS for authorization in the repository.
The first pair has already been created. Its keys are used when connecting to the server and are transmitted
. This makes it possible to execute commands via SSH.
The second pair is needed solely for performance git clone
in our script, you can copy the repository without entering a password only using SSH access. We will add the key from the second pair to the GitHub settings later.
This is quite a confusing moment, but you can handle it.
Script for updating the application
We sorted out the server. Now let's write a Bash script that will perform the entire application update process. Let's call him
:
#!/bin/bash
# Stop on error
set -e
# Load nvm
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# Move to folder with the apps from the github
cd /root
# Clone the repo
git clone <your-git-repo-link>
# Move to specific repo
cd /root/<name-of-repo>
# Install Node.js
nvm install
# Check node version
node -v
# Check npm version
npm -v
# Install dependencies
npm ci
# Build application
npm build
# Move build to the www folder
cp -rf /root/<your-project-name>/dist/* /var/www/default
# Remove repo
rm -rf /root/<your-project-name>
The script is commented in detail – it’s easy to figure out what’s happening.
Setting up GitHub Actions
Let's create a new file
.github/workflows/deploy-frontend.yml
:
name: Deploy
on:
push:
branches: [dev]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Set up SSH
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Run bash script via ssh
run: |
ssh -o StrictHostKeyChecking=no ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }} "bash ${{ secrets.PATH_TO_SCRIPT }}"
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
At the first step, we “explain” to the action how to work with SSH, and also pass the private key as a parameter. On the second, we connect to the server and run the previously written script
deploy.sh
.
But what key should I add? From the first pair or the second? It's simple. We add the key from the first pair to secrets – the private key on the local machine. And don’t forget to open access in the GitHub account settings – indicate the public key from the second pair created on the server.
To add variables to GitHub Actions secrets, you need to go to the repository page and then use the menu: Settings → Secrets and variables → Actions → New repository secret.
3. Automatic backend deployment
Preparing the server
Let's use PM2 – a convenient process manager for
Node.js
which simplifies the management and monitoring of server applications:
npm install -g pm2
Setting up GitHub Actions
Here we will go a slightly different way (this was done on purpose to show different possible options). Let's create a file
.github/workflows/deploy-backend.yml
:
name: Deploy Backend
on:
push:
branches: [dev]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Copy files to VPS
uses: appleboy/scp-action@v0.1.0
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: './*'
target: '</path/to/your/app>'
- name: Restart PM2
uses: appleboy/ssh-action@v0.1.0
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd </path/to/your/app>
nvm use
npm install
npm run build
pm2 start <your-app-name>
In this manual we say the following.
- Get access to our repository.
- Copy everything from the repository to the server.
- Execute the commands on the server: go to the project folder, install the node and dependencies, run the build using PM2.
Conclusion
GitHub Actions is a useful tool that can greatly simplify and speed up your development processes. We looked at three key automation scenarios: code review, front-end and back-end delivery. Using these examples, you can customize the scripts to suit your specific needs. A
Shared Line cloud servers
allow you to reduce project maintenance costs. Payment is made only for consumed power – according to the pay-as-you-go model.
Don't forget that to work with secrets (SERVER_IP
, SERVER_USER
, SERVER_SSH_KEY
) you need to make the appropriate settings in the repository on GitHub. This approach will ensure data security.
We hope the article was useful to you. If it wasn't clear enough, take a look YouTube video. And if you have any questions, don’t hesitate to ask them in the comments or Telegram channel. Good luck with your projects!