Jenkins CI Example

The following is a full example of using Modality in a Jenkins CI pipeline. The pipeline includes these steps:

  1. Build the example app, then copy the resulting binaries and SUT definition files, as well as the Modality CLI, to the Jenkins agent.

    • For this app, the SUT.toml SUT manifest file is in the source tree of the app.
    • Note that in this example we copy the modality CLI binary from our build container to the Jenkins agent since we have the entire contents of the Modality tarball in the build container. You could also copy the CLI from the modality-sdk container with the following commands:
    mkdir -p bin
    docker create --name sdk-files modality-sdk
    docker cp modality-sdk:/modality/bin/modality bin/
    docker rm sdk-files
    
  2. Run the modalityd container, clean up any previous SUT or session, then create the example-sut and open a session.

  3. Run the example SUT.

  4. Check our test suite to get a report, kill the modalityd container, and then save the report and Modality's data-dir as artifacts.

pipeline {
    agent any

    environment {
        PATH = "./bin:${env.PATH}"
    }

    stages {
        stage('Build modality C example') {
            steps {
                sh '''
                    docker build -f docker/Dockerfile-builder -t modality-c-example-builder .

                    docker create --name builder-files modality-c-example-builder
                    docker cp builder-files:/src/consumer-component .
                    docker cp builder-files:/src/producer-component .
                    docker cp builder-files:/src/monitor-component .

                    mkdir -p bin
                    docker cp builder-files:/src/build/producer bin/
                    docker cp builder-files:/src/build/consumer bin/
                    docker cp builder-files:/src/build/monitor bin/

                    docker cp builder-files:/usr/local/modality/bin/modality bin/
                    # Alternative to above - copy from modality-sdk container rather than build container
                    # mkdir -p bin
                    # docker create --name sdk-files modality-sdk
                    # docker cp modality-sdk:/modality/bin/modality bin/
                    # docker rm sdk-files

                    docker rm builder-files
                '''
            }
        }

        stage('Set up modality') {
            steps {
                dir('modality-data-dir') { }
                sh '''
                    docker run \
                        --name modalityd \
                        -v "$(pwd)/modality-data-dir:/data-dir" \
                        --network=host \
                        -e ACCEPT_EULA=Y \
                        -d --rm \
                        ghcr.io/auxoncorp/modalityd:latest
                '''

                sh '''
                    modality sut delete example-sut --force || true
                    modality session delete ci-session --force || true
                    modality sut create .
                    modality session open ci-session example-sut
                '''

            }
        }

        stage('Run the c-example') {
            steps {
                sh './scripts/run-example'
            }
        }

        stage('Modality analysis and teardown') {
            steps {
                sh '''
                    modality session close ci-session
                    modality check --suite ci-check-suite.toml --using ci-session --format html > modality-ci-report.html
                '''

                sh 'docker kill modalityd'
                sh 'tar czf modality-data-dir.tar.gz modality-data-dir/'

                archiveArtifacts artifacts: 'modality-ci-report.html'
                archiveArtifacts artifacts: 'modality-data-dir.tar.gz'
            }
        }
    }
    post {
        always {
            sh 'docker kill modalityd'
        }
    }
}