Creating a CI/CD Pipeline With GitHub Actions and API - (r)

Aug 15, 2023
CI/CD pipeline with GitHub Actions

-sidebar-toc>

The Reasons to Use CI/CD?

One reason is that, in a collaborative environment that has multiple developers working on the same project, automatic deployments triggered due to a single developer's modification of the repository can lead to instability and unforeseen issues. Without proper testing and validation, even a small alteration to code can disrupt the site's live version, creating downtime as well as poor user experience.

This is where a CI/CD pipeline comes into play. By creating a carefully orchestrated CI/CD workflow, developers can assure that their code modifications undergo testing and validation before being deployed to live sites. There are many tools available for implementing CI/CD in software development. In this tutorial, we'll use the GitHub Actions for this tutorial.

What Is GitHub actions?

GitHub Actions is an incredibly powerful automated tool offered by GitHub. It allows developers to automate various tasks processes and workflows inside their software development initiatives. It integrates with GitHub repositories, which makes it simple to use.

Utilizing GitHub Actions and the API, you can define customized workflows to meet the requirements of your project. You can set up the CI pipeline that runs tests on your application and triggers deployment on .

Getting Started By GitHub Actions

GitHub Actions operates on the idea of workflows. They are a collection of automatized tasks that are triggered by specific events or scheduled to run on a regular basis. The events could include pull requests, code pushes as well as issue creation and many more. When one of these events happens, GitHub Actions automatically runs the workflow associated with it, and executes a series of predefined steps.

Every step of the workflow represents a particular procedure, for example, building the code, testing and deploying or even making notifications. Let's build a workflow with three steps:

  1. Check syntax with ESLint
  2. Run tests
  3. Re-deploy the application

Step 1: Set Up Your GitHub Repository

To get started with GitHub Actions, you need an account on GitHub. GitHub repository.

You are welcome to access the repository by going to it on GitHub and choosing: Use this template > Start a new repository.

In this React application, unit tests are created for each component in order to verify its functionality. ESLint also helps ensure that the syntax is correct and to enforce code formatting. The CI pipeline blocks any deployment in the event that an pull request, or merge code that is pushed into a repository fails testing of the workflow.

Step 2: Create a Workflow File

Set up your workflow by creating a YAML file inside your repository's .github/workflows directory. This directory should be at the root level in your repository. The naming convention for workflow files is name-of-the-workflow.yml.

  1. In your repository, make a .github directory.
  2. In the .github directory, create a brand new directory called workflows.
  3. Inside the workflows directory, create a new file with a name like build-test-deploy.yml.

Step 3: Write the Workflow CI/CD

Now that you have created the workflow file, create an appropriate workflow that includes the steps for checking syntax using ESLint, test the workflow, and finally, deploy the software.

Create CI Event

When creating a CI pipeline, the initial process is to give the workflow a name and then set the event that would trigger the workflow. For this example, two of the events would be a pull request and a push into the branch that is in charge.

name Create, Test and then deploy to the pushbranches "main"
request for pullbranches "main"

If you'd prefer to schedule regular jobs (CRON jobs) to perform specific tasks it is possible to add these to your workflow. As an example, you may need to schedule specific tasks such as database backups, data cleaning, or any other regular maintenance tasks.

Here's an example of how you could include a CRON task to the workflow

on:
 # Existing triggers for events like pull and push requestsSet a schedule CRON jobs for cron "0 0. * *"

This scenario will start the process every day around midnight (UTC time) since the cron schedule has been configured to the following: 0 0 *. The cron schedule can be customized to meet your specific needs. schedule to fit your individual demands.

In a second example, imagine you would like to set up the C/C workflow for each Monday morning around 8 a.m. It is possible to set up a CRON job with the timetable event:

name Create, Test and deployon the following branches: pushbranches "main"
pull_request:branches "main"
branches "main"The workflow should be scheduled to start every Monday morning starting at 8:30 a.m. (UTC time)
schedule:"cron: "0 8 * * 1"
 
