DEV Community

Cover image for Streamlining Software Development with GitHub Actions: Automation, Testing, and Deployment
Serhat Ozdursun
Serhat Ozdursun

Posted on

1

Streamlining Software Development with GitHub Actions: Automation, Testing, and Deployment

GitHub Actions is a powerful CI/CD (Continuous Integration and Continuous Deployment) tool integrated directly into GitHub, allowing developers and QA engineers to automate, customize, and execute workflows within repositories. This tool simplifies the software development lifecycle by automating build, test, deployment, and other routine tasks directly from GitHub repositories.

Key Features of GitHub Actions:

  • Integrated CI/CD Workflows: Automate your development pipeline with ease.
  • Cross-platform Support: Execute workflows on Linux, macOS, and Windows.
  • Matrix Builds: Run multiple workflows in parallel with different configurations.
  • Extensive Marketplace: Utilize pre-built actions from a rich community-driven marketplace.
  • Real-time Feedback: Immediate visibility into the state of workflows and tests directly within GitHub pull requests and commits.
  • Secure Secrets Management: Store sensitive information securely with GitHub secrets.

Example: Static Code Analysis with CodeQL

Below is a practical example workflow for performing static code analysis on pull requests using CodeQL to detect vulnerabilities and quality issues in TypeScript and JavaScript code:

name: CodeQL Static Code Analysis

on:
  pull_request:
    branches: [main]

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      matrix:
        language: ['typescript', 'javascript']

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        # Checks out your repository's code.

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2
        with:
          languages: ${{ matrix.language }}
        # Initializes the CodeQL environment for specified languages.

      - name: Build code
        uses: actions/setup-node@v3
        with:
          node-version: '22'
        # Sets up Node.js environment.

      - run: |
          if [ -f package-lock.json ]; then
            npm install
          elif [ -f yarn.lock ]; then
            yarn install
          fi
        # Installs dependencies based on lock files.

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v2
        # Runs the actual code analysis.
Enter fullscreen mode Exit fullscreen mode

Using GitHub Actions for QA Automation

Quality Assurance engineers leverage GitHub Actions to run automated end-to-end (E2E) tests seamlessly within the development pipeline. Here’s a detailed example workflow for running UI Automation Tests on Chrome:

name: UI Automation Test for Chrome

on:
  pull_request:
    branches:
      - main

jobs:
  build_and_test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout resume repository
        uses: actions/checkout@v3
        # Fetches the latest code from the repository.

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '22'
        # Sets up the Node.js environment.

      - name: Install dependencies and build
        run: |
          yarn install
          yarn build
        # Installs necessary dependencies and builds the application.

      - name: Start the application
        run: |
          yarn start &
        env:
          PORT: 3000
        # Starts the application on port 3000.

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.12'
        # Sets up the Python environment for running test scripts.

      - name: Install Chrome
        run: |
          sudo apt update
          sudo apt install -y wget gnupg
          wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
          sudo apt install -y ./google-chrome-stable_current_amd64.deb
        # Installs Google Chrome for browser automation testing.

      - name: Install ChromeDriver
        run: |
          CHROMEDRIVER_VERSION=$(curl -sS https://chromedriver.storage.googleapis.com/LATEST_RELEASE)
          wget https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION}/chromedriver_linux64.zip
          unzip chromedriver_linux64.zip
          sudo mv chromedriver /usr/local/bin/chromedriver
          sudo chmod +x /usr/local/bin/chromedriver
        # Installs ChromeDriver required by Selenium tests.

      - name: Clone the test repository
        run: |
          git clone https://github.com/serhatozdursun/serhatozdursun-ui-tests.git
        env:
          GITHUB_TOKEN: ${{ secrets.UI_TEST_TOKEN }}
        # Clones the repository containing UI test scripts.

      - name: Install Python dependencies
        working-directory: serhatozdursun-ui-tests
        run: |
          pip install -r requirements.txt
        # Installs Python dependencies required by the UI tests.

      - name: Run tests
        working-directory: serhatozdursun-ui-tests
        id: run_tests
        run: |
          pytest --browser chrome --base_url http://localhost:3000 --html=reports/html/report.html --junitxml=reports/report.xml
        # Executes the UI automation tests using pytest and Selenium.

      - name: Upload HTML report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: html-report
          path: serhatozdursun-ui-tests/reports/html
        continue-on-error: true
        # Uploads the HTML report for test results.

      - name: Upload XML report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: xml-report
          path: serhatozdursun-ui-tests/reports/report.xml
        continue-on-error: true
        # Uploads the XML report for test results.

