Трубопровод Дженкинса: ждать, пока другая работа остановится - PullRequest
0 голосов
/ 06 марта 2020

У меня есть несколько проектов тестирования (тесты API, тесты UI Selenium и т. Д. c), которые тестируют одно и то же приложение. На данный момент шаги приложения. Развертывание дублируется в каждом файле jenkins.

Цель состоит в том, чтобы иметь общее задание app-deploy , которое подготавливает приложение на сервере:

  • Извлекает из определенной ревизии или тега;
  • Определяет множество переменных среды, таких как лицензии и т. Д .;
  • Создает файлы WAR;
  • Копирует их в каталог сборки Tomcat;
  • Запускает Tomcat и ожидает готовности контекста.

Я не могу просто завершить сборку sh после этого, так как Jenkins убьет все созданные процессы, включая запущенный Tomcat. Я попытался doNoKillMe cook ie для Tomcat, но это вызвало несколько других проблем, связанных с перезапуском приложения и подключений к БД. Итак, я поставил шаг input с идентификатором, когда приложение готово:

node {
    properties([
            parameters([
                    string(name: 'REVISION',
                            defaultValue: '',
                    ),
                    string(name: 'TAG_NAME',
                            defaultValue: ''),
            ]),
    ])
    withEnv(buildEnvVariables()) {
        stage('Checkout') {
        }

        stage('Prepare file system') {
        }

        stage('Prepare database') {
        }

        stage('Builds WAR files') {
        }

        stage('Tomcat deploy') {
            // Delete previous WAR files from Tomcat
            // Copy generated files to tomcat
            sh "$TOMCAT_DIR/bin/startup.sh"
            waitForTokenFileOrFail()
        }
        input(id: 'IsBuilt', 'Application is ready... ')
    }
}

Теперь я хочу, чтобы это задание вызывалось из нескольких других testing-speci c jenkins files:

node {
    properties([
            parameters([
                    string(name: 'TESTS_SUITE',
                            defaultValue: '',
                    ),
                    string(name: 'OTHER_PARAM',
                            defaultValue: ''),
            ]),
    ])
    withEnv(buildEnvVariables()) {
        stage('Checkout') {
        }

        stage('Stop any running application builds') {
            def jenkinsQueue = Jenkins.instance.queue
            jenkinsQueue.items.findAll { it.task.name.startsWith(contextDeployBuildName) }.each {
                echo "Found pending $contextDeployBuildName job. Cancelling: ${it.getId()}"
                jenkinsQueue.doCancelItem(it.getId())
            }

            Jenkins.instance.getItemByFullName(contextDeployBuildName)
                    .getAllJobs().first().getBuilds()
                    ?.each { build ->
                        if (build.isBuilding()) {
                            try {
                                echo "Found running $contextDeployBuildName job. Stopping: ${build.number}"
                                httpRequest(
                                        httpMode: 'POST',
                                        authentication: 'credentialsID',
                                        url: "${JENKINS_URL}job/$contextDeployBuildName/${build.number}/stop")
                            } catch (any) {
                                println any.message
                            }
                        }
                    }
        }

        stage('Build the app') {
            build(wait: true, job: contextDeployBuildName, parameters: [
                    string(name: 'REVISION', value: env.BRANCH_NAME),
                    string(name: 'TAG_NAME', value: env.TAG_NAME)])

            // How to wait for a specific input/condition here???
        }

        stage('Run tests') {
        }

        stage('Report, cleanup') {
        }
    }
}

Я использую jenkins build step с условием wait, но кажется, что он может ждать только до завершения работы sh. Изменение статуса задания развертывания игнорируется (я верю, потому что слушатели сборки не запускаются):

currentBuild.rawBuild.@result = hudson.model.Result.SUCCESS

Вопрос:

Как правильно сообщить в спецификацию тестирования c о сработавшем вводе в app-deploy * job? Существует ли стандартный способ решения такой проблемы «тестирования развертывания»?

Пока у меня есть два уродливых способа проверить состояние, кроме инструментов конвейера:

  1. Дождаться какого-то определенного c файла в папках Tomcat / application
  2. Когда ввод с указанным идентификатором инициируется, доступ к его странице можно получить через этот идентификатор, поэтому я могу пропинговать страницу ввода, пока она не вернет 200 статус вместо 404.

1 Ответ

2 голосов
/ 10 марта 2020

Немного истории: несколько лет go были регулярные задания Дженкинса, и люди привыкли видеть их как строительные блоки и запускать одно из другого. Это было не очень удобно, короче говоря, родился конвейер.

Конвейеры не должны запускать друг друга, потому что, если у вас так много зависимости между двумя вашими работами, где нужно ждать и подайте сигнал другому, возможно, было бы лучше рассматривать их как часть одного конвейера.

Дублирование кода - это проблема, но с ней можно бороться, если вы рассматриваете все свои шаги как часть больший трубопровод. Кое-что к мелодии этого (копирование-вставка из вашего кода в декларативный конвейер):

pipeline {
    agent any
    parameters {
        string(name: 'REVISION', defaultValue: '')
        string(name: 'TAG_NAME', defaultValue: '')
        choice(name: 'TEST_SUITE', choices: ['selenium', 'api', 'etc'])
    }
    stages {
        stage('Checkout') {
        }

        stage('Prepare file system') {
        }

        stage('Prepare database') {
        }

        stage('Builds WAR files') {
        }

        stage('Tomcat deploy') { 
        agent { label "tomcat" } 
        steps { script { 
            sh "$TOMCAT_DIR/bin/startup.sh"
        }}}

        // start testing
        stage('Testing') {
            parallel {
                stage('Selenium') {
                    when { equals expected: "selenium", actual: params.TEST_SUITE }}
                    agent { label "selenium-slave" }
                    steps {
                        echo "Doing selenium tests"
                    }
                }
                stage('API') {
                    when { equals expected: "api", actual: params.TEST_SUITE }}
                    agent { label "api-slave" }
                    steps {
                        echo "Doing api tests"
                    }
                }
            }
        }
        stage('Cleanup') { 
        agent { label "tomcat" } 
        steps { script { 
            sh "$TOMCAT_DIR/bin/shutdown.sh"
        }}}
    }
}

Редактировать: это может быть проблемой, из-за которой ваши 'start tomcat' и 'stop tomcat' падают на точно такой же узел, но немного распараллеливания и блок post { } тоже могут решить эту проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...