DEV Community

ChigozieCO
ChigozieCO

Posted on

Automate Build, Test & Deploy Processes with GitHub Actions

This project is a quick sample project that demonstrates the automation of the build, test, and deployment process of an application to a staging environment on push to the main branch.

To adequately demonstrate the CI/CD pipeline, we will create a simple Python project with minimal code and then integrate it into GitHub Actions.

Create a Simple Python Project

Like I earlier stated, we will create a simple project that we will use in our pipeline. I chose to do this in python for no particular reason, you can use any other programming language you choose, the main of this project is to demonstrate the pipeline.

Create Project Folder

So go ahead and create the project folder and navigate into that folder:

mkdir automated-testing
cd automated-testing
Enter fullscreen mode Exit fullscreen mode

Write Application File

Now we will write the simple python application. Create a new file app.py in the project folder.

touch app.py
Enter fullscreen mode Exit fullscreen mode

Add the below code block to the file:

def hello():
  return "Hello, World!"

if __name__ == "__main__":
  print(hello())
Enter fullscreen mode Exit fullscreen mode

This is a very simple python "Hello world" function that serves as an example of basic functionality that can be tested in the CI pipeline.

def hello() defines a function named hello which takes no arguments. When this function is called, it returns the string "Hello, World!".

if __name__ == "__main__" is a standard Python construct used to ensure that certain code only runs when the file is executed directly (not when imported as a module). It acts as an entry point for the script.

When app.py is run directly (e.g., by running python app.py), the script will call the hello() function and print the result, which is "Hello, World!".

Create a Requirements File.

A typical project would have dependencies and in a python project they are usually defined in the requirements.txt file.

Create a new file requirements.txt

touch requirements.txt
Enter fullscreen mode Exit fullscreen mode

Add this to the file:

pytest
Enter fullscreen mode Exit fullscreen mode

Create Unit Test

Now we will add a basic test file, test_app.py, to test the function in app.py. Add the below to the file:

from app import hello

def test_hello():
  assert hello() == "Hello, World!"
Enter fullscreen mode Exit fullscreen mode

Now we are ready to create our pipeline.

Set Up GitHub Actions for CI/CD

To configure GitHub actions we need to create a .github/workflows folder inside our repo, this is how we notify GitHub of the CI/CD pipeline in our repo.

Create a new file:

mkdir -p .github/workflows
Enter fullscreen mode Exit fullscreen mode

You can have multiple pipelines in one repo, so create a file proj.yml in the .github/workflows folder. This is where we will define the steps for building, testing, and deploying our Python project.

Add the below code to your file:

name: Build, Test and Deploy

# Trigger the workflow on pushes to the main branch
on:
  push:
    branches:
      - main

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
    # Checkout the code from the repository
    - name: Checkout repo
      uses: actions/checkout@v4

    # Set up Python environment
    - name: Setup Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.x'

    # Install dependencies
    - name: Install Dependecies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt

    # Build (this project deosn't require a build but we will simulate a build by creating a file)
    - name: Build Project
      run: |
        mkdir -p build
        # Simulate build output by creating a file
        touch build/output_file.txt

    # Run tests using pytest
    - name: Run tests
      run: 
        pytest

    # Upload the build output as an artifact (we created a file in the build step to simulate an artifact)
    - name: Upload build artifact
      uses: actions/upload-artifact@v4
      with:
        name: build-artifact
        path: build/

  deploy:
    runs-on: ubuntu-latest
    needs: build-and-test
    if: success()

    steps:
    # Download the artifact from the build stage
    - name: Download build artifact
      uses: actions/download-artifact@v4
      with:
        name: build-artifact
        path: build/

    - name: Simulate Deployment
      run: |
        echo "Deploying to staging..."
        ls build/
Enter fullscreen mode Exit fullscreen mode

Breakdown of the CI/CD Pipeline Steps

  • Trigger on Push to main: The pipeline is triggered whenever there is a push to the main branch.
  • Checkout Code: This step uses GitHub’s checkout action to pull our code from the repository.
  • Set Up Python: The pipeline sets up a Python environment on the CI runner (GitHub's virtual machine), ensuring that the correct Python version is used.
  • Install Dependencies: It installs the required dependencies for our Python project (pytest in this case). This dependency was just added as an example of when a project has dependencies as this particular sample python application does not require any.
  • Build: This stage was also just added for demonstration purposes, supposing this was a JavaScript/Node.js project this is where we would run the npm run build command and this will create an artifact we can upload and use in the deploy stage. Since this is a python project and it doesn't really require a build, we will create a file and folder in this stage. The file will serve as our artifact for the deploy stage.
  • Run Tests: It runs the tests using pytest to validate the code.
  • Upload Build Artifact: After running the tests, the build-and-test stage creates and saves a build artifact (in this case, a simulated output_file.txt in the build folder from the build step). The action upload-artifact is used to store this artifact. You can replace this with whatever actual build output your project creates.
  • Deploy Stage: Our application will only be deployed if the test was successful which is why I have added the conditionals needs and if. Using “needs” we can require that the deploy job won’t even run unless the test job is successful. The download-artifact action retrieves the build artifact and the last step "Simulate Deployment" simulates deployment by printing a message and lists the artifact. If this was a live project we would have the actual deployment commands to deploy to a real staging environment here. You can replace the echo and ls commands with actual deployment commands (e.g., deploying to a cloud platform). This approach ensures that the output from the build-and-test stage is properly passed to the deploy stage, simulating how a real deployment would work with build artifacts.

Push to GitHub

If you haven't already, you need to initialize a git repository using the commands below:

git init
git add .
git commit -m "Create project as well as CI/CD pipeline"
Enter fullscreen mode Exit fullscreen mode

Now we push to GitHub. Create a GitHub repository and push your code using the below commands:

git remote add origin <your-repo-url>
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Verify the Pipeline

After pushing the code, you can visit the Actions tab in your GitHub repository. You should see the pipeline triggered, running the steps defined in your proj.yml file.

If everything is set up correctly, the pipeline will build, test, and simulate deployment. You can changes things around in your project and make new pushes to see the the pipeline works, create errors intentional so you can see how the pipeline works when the tests fail.

On a successful run this is how your Actions tab should look.

successful-workflow-run

And that's it, this setup provides a working example of a CI/CD pipeline for a very basic Python project. If you found this helpful, please share with your connection and if you have any questions, do not hesitate to drop the question in the comments.

Top comments (0)