jobs:# Create jobs

The schedule syntax that is used to create the scheduling event in the GitHub Actions workflows is based upon the UNIX cron syntax. This syntax allows you to specify particular times and intervals to allow your workflow to run automatically. The syntax is composed of five fields, which are various aspects of the scheduling. Every field can be separated by the space. The format for the scheduling syntax follows:

* * * * + + + +| |  | | | | +- Day of the week (0 7) (Sunday through Saturday in which both 7 and 0 represent Sunday) | +--- month (1 12)
  +-----  Day (1 - 31)
 | +------- Hour (0 - 23)
  Minute (0 between 59 and)

Then, let's take a look at each field:

  • Minute (0 - the 59th minute): The minute that the cron task will be activated. As an example, 15 means that the workflow is activated in the 15th minute the hour.
  • Hour (0 23): The hour at which the cron job will begin to run. In this case, 8 means the workflow will trigger at 8 a.m.
  • The day of the month (1 1 - 31): The day of the month on which the cron task will be activated. For example, 1 means that the workflow is activated at the beginning of the month.
  • Month (1 - 12): The month in which the cron task will trigger. As an example, 6 means that the workflow will start in June.
  • The day of the week (0 - seven): The day that falls on a weekday when the cron job will trigger. This is because zero and 7 each represent Sunday. 1 signifies Monday, and so on. For example, 4 means the workflow will start when Thursday rolls around.

Special characters:

  • * (asterisk): Matches any value for that field. In this case, * in the field for minute indicates that the workflow is activated every minute.
  • */n (slash): It specifies an interval. As an example, */5 in the minute field indicates that the workflow will trigger every five minutes.
  • , (comma): Specifies multiple particular values. For example, 1,15,30 in the field for minutes means that the workflow will start at the 1st, 15th, and 30th minutes of the hour.
  • - (hyphen): The hyphen indicates a number of values. In this case, 1-5 in the day of the week field signifies that the workflow starts between Monday and Friday (1 through 5).
  • ? (question mark) It is used to define the absence of a specific value. It is often used for the day of the week field, where the day of the month is specified. As an example, ? in the day of the week field and fifteen in the month's day field means it will be activated at the 15th day of the month, regardless of the day of the week.

Create a CI Job to Verify Syntax Using ESLint

To set up the CI process, we will create the necessary jobs or tasks. Each job should have a clear and understandable name. Let's say the job is eslint since it will involve reviewing the syntax of code with ESLint.

jobs:
 eslint:
 name: Check Syntax by using ESLint
runs-on: ubuntu-latest
 
strategy:matrix:
node-version [18.x, 20.x]

Next, define the steps to be followed by the "ESLint" task is to run. This includes checking the code, setting up the specified Node.js version to run ESLint, caching npm packages, establishing project dependencies, and finally using ESLint to check the syntax of your code.

 steps:
 - name: Checkout code
 uses: actions/checkout@v3
 
 - name: Use Node.js $ matrix.node-version  to Check Lint
 uses: actions/setup-node@v3
 with:
 node-version: $ matrix.node-version 
 cache: 'npm'
 
 - name: Install Dependencies
 run: npm ci
 
 - name: Run ESLint
 run: npm run lint

The workflow described above has each step is given a description with a name to make it easy to find the root of the error or bugs when inspecting the process using GitHub Actions. Particularly, in the third step, we use the the npm ci command for installing dependencies. This is more preferred to npm install as it performs an uncluttered installation. Furthermore, the third stage, performing ESLint with the npm run lint command requires that you have installed this command into your package.json file.

Below is the full task for checking code syntax with ESLint:

jobs:
 eslint:
 name: Check Syntax with ESLint
 runs-on: ubuntu-latest
 
 strategy:
 matrix:
 node-version: [18.x, 20.x]
 
 steps:
 - name: Checkout code
 uses: actions/checkout@v3
 
 - name: Use Node.js $ matrix.node-version  to Check Lint
 uses: actions/setup-node@v3
 with:
 node-version: $ matrix.node-version 
 cache: 'npm'
 
 - name: Install Dependencies
 run: npm ci
 
 - name: Run ESLint
 run: npm run lint