Enter fullscreen mode Exit fullscreen mode

Step-by-step summary and objectives:

  1. Checkout Repository:
    • Objective: Fetches the latest version of the application code from the repository.
  2. Set up Node.js:
    • Objective: Prepares the environment required for Node.js application execution.
  3. Install Dependencies and Build:
    • Objective: Installs necessary packages and builds the application to verify code integrity and build stability.
  4. Start the Application:
    • Objective: Runs the application locally within the GitHub Actions environment to perform realistic E2E testing.
  5. Set up Python Environment:
    • Objective: Configures Python, essential for running Selenium tests.
  6. Install Google Chrome:
    • Objective: Provides the browser needed to execute Selenium-based UI automation tests.
  7. Install ChromeDriver:
    • Objective: Installs the driver for Selenium to interface with Chrome for browser automation.
  8. Clone Test Repository:
    • Objective: Retrieves the latest version of automated UI tests from the dedicated repository.
  9. Install Python Dependencies:
    • Objective: Ensures all required libraries and packages are available for the test scripts to run successfully.
  10. Run Tests:
    • Objective: Executes Selenium tests against the locally running application, identifying potential UI or functional issues.
  11. Upload HTML Report:
    • Objective: Provides an easy-to-read HTML format report for reviewing test results directly from the GitHub interface.
  12. Upload XML Report:
    • Objective: Supplies detailed test results in XML format, useful for integration with test management systems or further analysis.

By setting up parallel workflows (one for Chrome, another for Firebase), you achieve effective cross-browser testing for each pull request, running tests in isolated containers before merging to master. This ensures that only thoroughly tested code is merged, significantly reducing potential issues.

Comprehensive Deployment Workflow: Automating Reliable and Efficient Website Deployments

This detailed DevOps automation example illustrates how to reliably deploy code changes to production. The workflow automatically triggers upon merging new code into the main branch, ensuring minimal downtime through structured steps, providing stability and reliability:

  1. Maintenance Mode: Activates maintenance mode to inform users about ongoing updates.
  2. Server Shutdown & Update: Gracefully stops the running server, ensures no residual processes, and pulls the latest code from the repository.
  3. Application Build: Installs dependencies and builds the latest version of the application.
  4. Server Restart: Restarts the application server using PM2 to ensure the application is live again.
  5. Disable Maintenance Mode: Removes the maintenance notification, returning the website to normal operation.
name: Deploy Website

on:
  push:
    branches:
      - main

jobs:
  set_maintenance:
    runs-on: ubuntu-latest
    steps:
      - name: Set maintenance mode
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            touch /var/www/maintenance.flag
            echo "Maintenance mode enabled."

  stop_server:
    runs-on: ubuntu-latest
    needs: set_maintenance
    steps:
      - name: Stop the server and fetch the latest code
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd ~/repo/resume
            export PATH=/root/.nvm/versions/node/v23.6.0/bin:$PATH
            nvm alias default 23
            pm2 stop so-website || true
            PID=$(sudo netstat -tulnp | grep :3000 | awk '{print $7}' | cut -d'/' -f1)
            if [ -n "$PID" ]; then
              sudo kill -9 $PID
            fi
            rm -rf .next
            git pull origin main

  build:
    runs-on: ubuntu-latest
    needs: stop_server
    steps:
      - name: Build the app
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd ~/repo/resume
            export PATH=/root/.nvm/versions/node/v23.6.0/bin:$PATH
            nvm alias default 23
            yarn install
            yarn build

  start_server:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Start the app
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd ~/repo/resume
            export PATH=/root/.nvm/versions/node/v23.6.0/bin:$PATH
            if ! command -v pm2 &> /dev/null; then
              npm install -g pm2
            fi
            pm2 start yarn --name "so-website" -- start
            pm2 save

  disable_maintenance:
    runs-on: ubuntu-latest
    needs: start_server
    steps:
      - name: Disable maintenance mode
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            rm -f /var/www/maintenance.flag
            echo "Maintenance mode disabled."
Enter fullscreen mode Exit fullscreen mode

Practical Implementation

I've proactively implemented all these GitHub Actions workflows for my personal website (serhatozdursun.com). You can find the repositories here:

These workflows ensure code quality, robust testing, and seamless deployments, significantly enhancing the overall reliability and maintainability of the project.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

If you found this article helpful, a little ❤️ or a friendly comment would be much appreciated!

Got it