Integrating GitHub, Jenkins, and ngrok for Continuous Integration on WSL in Windows

2024-07-21




Prerequisite

you already have jenkins installed and set it up in WSL.

Setting up Jenkins

start jenkins

sudo systemctl start jenkins

check status of jenkins

sudo systemctl status jenkins

check the jenkins in browsers

in url, type http://<your_wsl_ip>:8080/

browser will display jenkins login page

Login ngrok

copy authtoken

Install ngrok

https://ngrok.com/download

select Linux

install ngrok vis apt

 curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrok

add authtoken

./ngrok authtoken <your_token>

set up your jenkins port

./ngrok http 8080

later ngrok will show your public url

https://9ee3-39-15-48-66.ngrok-free.app/

Setting Up Github Webhooks

  • go to your target repository
  • go to its settings
  • Click Webhooks on the left panel
  • click Add webhook on the top-right corner
  • settings
    • Payload URL
      • https://9ee3-39-15-48-66.ngrok-free.app/github-webhook/
    • Content type
      • application/x-www-form-urlencoded
    • Secret
      • leave it blank
    • SSL verification
      • Enable SSL verification
    • Events
      • Just the push event
    • Active
      • active
  • after the settings are finished, Webhooks will ping you url, if the connection is success, it will show check mark, if the connection is failed, it will show red cross mark
  • In Recent Deliveries you can see the push record

Setting up Jenkins

  • add New Item
  • Setting Up Your GitHub project
  • setting up Build Triggers
  • setting up pipeline

save the pipeline

  • first time manually click Build Now
  • after that, everytime you push a commit on github, it will automatically trigger this pipeline
  • note that if you have other jenkins project link to the same repository and same branch, which also has GitHub hook trigger for gitscm polling checked, the push will trigger all of them, which will lead to port already in use error if your jenkinsfile have it.

jenkinsfile

// Defines the Jenkins pipeline
pipeline {
    // the pipeline can run on any available Jenkins agent
    agent any

    environment {
        // Define environment variables for the virtual environment directory, pip, and python executables
        VENV_DIR = '/var/lib/jenkins/envs/venv' // virtual environment directory path
        PIP = "${VENV_DIR}/bin/pip"             // the path to the pip executable
        PYTHON = "${VENV_DIR}/bin/python"       // the path to the python executable
    }

    stages {
        stage('Setup') {
            // Purpose: Ensure a clean workspace to avoid issues from previous builds
            steps {
                script {
                    // Clean the workspace to ensure a fresh start
                    cleanWs()
                }
            }
        }

        stage('Checkout') {
            // Purpose: Retrieve the latest code from the specified branch in the Git repository
            steps {
                // Checkout the code from your repository
                git branch: 'dev', url: 'https://github.com/shuminchang/codemy_blog.git'
            }
        }

        stage('Install Dependencies') {
            // Purpose: Set up the necessary Python environment by upgrading pip and installing required dependencies
            steps {
                script {
                    // Upgrade pip and install the required dependencies from requirements.txt
                    sh """
                    ${PIP} install --upgrade pip
                    ${PIP} install -r requirements.txt
                    """
                }
            }
        }

        stage('Run Server') {
            // Purpose: Start the Django development server to run tests against it
            steps {
                script {
                    // Ensure the port 8002 is not already in use
                    sh """
                    if lsof -i:8002; then
                        echo "Port 8002 is already in use. Existing."
                        exit 1
                    fi
                    """
                    // Start the Django development server in the background and save the process ID
                    sh """
                    ${PYTHON} manage.py runserver 8002 > server_log.txt 2>&1 &
                    echo \$! > server_pid.txt
                    """
                }
            }
        }

        stage('Run Tests') {
            // Purpose: Execute the test suite to verify the integrity of the application
            steps {
                script {
                    // Give the server some time to start
                    sleep 10

                    // Check if the server started correctly using the saved process ID
                    def server_pid = readFile('server_pid.txt').trim()
                    if (sh(returnStatus: true, script: "ps -p ${server_pid}") != 0) {
                        echo "Django server failed to start. Check server_log.txt for details."
                        sh 'cat server_log.txt'
                        error "Django server failed to start."      // mark the build as failed if the server did not start
                    } else {
                        // Run tests if the server started correctly
                        sh "${PYTHON} manage.py test" 
                    }
                }
            }
        }

        stage('Cleanup') {
            // Purpose: Stop the Django development server and clean up the environment
            steps {
                script {
                    // Terminate the Django development server if it is still running
                    def server_pid = readFile('server_pid.txt').trim()
                    sh """
                    if ps -p ${server_pid} > /dev/null; then
                        kill ${server_pid}
                    fi
                    """
                }
            }
        }
    }

    // Defines actions that always run after the stages
    post {
        always {
            // Purpose: Ensure the server log is archived after the build, regradless of the result
            archiveArtifacts artifacts: 'server_log.txt', allowEmptyArchive: true
        }
        cleanup {
            // Purpose: Ensure the workspace is cleaned up after the build
            cleanWs()
        }
    }
}

 







Login to like - 0 Likes



Comments...


No Comments Yet...



Add Comment...




Footer with Icons