Create CI Job to Run Tests

For adding the CI job that runs tests, start by defining the job, and then giving it a descriptive name, such as testing. Also, we'll specify that this task is dependent upon the test eslint job. This means that the test job is run prior to testing tests job is executed. This ensures that the code is inspected for syntax mistakes prior to conducting the tests.

tests:
Name"Run Tests"needs: eslint
 runs-on: Ubuntu-latest

The next step is to define the steps that will be followed for the tests task. As with the first job, we'll check out the source code, configure Node.js version 18.x to run the tests. Install project dependencies using npm ci, and then execute tests with the run test command.

 steps:
 - name: Checkout code
 uses: actions/checkout@v3
 
 - name: Use Node.js 18.x to run Test
 uses: actions/setup-node@v3
 with:
 node-version: 18.x
 cache: 'npm'
 
 - name: Install Dependencies
 run: npm ci
 
 - name: Run Tests
 run: npm run test

Create CI Jobs To deploy Using API

 deploy:
 name: Re-Deploy Application
 needs: [eslint, tests]
 runs-on: ubuntu-latest

Learning the API

To create an API key: API key:

  1. Log into your My Dashboard.
  2. Navigate to your API Keys page ( Your name > Company settings > API Keys).
  3. Click to Create API Key.
  4. Choose an expiration or set a custom start date and number of hours for the key to expire.
  5. Give the key a unique name.
  6. Click for Generate.
Create API Key on My
Create API Key by logging into My.

What is the best way to trigger deployment using API

To deploy an application to via the API, you need two parameters that are required: the application ID and the branch. You are able to retrieve the ID of your application by searching for the listing of your apps that will give you information regarding each application, which includes its ID.

curl -i -X POST \
 https://api..com/v2/applications/deployments \
 -H 'Authorization: Bearer ' \
 -H 'Content-Type: application/json' \
 -d '
 "app_id": "",
 "branch": "main"
 '

Trigger Deployment With cURL in CI/CD Pipeline

To trigger deployment with the API To trigger deployment with the API, simply incorporate the cURL command into the running command of your CI pipeline. However, it's important to keep your API key as well as your application's ID securely.

  1. Navigate to the repository where you'd like to put up the secret.
  2. Go to the Settings tab on the menu for the repository.
  3. On the left sidebar, click Secrets in the Options category.
  4. Click on The new repository Secret.
  5. Create a unique name for your secret (like _API_KEY) and enter your API key in the Value field.
  6. Once you have entered the name and the value, click on Add secret button. "Add secret" option to store it.
  7. Repeat the procedure for additional methods.
Storing secrets on GitHub
Keep secrets on GitHub.

Once you have added the secrets, you can reference them in your GitHub Actions workflow by using the $secrets.SECRET_NAME |syntax.|secrets.SECRET_NAME} syntax.

Now, let's finish the deploy job for the GitHub Actions CI/CD pipeline. Create the steps as previously, but with only one process to deploy it to . The first step is to define the secrets in the the env command, and then include the cURL command in order to execute the deployment.

 steps:
 - name: Deploy to 
 env:
 _API_KEY: $ secrets._API_KEY 
 APP_ID: $ secrets.APP_ID 
 run: |
 curl -i -X POST \
 https://api..com/v2/applications/deployments \
 -H "Authorization: Bearer $_API_KEY" \
 -H "Content-Type: application/json" \
 -d '
 "app_id": "'"$APP_ID"'",
 "branch": "main"
 '

In the cURL command, you will notice that the environment variables are added within the command, allowing secret information to be secure accessed during the deployment process.

This is what your final CI/CD workflow should look like:

