diff --git a/.github/workflows/consumer-tests-pr.yml b/.github/workflows/consumer-tests-pr.yml deleted file mode 100644 index f1aaa3fd1b..0000000000 --- a/.github/workflows/consumer-tests-pr.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Consumer tests (Pull Request) - -on: - issue_comment: - types: - - created - - edited - -jobs: - consumer_tests: - name: Consumer tests - if: | - ( - github.event.comment.body == '/it' || - github.event.comment.body == '/it-consumer' - ) && ( - github.event.comment.author_association == 'COLLABORATOR' || - github.event.comment.author_association == 'OWNER' || - github.event.comment.author_association == 'MEMBER' - ) - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: styfle/cancel-workflow-action@0.11.0 - - name: Get pull request URL - id: pull_request - run: | - echo "pull_request=$(curl ${{ github.event.comment.issue_url }} | - jq '.pull_request.url' | - sed 's/\"//g')" >> "$GITHUB_OUTPUT" - - name: Get repository - id: repository - run: | - echo "repository=$(curl ${{ steps.pull_request.outputs.pull_request }} | - jq '.head.repo.full_name' | - sed 's/\"//g')" >> "$GITHUB_OUTPUT" - - name: Get branch name - id: branch_name - run: | - echo "branch_name=$(curl ${{ steps.pull_request.outputs.pull_request }} | - jq '.head.ref' | - sed 's/\"//g')" >> "$GITHUB_OUTPUT" - - uses: actions/checkout@v4 - with: - repository: ${{ steps.repository.outputs.repository }} - ref: ${{ steps.branch_name.outputs.branch_name }} - - uses: actions/setup-java@v4 - with: - java-version: 11 - distribution: zulu - - name: Install Groovy - run: | - sudo apt-get update - sudo apt-get install groovy -y - - name: Setup Git - run: | - git config --global user.email "piper-testing-bot@example.com" - git config --global user.name "piper-testing-bot" - - name: Run tests - env: - REPOSITORY_UNDER_TEST: ${{ github.repository }} - BRANCH_NAME: ${{ github.ref_name }} - BUILD_WEB_URL: https://github.com/SAP/jenkins-library/actions/runs/${{ github.run_id }} - INTEGRATION_TEST_VOTING_TOKEN: ${{ secrets.INTEGRATION_TEST_VOTING_TOKEN }} - CX_INFRA_IT_CF_USERNAME: ${{ secrets.CX_INFRA_IT_CF_USERNAME }} - CX_INFRA_IT_CF_PASSWORD: ${{ secrets.CX_INFRA_IT_CF_PASSWORD }} - NEO_DEPLOY_USERNAME: ${{ secrets.NEO_DEPLOY_USERNAME }} - NEO_DEPLOY_PASSWORD: ${{ secrets.NEO_DEPLOY_PASSWORD }} - CX_INFRA_IT_TMS_UPLOAD: ${{ secrets.CX_INFRA_IT_TMS_UPLOAD }} - run: | - cd ./consumer-test - groovy consumerTestController.groovy diff --git a/.github/workflows/consumer-tests.yml b/.github/workflows/consumer-tests.yml deleted file mode 100644 index ca4cdb0471..0000000000 --- a/.github/workflows/consumer-tests.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Consumer tests - -on: - push: - branches: - - master - - it/** - -jobs: - consumer_tests: - name: Consumer tests - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: styfle/cancel-workflow-action@0.11.0 - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - java-version: 11 - distribution: zulu - - name: Install Groovy - run: | - sudo apt-get update - sudo apt-get install groovy -y - - name: Setup Git - run: | - git config --global user.email "piper-testing-bot@example.com" - git config --global user.name "piper-testing-bot" - - name: Run tests - env: - REPOSITORY_UNDER_TEST: ${{ github.repository }} - BRANCH_NAME: ${{ github.ref_name }} - BUILD_WEB_URL: https://github.com/SAP/jenkins-library/actions/runs/${{ github.run_id }} - INTEGRATION_TEST_VOTING_TOKEN: ${{ secrets.INTEGRATION_TEST_VOTING_TOKEN }} - CX_INFRA_IT_CF_USERNAME: ${{ secrets.CX_INFRA_IT_CF_USERNAME }} - CX_INFRA_IT_CF_PASSWORD: ${{ secrets.CX_INFRA_IT_CF_PASSWORD }} - NEO_DEPLOY_USERNAME: ${{ secrets.NEO_DEPLOY_USERNAME }} - NEO_DEPLOY_PASSWORD: ${{ secrets.NEO_DEPLOY_PASSWORD }} - CX_INFRA_IT_TMS_UPLOAD: ${{ secrets.CX_INFRA_IT_TMS_UPLOAD }} - run: | - cd ./consumer-test - groovy consumerTestController.groovy diff --git a/consumer-test/TestRunnerThread.groovy b/consumer-test/TestRunnerThread.groovy deleted file mode 100644 index 23856c5f1b..0000000000 --- a/consumer-test/TestRunnerThread.groovy +++ /dev/null @@ -1,145 +0,0 @@ -@Grab('org.yaml:snakeyaml:1.17') - -import org.yaml.snakeyaml.Yaml - -class TestRunnerThread extends Thread { - - static def workspacesRootDir - static def libraryVersionUnderTest - static def repositoryUnderTest - - Process currentProcess - final StringBuilder stdOut = new StringBuilder() - final StringBuilder stdErr = new StringBuilder() - int lastPrintedStdOutLine = -1 - public def returnCode = -1 - public def lastCommand - def area - def testCase - def uniqueName - def testCaseRootDir - def testCaseWorkspace - def testCaseConfig - - TestRunnerThread(File testCaseFile) { - this.testCaseConfig = new Yaml().load(testCaseFile.text) - if (!System.getenv(testCaseConfig.deployCredentialEnv.username) || - !System.getenv(testCaseConfig.deployCredentialEnv.password)) { - throw new RuntimeException("Environment variables '${testCaseConfig.deployCredentialEnv.username}' and '${testCaseConfig.deployCredentialEnv.password}' need to be set.") - } - // Regex pattern expects a folder structure such as '/rootDir/areaDir/testCase.extension' - def testCaseMatches = (testCaseFile.toString() =~ - /^[\w\-]+\\/([\w\-]+)\\/([\w\-]+)\..*\u0024/) - this.area = testCaseMatches[0][1] - this.testCase = testCaseMatches[0][2] - if (!area || !testCase) { - throw new RuntimeException("Expecting file structure '/rootDir/areaDir/testCase.yml' " + - "but got '${testCaseFile}'.") - } - this.uniqueName = "${area}|${testCase}" - this.testCaseRootDir = new File("${workspacesRootDir}/${area}/${testCase}") - this.testCaseWorkspace = "${testCaseRootDir}/workspace" - } - - void run() { - println "[INFO] Test case '${uniqueName}' launched." - - if (testCaseRootDir.exists() || !testCaseRootDir.mkdirs()) { - throw new RuntimeException("Creation of dir '${testCaseRootDir}' failed.") - } - - executeShell("git clone -b ${testCaseConfig.referenceAppRepo.branch} " + - "${testCaseConfig.referenceAppRepo.url} ${testCaseWorkspace}") - - addJenkinsYmlToWorkspace() - setLibraryVersionInJenkinsfile() - - //Commit the changed version because artifactSetVersion expects the git repo not to be dirty - executeShell(["git", "-C", "${testCaseWorkspace}", "commit", "--all", - '--author="piper-testing-bot "', - '--message="Set piper lib version for test"']) - - executeShell("docker run --rm -v /var/run/docker.sock:/var/run/docker.sock " + - "-v ${System.getenv('PWD')}/${testCaseWorkspace}:/workspace -v /tmp " + - "-e CASC_JENKINS_CONFIG=/workspace/jenkins.yml " + - "-e ${testCaseConfig.deployCredentialEnv.username} " + - "-e ${testCaseConfig.deployCredentialEnv.password} " + - "-e LIBRARY_VERSION_UNDER_TEST=${libraryVersionUnderTest} " + - "-e REPOSITORY_UNDER_TEST=${repositoryUnderTest} " + - "-e BRANCH_NAME=${testCaseConfig.referenceAppRepo.branch} ppiper/jenkinsfile-runner") - - println "*****[INFO] Test case '${uniqueName}' finished successfully.*****" - printOutput() - } - - // Configure path to library-repository under test in Jenkins config - private void addJenkinsYmlToWorkspace() { - def sourceFile = 'jenkins.yml' - def sourceText = new File(sourceFile).text.replaceAll( - '__REPO_SLUG__', repositoryUnderTest) - def target = new File("${testCaseWorkspace}/${sourceFile}") - target.write(sourceText) - } - - // Force usage of library version under test by setting it in the Jenkinsfile, - // which is then the first definition and thus has the highest precedence. - private void setLibraryVersionInJenkinsfile() { - def jenkinsfile = new File("${testCaseWorkspace}/Jenkinsfile") - def manipulatedText = - "@Library(\"piper-lib-os@${libraryVersionUnderTest}\") _\n" + - jenkinsfile.text - jenkinsfile.write(manipulatedText) - } - - private void executeShell(command) { - lastCommand = command - def startOfCommandString = "Shell command: '${command}'\n" - stdOut << startOfCommandString - stdErr << startOfCommandString - - currentProcess = command.execute() - currentProcess.waitForProcessOutput(stdOut, stdErr) - - returnCode = currentProcess.exitValue() - - currentProcess = null - - if (returnCode > 0) { - throw new ReturnCodeNotZeroException("Test case: [${uniqueName}]; " + - "shell command '${command} exited with return code '${returnCode}") - } - } - - void printOutput() { - println "\n[INFO] stdout output from test case ${uniqueName}:" - stdOut.eachLine { line, i -> - println "${i} [${uniqueName}] ${line}" - lastPrintedStdOutLine = i - } - - println "\n[INFO] stderr output from test case ${uniqueName}:" - stdErr.eachLine { line, i -> - println "${i} [${uniqueName}] ${line}" - } - } - - public void printRunningStdOut() { - stdOut.eachLine { line, i -> - if (i > lastPrintedStdOutLine) { - println "${i} [${uniqueName}] ${line}" - lastPrintedStdOutLine = i - } - } - } - - @Override - public String toString() { - return uniqueName - } -} - -class ReturnCodeNotZeroException extends Exception { - ReturnCodeNotZeroException(message) { - super(message) - } -} diff --git a/consumer-test/consumerTestController.groovy b/consumer-test/consumerTestController.groovy deleted file mode 100644 index a6f3517008..0000000000 --- a/consumer-test/consumerTestController.groovy +++ /dev/null @@ -1,231 +0,0 @@ -import groovy.io.FileType - -import static groovy.json.JsonOutput.toJson - -COMMIT_HASH = null -RUNNING_LOCALLY = false -AUXILIARY_SLEEP_MS = 10000 -START_TIME_MS = System.currentTimeMillis() -WORKSPACES_ROOT = 'workspaces' -TEST_CASES_DIR = 'testCases' -LIBRARY_VERSION_UNDER_TEST = "git log --format=%H -n 1".execute().text.trim() -REPOSITORY_UNDER_TEST = System.getenv('REPOSITORY_UNDER_TEST') ?: System.getenv('TRAVIS_REPO_SLUG') ?: 'SAP/jenkins-library' -BRANCH_NAME = System.getenv('TRAVIS_BRANCH') ?: System.getenv('BRANCH_NAME') - -EXCLUDED_FROM_CONSUMER_TESTING_REGEXES = [ - /^documentation\/.*$/, - /^.travis.yml$/, - /^test\/.*$/ -] - -println "Running tests for repository: ${REPOSITORY_UNDER_TEST}, branch: ${BRANCH_NAME}, commit: ${LIBRARY_VERSION_UNDER_TEST}" - -newEmptyDir(WORKSPACES_ROOT) -TestRunnerThread.workspacesRootDir = WORKSPACES_ROOT -TestRunnerThread.libraryVersionUnderTest = LIBRARY_VERSION_UNDER_TEST -TestRunnerThread.repositoryUnderTest = REPOSITORY_UNDER_TEST - -def testCaseThreads -def cli = new CliBuilder( - usage: 'groovy consumerTestController.groovy []', - header: 'Options:', - footer: 'If no options are set, all tests are run centrally, i.e. on travisCI.') - -cli.with { - h longOpt: 'help', 'Print this help text and exit.' - l longOpt: 'run-locally', 'Run consumer tests locally in Docker, i.e. skip reporting of GitHub status.' - s longOpt: 'single-test', args: 1, argName: 'filePath', 'Run single test.' -} - -def options = cli.parse(args) - -if (options.h) { - cli.usage() - return -} - -if (options.l) { - RUNNING_LOCALLY = true -} - -if (!RUNNING_LOCALLY) { - /* - In case the build is performed for a pull request TRAVIS_COMMIT is a merge - commit between the base branch and the PR branch HEAD. That commit is actually built. - But for notifying about a build status we need the commit which is currently - the HEAD of the PR branch. - - In case the build is performed for a simple branch (not associated with a PR) - In this case there is no merge commit between any base branch and HEAD of a PR branch. - The commit which we need for notifying about a build status is in this case simply - TRAVIS_COMMIT itself. - */ - COMMIT_HASH = System.getenv('TRAVIS_PULL_REQUEST_SHA') ?: System.getenv('TRAVIS_COMMIT') ?: LIBRARY_VERSION_UNDER_TEST - - if (changeDoesNotNeedConsumerTesting()) { - println 'No consumer tests necessary.' - notifyGithub("success", "No consumer tests necessary.") - return - } else { - notifyGithub("pending", "Consumer tests are in progress.") - } -} - -if (options.s) { - def file = new File(options.s) - if (!file.exists()) { - exitPrematurely("Test case configuration file '${file}' does not exist. " + - "Please provide path to a configuration file of structure '/rootDir/areaDir/testCase.yml'.") - } - testCaseThreads = [new TestRunnerThread(file)] -} else { - testCaseThreads = listTestCaseThreads() -} - -testCaseThreads.each { it -> - it.start() -} - -//The thread below will print to console while the test cases are running. -//Otherwise the job would be canceled after 10 minutes without output. -def done = false -Thread.start { - def outputWasPrintedPrematurely = false - def singleTestCase = (testCaseThreads.size() == 1) - if (singleTestCase) { - AUXILIARY_SLEEP_MS = 1000 //for a single test case we print the running output every second - } - for (; ;) { - if (singleTestCase) { - testCaseThreads[0].printRunningStdOut() - } else { - println "[INFO] Consumer tests are still running." - } - - // Build is killed at 50 min, print log to console at minute 45 - int MINUTES_SINCE_START = (System.currentTimeMillis() - START_TIME_MS) / (1000 * 60) - if (!singleTestCase && MINUTES_SINCE_START > 44 && !outputWasPrintedPrematurely) { - testCaseThreads.each { thread -> - thread.printOutput() - } - outputWasPrintedPrematurely = true - } - - sleep(AUXILIARY_SLEEP_MS) - if (done) { - break - } - } -} - -testCaseThreads.each { it -> - it.join() -} -done = true - -def failedThreads = testCaseThreads.findAll { thread -> - thread.returnCode != 0 -} - -def status -def statusMessage -if (failedThreads.size() == 0) { - status = "success" - statusMessage = "All consumer tests finished successfully. Congratulations!" -} else { - failedThreads.each { failedThread -> - println "[ERROR] ${failedThread.uniqueName}: Process execution of command: '${failedThread.lastCommand}' failed. " + - "Return code: ${failedThread.returnCode}." - failedThread.printOutput() - } - status = "failure" - statusMessage = "The following consumer test(s) failed: ${failedThreads}" -} - -if (!RUNNING_LOCALLY) { - notifyGithub(status, statusMessage) -} - -println statusMessage - -if (status == "failure") { - System.exit(1) -} - - -def listTestCaseThreads() { - //Each dir that includes a yml file is a test case - def threads = [] - new File(TEST_CASES_DIR).traverse(type: FileType.FILES, nameFilter: ~/^.+\.yml\u0024/) { file -> - threads << new TestRunnerThread(file) - } - return threads -} - -def notifyGithub(state, description) { - println "[INFO] Notifying about state '${state}' for commit '${COMMIT_HASH}'." - - URL url = new URL("https://api.github.com/repos/SAP/jenkins-library/statuses/${COMMIT_HASH}") - HttpURLConnection con = (HttpURLConnection) url.openConnection() - con.setRequestMethod('POST') - con.setRequestProperty("Content-Type", "application/json; utf-8"); - con.setRequestProperty('User-Agent', 'groovy-script') - con.setRequestProperty('Authorization', "token ${System.getenv('INTEGRATION_TEST_VOTING_TOKEN')}") - - def postBody = [ - state : state, - target_url : System.getenv('TRAVIS_BUILD_WEB_URL') ?: System.getenv('BUILD_WEB_URL'), - description: description, - context : "integration-tests" - ] - - con.setDoOutput(true) - con.getOutputStream().withStream { os -> - os.write(toJson(postBody).getBytes("UTF-8")) - } - - int responseCode = con.getResponseCode() - if (responseCode != HttpURLConnection.HTTP_CREATED) { - exitPrematurely("[ERROR] Posting status to github failed. Expected response code " + - "'${HttpURLConnection.HTTP_CREATED}', but got '${responseCode}'. " + - "Response message: '${con.getResponseMessage()}'", - 34) // Error code taken from curl: CURLE_HTTP_POST_ERROR - } -} - -def changeDoesNotNeedConsumerTesting() { - if (BRANCH_NAME == 'master') { - return false - } - - def excludesRegex = '(' + EXCLUDED_FROM_CONSUMER_TESTING_REGEXES.join('|') + ')' - - "git remote add sap https://github.com/SAP/jenkins-library.git".execute().waitFor() - "git fetch sap".execute().waitFor() - def diff = "git diff --name-only sap/master ${LIBRARY_VERSION_UNDER_TEST}".execute().text.trim() - - for (def line : diff.readLines()) { - if (!(line ==~ excludesRegex)) { - return false - } - } - - return true -} - -static def newEmptyDir(String dirName) { - def dir = new File(dirName) - if (dir.exists()) { - if (!dir.deleteDir()) { - exitPrematurely("Deletion of dir '${dirName}' failed.") - } - } - if (!dir.mkdirs()) { - exitPrematurely("Creation of dir '${dirName}' failed.") - } -} - -static def exitPrematurely(String message, int returnCode = 1) { - println message - System.exit(returnCode) -} diff --git a/consumer-test/jenkins.yml b/consumer-test/jenkins.yml deleted file mode 100644 index b659df9d19..0000000000 --- a/consumer-test/jenkins.yml +++ /dev/null @@ -1,39 +0,0 @@ -jenkins: - numExecutors: 10 -unclassified: - globallibraries: - libraries: - - defaultVersion: "master" - name: "piper-lib-os" - retriever: - modernSCM: - scm: - git: - remote: "https://github.com/__REPO_SLUG__.git" -credentials: - system: - domainCredentials: - - credentials: - - usernamePassword: - scope: GLOBAL - id: "devops-docker-images-IT-cf" - username: ${CX_INFRA_IT_CF_USERNAME} - password: ${CX_INFRA_IT_CF_PASSWORD} - description: "SAP CP Trail account for test deployment" - - usernamePassword: - scope: GLOBAL - id: "neo_deploy" - username: ${NEO_DEPLOY_USERNAME} - password: ${NEO_DEPLOY_PASSWORD} - description: "SAP CP NEO Trail account for test deployment" - - usernamePassword: - scope: GLOBAL - id: "cf_deploy" - username: ${CX_INFRA_IT_CF_USERNAME} - password: ${CX_INFRA_IT_CF_PASSWORD} - description: "SAP CP CF Trial account for test deployment" - - string: - scope: GLOBAL - id: "tmsUpload" - secret: ${CX_INFRA_IT_TMS_UPLOAD} - description: "Service key for tms upload" diff --git a/consumer-test/testCases/scs/cap.yml b/consumer-test/testCases/scs/cap.yml deleted file mode 100644 index f835101075..0000000000 --- a/consumer-test/testCases/scs/cap.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Test case configuration -referenceAppRepo: - url: "https://github.com/piper-validation/mta-sample-app.git" - branch: "piper-test-cap" -deployCredentialEnv: - username: "CX_INFRA_IT_CF_USERNAME" - password: "CX_INFRA_IT_CF_PASSWORD" diff --git a/consumer-test/testCases/scs/ui5-neo.yml b/consumer-test/testCases/scs/ui5-neo.yml deleted file mode 100644 index 412ad3681a..0000000000 --- a/consumer-test/testCases/scs/ui5-neo.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Test case configuration -referenceAppRepo: - url: "https://github.com/piper-validation/openui5-sample-app.git" - branch: "piper-test-ui5-neo" -deployCredentialEnv: - username: "NEO_DEPLOY_USERNAME" - password: "NEO_DEPLOY_PASSWORD" diff --git a/consumer-test/testCases/tms/tmsUpload.yml b/consumer-test/testCases/tms/tmsUpload.yml deleted file mode 100644 index f3a177583e..0000000000 --- a/consumer-test/testCases/tms/tmsUpload.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Test case configuration -referenceAppRepo: - url: "https://github.com/piper-validation/tmsUpload.git" - branch: "master" -deployCredentialEnv: - username: "CX_INFRA_IT_TMS_UPLOAD" - password: "CX_INFRA_IT_TMS_UPLOAD"