name: Build, Test, and Deploy
 
 on:
 push:
 branches: "main"
 pull_request:
 branches: "main"
 
 jobs:
 eslint:
 name: Check Syntax with ESLint
 runs-on: ubuntu-latest
 
 strategy:
 matrix:
 node-version: [18.x, 20.x]
 
 steps:
 - name: Checkout code
 uses: actions/checkout@v3
 
 - name: Use Node.js $ matrix.node-version  to Check Lint
 uses: actions/setup-node@v3
 with:
 node-version: $ matrix.node-version 
 cache: 'npm'
 
 - name: Install Dependencies
 run: npm ci
 
 - name: Run ESLint
 run: npm run lint
 
 tests:
 name: Run Tests
 needs: eslint
 runs-on: ubuntu-latest
 
 steps:
 - name: Checkout code
 uses: actions/checkout@v3
 
 - name: Use Node.js 18.x to run Test
 uses: actions/setup-node@v3
 with:
 node-version: 18.x
 cache: 'npm'
 
 - name: Install Dependencies
 run: npm ci
 
 - name: Run Tests
 run: npm run test
 
 deploy:
 name: Re-Deploy Application
 needs: [eslint, tests]
 runs-on: ubuntu-latest
 
 steps:
 - name: Deploy to 
 env:
 _API_KEY: $ secrets._API_KEY 
 APP_ID: $ secrets.APP_ID 
 run: |
 curl -i -X POST \
 https://api..com/v2/applications/deployments \
 -H "Authorization: Bearer $_API_KEY" \
 -H "Content-Type: application/json" \
 -d '
 "app_id": "'"$APP_ID"'",
 "branch": "main"
 '

Copy the given workflow and paste it into your build-test-deploy.yml file. After that, create an open pull request to include this file to the primary section of the repository. Make sure to note that this pull request will automatically start the process.

It lets you review any changes to your repository and ensure that any new change in the pull request passes the requirements before you decide whether to merge the changes into your codebase.

Storing secrets on GitHub
Store secrets in GitHub.

When you merge the pull request. You can go to the actions tab in your GitHub repository. You will be able to see the CI/CD workflow in motion.

GitHub Actions summary
GitHub Actions summary.

Click on each job for more information on the work (this is the reason you have to describe each phase of your work a clear job description).

CI steps details
CI steps details.

Enforcing Pull Request Workflows on GitHub

For effective management of code and cooperation in GitHub repositories it's important to implement a pull request workflow and stop direct commits to branches that are not part of the primary branch. This approach establishes a controlled and organized development process that requires all modifications to go through reviews and pull requests prior to merging with the primary branch.

If they follow this method, development teams can improve the quality of their code, reduce chances of developing bugs, and maintain an open record of any the changes.

This is how you can set up pull request workflow enforcement:

  1. Click the Settings tab in your repository on GitHub.
  2. Under Automation and Code Select Branches in the sidebar menu options.
  3. If there is no rule Click Add branch protection rule.
  4. Give a name to the rule. After that, you can select the checkbox for the requirement of a pull request before merging. Then, you will see further options for setting up.
  5. Additionally, make sure to check the box that says Checks on status that require to pass before merging.
  6. Customize additional options based on your needs and preferences.
  7. Hit on the button to create the button in order to save the rule.
Enforcing pull request workflow on GitHub
Pull request workflows must be enforced on GitHub.

By following these steps, you have created a rule to enforce the process of pulling pull requests within your GitHub repository. It ensures that every change are subjected to review and automated checks before being integrated into the main branch. This creates an efficient and productive working environment for development.

Summary

Through combining the capabilities of GitHub Actions along with the API to streamline your development workflow and foster a collaborative and efficient environment for your team of developers.

Developers can be confident in submitting codes, confident that they will be thoroughly tested before it is released for production. Additionally, all those who are involved can rest in mind knowing that the process of deployment is reliable and well-controlled.

   How do you use the API? Which endpoints do you want to see added to the API? What API-related tutorial do you wish to see in the future?

Joel Olawanle

Joel is an Frontend developer working at as Technical Editor. He is a fervent educator with a love of open source and has published over 200 technical pieces, mainly on JavaScript as well as its frameworks.