{"id":15045288,"url":"https://github.com/jenkinsci/ecutest-plugin","last_synced_at":"2025-10-19T21:31:21.550Z","repository":{"id":2514374,"uuid":"43631303","full_name":"jenkinsci/ecutest-plugin","owner":"jenkinsci","description":"This plugin integrates Jenkins with ecu.test and generates reports on automated test execution.","archived":false,"fork":false,"pushed_at":"2025-01-24T07:16:38.000Z","size":6873,"stargazers_count":25,"open_issues_count":15,"forks_count":17,"subscribers_count":101,"default_branch":"master","last_synced_at":"2025-01-24T08:23:04.145Z","etag":null,"topics":["deprecated","ecu-test","embedded-systems","jenkins","jenkins-plugin","testautomation","tracetronic"],"latest_commit_sha":null,"homepage":"https://plugins.jenkins.io/ecutest","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"tracetronic/ecutest-plugin","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jenkinsci.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-10-04T09:30:06.000Z","updated_at":"2024-12-17T10:46:23.000Z","dependencies_parsed_at":"2023-12-19T12:02:40.582Z","dependency_job_id":"7b5d8294-80a7-47a4-8613-d620e6738e83","html_url":"https://github.com/jenkinsci/ecutest-plugin","commit_stats":{"total_commits":865,"total_committers":23,"mean_commits":"37.608695652173914","dds":"0.33179190751445087","last_synced_commit":"c49f825ffcf4988955ac6738d97878fe4fbda01e"},"previous_names":[],"tags_count":68,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fecutest-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fecutest-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fecutest-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fecutest-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jenkinsci","download_url":"https://codeload.github.com/jenkinsci/ecutest-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237215757,"owners_count":19273551,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deprecated","ecu-test","embedded-systems","jenkins","jenkins-plugin","testautomation","tracetronic"],"created_at":"2024-09-24T20:51:41.449Z","updated_at":"2025-10-19T21:31:21.543Z","avatar_url":"https://github.com/jenkinsci.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!--\nSPDX-FileCopyrightText: 2015-2023 tracetronic GmbH \u003cinfo@tracetronic.de\u003e\n\nSPDX-License-Identifier: BSD-3-Clause\n--\u003e\n\n# tracetronic ecu.test plugin\n\n[![Build Status](https://ci.jenkins.io/buildStatus/icon?job=plugins/ecutest-plugin/master)](https://ci.jenkins.io/job/plugins/job/ecutest-plugin/job/master) [![Third Party License Check](https://github.com/jenkinsci/ecutest-plugin/actions/workflows/license.yml/badge.svg)](https://github.com/jenkinsci/ecutest-plugin/actions/workflows/license.yml)  [![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/ecutest.svg)](https://plugins.jenkins.io/ecutest)\n[![Jenkins Release](https://img.shields.io/github/release/jenkinsci/ecutest-plugin.svg?label=changelog)](https://github.com/jenkinsci/ecutest-plugin/releases) [![Plugin Installs](https://img.shields.io/jenkins/plugin/i/ecutest.svg?color=blue)](https://plugins.jenkins.io/ecutest) [![License](https://img.shields.io/badge/license-3--clause%20BSD-blue.svg?style=flat)](https://github.com/jenkinsci/ecutest-plugin/blob/master/LICENSE)\n\n| ⚠️ End of Life ⚠️                 | \n|------------------------------------------|\n| This plugin is deprecated and the support ends at 2024-12-31.    |\n| You can migrate your test execution to [test.guide](https://www.tracetronic.com/products/test-guide/) or still use Jenkins with the [ecu.test Execution Plugin](https://github.com/jenkinsci/ecu-test-execution-plugin).    |\n| After the compatibility update for ecu.test 2024.4 at the end of 2024, there will never be an update for this plugin again - not for compatibility updates and also not for security fixes.    |\n| The plugin will be deleted from the [Update-Center](https://updates.jenkins.io/) at 2026-03-31.    |\n\n\u003cbr/\u003e\u003cbr/\u003e\n\nThis plugin integrates Jenkins with [ecu.test](https://www.tracetronic.com/products/ecu-test) and generates reports on automated test execution.\n\n\u003cimg src=\"docs/images/ecu.test.png\" align=\"left\" alt=\"ecu.test Logo\" style=\"padding-right: 15px;height:150px\"\u003e\n\n**ecu.test** allows for a consistent and effective automation of the entire test environment. It supports and connects so many different software tools, that it easily fits in numerous existing test and validation processes. The test automation tool can be used in all phases of development up to the finished vehicle itself. It allows for a high reusability of the test cases in the various test areas MiL, SiL, HiL, PiL and ViL (vehicle), through generic test description and tool-access abstraction.\n\n\n**ecu.test Jenkins Plugin** project is part of the [Automotive DevOps Platform](https://www.tracetronic.com/products/automotive-devops-platform/) by tracetronic. With the **Automotive DevOps Platform**, we go from the big picture to the details and unite all phases of vehicle software testing – from planning the test scopes to summarizing the test results. At the same time, continuous monitoring across all test phases always provides an overview of all activities – even with several thousand test executions per day and in different test environments.\n\nPlease consider other open-source automation solutions by [tracetronic](https://github.com/tracetronic?type=source), especially [Jenkins Library](https://github.com/tracetronic/jenkins-library) and [CX Templates](https://github.com/tracetronic/cx-templates).\n\n## Table of Contents\n\n- [Features](#features)\n- [Configuration](#configuration)\n    - [ecu.test configuration](#ecutest-configuration)\n    - [test.guide configuration](#testguide-configuration)\n    - [Job configuration](#job-configuration)\n    - [Job execution](#job-execution)\n    - [Environment variables](#environment-variables)\n- [Downstream report generation](#downstream-report-generation)\n    - [Example configurations](#example-configurations)\n- [Downstream trace analysis](#downstream-trace-analysis)\n    - [Example configurations](#example-configurations-1)\n- [Extensions](#extensions)\n    - [Job DSL](#job-dsl)\n    - [Pipeline](#pipeline)\n    - [Configuration as Code](#configuration-as-code)\n- [Debugging](#debugging)\n- [Issues](#issues)\n- [Known limitations](#known-limitations)\n- [FAQ](#faq)\n- [Compatibility](#compatibility)\n- [License](#license)\n- [Changelog](#changelog)\n\n## Features\n\n- Provides an easy integration and control of ecu.test and the Tool-Server with Jenkins\n- Enables the execution of ecu.test packages and projects with their respective configurations\n\nMoreover publishing test results is included in form of:\n\n- Linking the TRF reports\n- Generating various report formats\n- Displaying test result trend graphs\n- Uploading ATX test reports to [test.guide](https://www.tracetronic.com/products/test-guide)\n- Parsing the ecu.test logs for warnings and errors\n\nAdvanced workflows integrated for:\n\n- [Downstream report generation](#downstream-report-generation)\n- [Downstream trace analysis](#downstream-trace-analysis)\n\n## Configuration\n\n### ecu.test configuration\n\necu.test installations are administrated in the Jenkins system configuration or starting with Jenkins 2.0 in the global tool configuration at section \"ecu.test\".\nAn installation entry is specified by an arbitrary name and the path to the installation directory.\nThe execution on a Jenkins agent requires the adaption of the ecu.test installation directory on the agent configuration page.\n\n![ecu.test](docs/images/ecutest.png \"ecu.test\")\n![ecu.test_AGENT](docs/images/ecutest2.png \"ecu.test\")\n\n### test.guide configuration\n\ntest.guide is also configured in the Jenkins system configuration at section \"test.guide\".\nA new entry requires both an arbitrary name and the selection of a previously configured ecu.test installation.\nFurther settings like the server or ATX specific configuration can be found in the advanced block.\n\n![test.guide](docs/images/testguide.png \"test.guide\")\n\n### Job configuration\n\nThe plugin provides several new build steps:\n\n![Build Steps](docs/images/build_steps.png \"Build Steps\")\n\n**Note:**\n\n- All build steps have an \"Advanced\" button through which more options can be accessed\n- All text fields can be parameterized and are resolved at build execution\n  - Syntax: _$parameter_ or _${parameter}_\n\nThe post-build actions are extended by these test report related post-build steps:\n\n![Post-Build Steps](docs/images/post_build_steps.png \"Post-Build Steps\")\n\n### Job execution\n\n- After job configuration is done a new build can be triggered by clicking on the \"Build now\" button\n- The test results are published both on the build page and the job page based on the latest build after the step\n  *[TT] Publish UNIT* Reports has been executed.\n- The console log contains detailed information per build step execution.\n\n![Demo Job](docs/images/demo_job.png \"Demo Job\")\n![Demo Build](docs/images/demo_build.png \"Demo Build\")\n![Demo Log](docs/images/demo_log.png \"Demo Log\")\n\n### Environment variables\n\n- This plugin also exposes the tool and test related information of the current build as environment variables.\n- These variables are composed of ${TT_\u003cTOOL | TEST\u003e_\u003cvariable-info\u003e_n} where n is the index of the\n  related build steps in the job configuration, counting from 0.\n- The summary of all generated environment variables is also shown on the build page.\n\n\u003cdetails\u003e\n    \u003csummary\u003eTool related variables\u003c/summary\u003e\n\n| Environment variable | Description |\n| --- | --- |\n| TT_TOOL_NAME | Name of the selected ecu.test installation |\n| TT_TOOL_INSTALL | Full path to related ecu.test executable |\n| TT_TOOL_VERSION | Program version of selected ecu.test installation |\n| TT_TOOL_WORKSPACE | ecu.test workspace directory |\n| TT_TOOL_SETTINGS | ecu.test settings directory |\n| TT_TOOL_DEBUG | ecu.test debug mode |\n| TT_TOOL_TIMEOUT | Maximum execution time |\n| TT_TOOL_LAST_TBC | Last loaded TBC file path |\n| TT_TOOL_LAST_TCF | Last loaded TCF file path |\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eTest related variables\u003c/summary\u003e\n\n| Environment variable | Description |\n| --- | --- |\n| TT_TEST_NAME | Name of the executed test |\n| TT_TEST_FILE | Full path to related test file |\n| TT_TEST_TYPE | Type of related test (PACKAGE, PROJECT) |\n| TT_TEST_DESCRIPTION | Test description |\n| TT_TEST_TBC | Full path to test bench configuration file |\n| TT_TEST_TCF | Full path to test configuration file |\n| TT_TEST_TIMEOUT | Maximum execution time |\n| TT_TEST_RESULT | Test result (SUCCESS, INCONCLUSIVE, FAILED, ERROR, NONE) |\n| TT_TEST_REPORT | Full path to test report directory |\n| TT_TEST_RETVAL_\\\u003cVARIABLE NAME\\\u003e | Test related package output parameter (only for package execution)|\n\u003c/details\u003e\n\n## Downstream report generation\n\nThe concept of downstream report generation allows to execute the report generators like ATX, UNIT, HTML etc. in a downstream-based project.\nTherefore the report artifacts like TRF reports etc. must be archived after the test execution stage and will then be copied into a separate workspace of the triggered downstream project.\n\nThis downstream project acts like a central reporting service which waits for inputs from other test executions. It will be an ease to scale this service with help of Jenkins parallelization and distribution features.\nThe big advantage of this approach is to save time for the report generation and uploading process on expensive testing resources like HiL test benches. These resources can be directly used for the next test.\n\n![Downstream Report Generation](docs/images/downstream_report_generation.png \"Downstream Report Generation\")\n\n### Example configurations\n\n#### Preconditions\n\nTo prevent duplicate reports the build workspace should be cleaned before running the tests and before copying artifacts inside of the downstream project.\nThis can be achieved by using clean checkouts from repository or using the [Workspace Cleanup Plugin](https://plugins.jenkins.io/ws-cleanup) when preparing the build environment.\n\nTo transfer the report artifacts from one node to another the [Copy Artifact Plugin](https://plugins.jenkins.io/copyartifact) is required for freestyle projects. When using pipelines also stash/unstash commands can be used.\n\n#### Freestyle configuration\n\nExecuting tests and archiving the artifacts (_upstream_)\n\n![Upstream Build Steps](docs/images/upstream_build_steps.png \"Upstream Build Steps\")\n![Upstream Post-Build Steps](docs/images/upstream_post_build_steps.png \"Upstream Post-Build Steps\")\n\nCopying artifacts and generating ATX report (_downstream_)\n\n![Downstream Build Steps](docs/images/downstream_build_steps.png \"Downstream Build Steps\")\n![Downstream Post-Build Steps](docs/images/downstream_post_build_steps.png \"Downstream Post-Build Steps\")\n\n#### Pipeline configuration\n\n\u003cdetails\u003e\n    \u003csummary\u003eUpstream pipeline definition\u003c/summary\u003e\n\n```groovy\nnode('windows') {\n    deleteDir()\n\n    startET 'ecu.test'\n    testPackage testFile: 'sample.pkg', testConfig: [tbcFile: 'sample.tbc', tcfFile: 'sample.tcf']\n    stopET 'ecu.test'\n\n    archiveArtifacts 'TestReports/**/*.trf'\n    build job: 'downstream', wait: false\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eDownstream pipeline definition\u003c/summary\u003e\n\n```groovy\nnode('windows') {\n    deleteDir()\n\n    copyArtifacts filter: 'TestReports/**/*.trf', projectName: 'upstream', selector: lastSuccessful()\n\n    // Class notation is required for publisher steps inside downstream wrapper!\n    // Available: ATXPublisher, ETLogPublisher, JUnitPublisher, ReportGeneratorPublisher, TMSPublisher, TRFPublisher\n    downstreamPublisher workspace: '', reportDir: 'TestReports', publishers: [\n        [$class: 'ATXPublisher', atxName: 'test.guide'],\n        [$class: 'JUnitPublisher', toolName: 'ecu.test']]\n}\n```\n\u003c/details\u003e\n\n## Downstream trace analysis\n\nIn addition to downstream report generation the plugin allows to run trace analyses in a downstream-based project. Therefore the test cases are executed without trace analysis at first.\nAfterwards all trace analysis artifacts like analysis job files, traces, trace step templates and TRF reports etc. must be archived and will then be copied into a separate workspace of the triggered downstream project.\n\nThis downstream project acts like a central trace analysis service which waits for inputs from other test executions and is designed to be highly scalable.\nThe huge advantage of better ressource efficiency is the same as for downstream report generation and can also be used in combination.\n\n![Downstream Trace Analysis](docs/images/downstream_trace_analysis.png \"Downstream Trace Analysis\")\n\n### Example configurations\n\n#### Preconditions\n\nSame as in [downstream report generation](#downstream-report-generation).\n\n#### Freestyle configuration\n\nExecuting test cases without trace analysis and archiving the artifacts (_upstream_)\n\n![Upstream Build Steps](docs/images/upstream_build_steps2.png \"Upstream Build Steps\")\n![Upstream Post-Build Steps](docs/images/upstream_post_build_steps2.png \"Upstream Post-Build Steps\")\n\nCopying artifacts and running the trace analysis (_downstream_)\n\n![Downstream Build Steps](docs/images/downstream_build_steps2.png \"Downstream Build Steps\")\n![Downstream Post-Build Steps](docs/images/downstream_post_build_steps2.png \"Downstream Post-Build Steps\")\n\n#### Pipeline configuration\n\n\u003cdetails\u003e\n    \u003csummary\u003eUpstream pipeline definition\u003c/summary\u003e\n\n```groovy\nnode('windows') {\n    deleteDir()\n\n    startET 'ecu.test'\n    testPackage testFile: 'sample.pkg', testConfig: [tbcFile: 'sample.tbc', tcfFile: 'sample.tcf'], packageConfig: [runTraceAnalysis: false]\n    stopET 'ecu.test'\n\n    archiveArtifacts 'TestReports/**/*.trf, TestReports/**/*.ajob, Packages/**, Traces/**, TraceStepTemplates/**'\n    build job: 'downstream', wait: false\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eDownstream pipeline definition\u003c/summary\u003e\n\n```groovy\nnode('windows') {\n    deleteDir()\n\n    copyArtifacts filter: 'TestReports/**/*.trf, TestReports/**/*.ajob, Packages/**, Traces/**, TraceStepTemplates/**', projectName: 'upstream', selector: lastSuccessful()\n\n    // Class notation is required for publisher steps inside downstream wrapper!\n    downstreamPublisher workspace: '', reportDir: 'TestReports', publishers: [\n        [$class: 'TraceAnalysisPublisher', toolName: 'ecu.test', mergeReports: true]]\n}\n```\n\u003c/details\u003e\n\n## Extensions\n\n### Job DSL\n\nThe [Job DSL Plugin](https://plugins.jenkins.io/job-dsl) allows the programmatic creation of projects using a DSL. This plugin provides some specific DSL extensions.\n\nFurthermore, if there is a method which is currently not supported then Job DSL also provides an [auto-generator](https://github.com/jenkinsci/job-dsl-plugin/wiki/Dynamic-DSL).\n\n\u003cdetails\u003e\n    \u003csummary\u003eControlling tools\u003c/summary\u003e\n\n```groovy\nsteps {\n    // Start ecu.test\n    startET(String installation) {\n        workspaceDir(String directory)\n        settingsDir(String directory)\n        timeout(int | String timeout = 120)\n        debugMode(boolean debugMode = false)\n        keepInstance(boolean keepInstance = false)\n    }\n    // Stop ecu.test\n    stopET(String installation) {\n        timeout(int | String timeout = 30)\n    }\n    // Start Tool-Server\n    startTS(String installation) {\n        toolLibsIni(String toolLibsPath)\n        tcpPort(int | String port = 5017)\n        timeout(int | String timeout = 120)\n        keepInstance(boolean keepInstance = false)\n    }\n    // Stop Tool-Server\n    stopTS(String installation)\n    timeout(int | String timeout = 30)\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eTest execution\u003c/summary\u003e\n\n```groovy\nsteps {\n    // Run package\n    testPackage(String packageFile) {\n        testConfig {\n            tbcFile(String tbcFile)\n            tcfFile(String tcfFile)\n            forceReload(boolean forceReload = false)\n            loadOnly(boolean loadOnly = false)\n            constants {\n                constant(String name, String value)\n                constant {\n                    name(String name)\n                    value(String value)\n                }\n            }\n        }\n        packageConfig {\n            runTest(boolean runTest = true)\n            runTraceAnalysis(boolean runTraceAnalysis = true)\n            parameters {\n                parameter(String name, String value)\n                parameter {\n                    name(String name)\n                    value(String value)\n                }\n            }\n        }\n        executionConfig {\n            timeout(int | String timeout = 3600)\n            checkTestFile(boolean checkTestFile = true)\n            stopOnError(boolean stopOnError = true)\n        }\n    }\n    // Run project\n    testProject(String projectFile) {\n        testConfig { (...) }\n        projectConfig {\n            execInCurrentPkgDir(boolean currentPkgDir = false)\n            filterExpression(String expression)\n            // modes: NO_EXECUTION(0), SEQUENTIAL_EXECUTION(1),\n            // PARALLEL_EXECUTION(2), SEPARATE_SEQUENTIAL_EXECUTION(5),\n            // SEPARATE_PARALLEL_EXECUTION(6), NO_TESTCASE_EXECUTION(9)\n            jobExecutionMode(int | String execMode = 1)\n        }\n        executionConfig { (...) }\n    }\n    // Run test folder\n    testFolder(String testFolder) {\n        // modes: PACKAGES_ONLY, PROJECTS_ONLY, PACKAGES_AND_PROJECTS\n        scanMode(String mode = 'PACKAGES_AND_PROJECTS')\n        recursiveScan(boolean recursive = false)\n        testConfig { (...) }\n        packageConfig { (...) }\n        projectConfig { (...) }\n        executionConfig { (...) }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eTest management\u003c/summary\u003e\n\n```groovy\nsteps {\n    // Import projects\n    importProjects {\n        importFromArchive(String archivePath, String importPath, String importConfigPath, boolean replaceFiles)\n        importFromArchive(String archivePath) {\n            importPath(String importPath)\n            importConfigPath(String importConfigPath)\n            replaceFiles(boolean replaceFiles)\n        }\n        importFromTMS(String credentialsId, String projectPath, String importPath, int | String timeout = 60, String tmProjectId)\n        importFromTMS(String credentialsId, String projectPath, {\n            importPath(String importPath)\n            timeout(int | String timeout = 60)\n        }, String tmProjectId)\n        importFromTMSDir(String credentialsId, String projectDirPath, String importPath, int | String timeout = 60)\n        importFromTMSDir(String credentialsId, String projectDirPath) {\n            importPath(String importPath)\n            timeout(int | String timeout = 60)\n        }\n        importAttributesFromTMS(String credentialsId, String projectPath, int | String timeout = 60)\n        importAttributesFromTMS(String credentialsId, String projectPath) {\n            timeout(int | String timeout = 60)\n        }\n    }\n    // Import packages\n    importPackages {\n        importFromTMS { (...) }\n        importFromTMSDir { (...) }\n        importAttributesFromTMS { (...) }\n    }\n    // Export projects\n    exportProjects {\n        exportToTMS(String credentialsId, String projectPath, String exportPath, boolean createNewPath, int | String timeout = 60)\n        exportToTMS(String credentialsId, String projectPath) {\n            exportPath(String exportPath)\n            createNewPath(boolean createNewPath)\n            timeout(int | String timeout = 60)\n        }\n        exportAttributesToTMS(String credentialsId, String projectPath, int | String timeout = 60)\n        exportAttributesToTMS(String credentialsId, String projectPath) {\n            timeout(int | String timeout = 60)\n        }\n    }\n    // Export packages\n    exportPackages {\n        exportToTMS { (...) }\n        exportAttributesToTMS { (...) }\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003ePublishing reports\u003c/summary\u003e\n\n```groovy\npublishers {\n    // Publish ATX reports\n    publishATX(String atxInstallation) {\n        // Archive options\n        allowMissing(boolean allowMissing = false)\n        runOnFailed(boolean runOnFailed = false)\n        archiving(boolean archiving = true)\n        keepAll(boolean keepAll = true)\n    }\n    // Publish TRF reports\n    publishTRF() {\n        // Archive options...\n    }\n    // Publish UNIT reports\n    publishUNIT(String installation) {\n        unstableThreshold(double threshold = 0)\n        failedThreshold(double threshold = 0)\n        // Archive options...\n    }\n    // Publish ecu.test logs\n    publishETLogs() {\n        unstableOnWarning(boolean markUnstable = false)\n        failedOnError(boolean markFailed = false)\n        testSpecific(boolean testSpecific = false)\n        // Archive options...\n    }\n    // Publish Report Generators\n    publishGenerators(String installation) {\n        generators {\n            generator(String generatorName) {\n                settings {\n                    setting(String name, String value)\n                    setting {\n                        name(String name)\n                        value(String value)\n                    }\n                }\n            }\n        }\n        customGenerators {\n            customGenerator(String generatorName) { (...) }\n        }\n        // Archive options...\n    }\n    // Publish to Test Management System\n    publishTMS(String installation, String credentialsId) {\n        timeout(int | String timeout = 60)\n        // Archive options...\n    }\n}\n```\n\u003c/details\u003e\n\n### Pipeline\n\nThe [Pipeline Plugin](https://plugins.jenkins.io/workflow-aggregator) allows to orchestrate automation, simple or complex, using a DSL. This plugin supports the use of all provided build steps and post-build actions from within a Jenkins Pipeline build. The appropriate DSL syntax for these steps and actions can be easily generated with help of the [Pipeline Snippet Generator](https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md#exploring-the-snippet-generator) using the related custom pipeline step or the 'step' command, when using plugin version prior to 1.13.\n\n\u003cdetails\u003e\n    \u003csummary\u003eBasic pipeline example\u003c/summary\u003e\n\n```groovy\nnode('windows') {\n    stage('Start Tools') {\n        startET 'ecu.test'\n    }\n    stage('Test Execution') {\n        testPackage testFile: 'sample.pkg', testConfig: [tbcFile: 'sample.tbc', tcfFile: 'sample.tcf']\n        testProject testFile: 'sample.prj', testConfig: [tbcFile: 'sample.tbc', tcfFile: 'sample.tcf']\n    }\n    stage('Publish Reports') {\n        publishATX 'test.guide'\n    }\n    stage('Stop Tools') {\n        stopET 'ecu.test'\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eDynamic ecu.test pipeline example\u003c/summary\u003e\n\n```groovy\nnode('windows') {\n    // ecu.test installation using global variable ET\n    def et = ET.newInstallation toolName: 'ecu.test', installPath: 'C:\\\\Program Files\\\\ECU-TEST X.Y'\n\n    // or getting existing installation from global tool configuration\n    def et = ET.installation('ecu.test')\n\n    // Start ecu.test\n    et.start('C:\\\\Data\\\\workspace', 'C:\\\\Data\\\\settings')\n\n    // Stop ecu.test\n    et.stop()\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eDynamic test.guide pipeline example\u003c/summary\u003e\n\n**Simple**  \nFor simple use cases there is the `newServer` method of the global `ATX` variable.\n\n```groovy\nnode('windows') {\n    // Start tools, execute tests\n    ...\n\n    // test.guide server instantiation using global variable ATX\n    def atx = ATX.newServer atxName: 'test.guide', toolName: 'ecu.test',\n        fullServerURL: 'http://localhost:8085', uploadToServer: false,\n        uploadAuthenticationKey: 'xxx', projectId: '1'\n\n    // or getting existing instance from global configuration\n    def atx = ATX.server('test.guide')\n\n    // Override one or multiple settings explicitly\n    atx.overrideSetting('useHttpsConnection', true)\n    atx.overrideSettings([serverURL: '127.0.0.1', useHttpsConnection: true])\n\n    // Publish ATX reports directly\n    atx.publish()\n}\n```\n\n**Complex configurations**  \nFor more complex configurations it is recommended to use the `newATXServer` step, which allows to pass an ATXConfig \nobject. For some more information and/or examples refer the help section of the `newATXServer` step in your Jenkins \ninstance.  \nIf there is a setting in ecu.test which is not supported by this plugin yet, you can still configure them as \n`customSettings`.\n\n```groovy\nnode('windows') {\n    // Start tools, execute tests, generate reports\n    ...\n\n    // dynamic test.guide server instantiation using newATXServer step\n    def atx = newAtxServer atxName: 'test.guide', toolName: 'ecu.test',\n        config: atxConfig(\n            settings: [\n                atxTextSetting(group: 'CONNECTION', name: 'serverURL', value: 'localhost'),\n                atxTextSetting(group: 'CONNECTION', name: 'serverPort', value: '8085'),\n                atxTextSetting(group: 'CONNECTION', name: 'projectId', value: '1'),\n                atxSecretSetting(group: 'CONNECTION', name: 'uploadAuthenticationKey', value: 'xxx'),\n                atxBooleanSetting(group: 'UPLOAD', name: 'uploadToServer', value: true),\n            ],\n            customSettings: [\n                atxCustomTextSetting(name: 'customSetting', value: 'customValue'),\n                atxCustomBooleanSetting(name: 'boolSetting', checked: true)\n            ]\n        )\n    \n    // Publish ATX reports\n    publishATX atxName: atx.installation.getName(), atxInstallation: atx.installation\n}\n```\n\u003c/details\u003e\n\n### Configuration as Code\n\nThe [Jenkins Configuration as Code Plugin](https://plugins.jenkins.io/configuration-as-code) (a.k.a. JCasC) allows to configure Jenkins based on human-readable declarative configuration files. This plugin supports the external configuration of ecu.test tool installations and of test.guide server instances in the Jenkins global configuration.\n\nExisting configurations of both types can be exported to according YAML file using the [JCasC export view](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/docs/features/configExport.md).\n\n\u003cdetails\u003e\n    \u003csummary\u003eecu.test installation\u003c/summary\u003e\n\n```yml\ntool:\n    ecu-test:\n        installations:\n            - name: \"ecu.test X.Y\"\n              home: \"C:\\\\Program Files\\\\ECU-TEST X.Y\"\n            - name: \"ecu.test X2.Y2\"\n              home: \"C:\\\\Program Files\\\\ECU-TEST X2.Y2\"\n              properties:\n                  - ecuTestProperty:\n                        progId: \"ECU-TEST.Application.X2.Y2\"\n                        registerComServer: true\n                        timeout: 60\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003etest.guide server\u003c/summary\u003e\n\n```yml\nunclassified:\n    testGuide:\n        installations:\n            - name: \"test.guide\"\n              toolName: \"ecu.test\"\n              config:\n                  settings:\n                      - atxTextSetting:\n                            group: CONNECTION\n                            name: \"serverURL\"\n                            value: \"127.0.0.1\"\n                      - atxTextSetting:\n                            group: CONNECTION\n                            name: \"serverLabel\"\n                      - atxBooleanSetting:\n                            group: CONNECTION\n                            name: \"useHttpsConnection\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: CONNECTION\n                            name: \"ignoreSSL\"\n                            value: false\n                      - atxTextSetting:\n                            group: CONNECTION\n                            name: \"serverPort\"\n                            value: \"8085\"\n                      - atxTextSetting:\n                            group: CONNECTION\n                            name: \"serverContextPath\"\n                      - atxSecretSetting:\n                            group: CONNECTION\n                            name: \"httpProxy\"\n                      - atxSecretSetting:\n                            group: CONNECTION\n                            name: \"httpsProxy\"\n                      - atxTextSetting:\n                            group: CONNECTION\n                            name: \"projectId\"\n                            value: \"1\"\n                      - atxSecretSetting:\n                            group: CONNECTION\n                            name: \"uploadAuthenticationKey\"\n                      - atxTextSetting:\n                            group: CONNECTION\n                            name: \"uploadSettings\"\n                      - atxTextSetting:\n                            group: CONNECTION\n                            name: \"useSettingsFromServer\"\n                            value: \"Never\"\n                      - atxBooleanSetting:\n                            group: CONNECTION\n                            name: \"uploadToServer\"\n                            value: true\n                      - atxTextSetting:\n                            group: CONNECTION\n                            name: \"uploadThroughResourceAdapter\"\n                            value: \"0\"\n                      - atxBooleanSetting:\n                            group: CONNECTION\n                            name: \"uploadThroughResourceAdapterFallback\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: UPLOAD\n                            name: \"uploadAsync\"\n                            value: true\n                      - atxTextSetting:\n                            group: UPLOAD\n                            name: \"maxUploadTries\"\n                            value: \"42\"\n                      - atxBooleanSetting:\n                            group: UPLOAD\n                            name: \"compressUpload\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: UPLOAD\n                            name: \"cleanAfterSuccessUpload\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: UPLOAD\n                            name: \"uploadOnlyProjectReport\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"enableArchive\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveExternalLinks\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveTrf\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archivePkg\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveTcf\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveTbc\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveMapping\"\n                            value: false\n                      - atxTextSetting:\n                            group: ARCHIVE\n                            name: \"archiveRecordings\"\n                            value: \"False\"\n                      - atxTextSetting:\n                            group: ARCHIVE\n                            name: \"archiveRecordingsByAttributes\"\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveRecordingMetadata\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archivePlots\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveImages\"\n                            value: true\n                      - atxTextSetting:\n                            group: ARCHIVE\n                            name: \"archiveMiscFiles\"\n                      - atxTextSetting:\n                            group: ARCHIVE\n                            name: \"archiveMiscFilePrefix\"\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveMiscFilesOnlyInTestReportDir\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveFilesExcludeRecordings\"\n                            value: false\n                      - atxTextSetting:\n                            group: ARCHIVE\n                            name: \"archiveBy\"\n                            value: \"NONE;SUCCESS;INCONCLUSIVE;FAILED;ERROR\"\n                      - atxBooleanSetting:\n                            group: ARCHIVE\n                            name: \"archiveDescriptionImages\"\n                            value: true\n                      - atxTextSetting:\n                            group: ATTRIBUTE\n                            name: \"coveredAttributes\"\n                            value: \"Testlevel;Designer;Execution Priority;Estimated Duration [min];\"\n                      - atxTextSetting:\n                            group: ATTRIBUTE\n                            name: \"attributeDelimiter\"\n                      - atxBooleanSetting:\n                            group: ATTRIBUTE\n                            name: \"mapIsTestCaseAsAttribute\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ATTRIBUTE\n                            name: \"mapTestCaseVersionAsAttribute\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ATTRIBUTE\n                            name: \"mapIsStimulationAsAttribute\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ATTRIBUTE\n                            name: \"mapIsAnalysisAsAttribute\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ATTRIBUTE\n                            name: \"mapRootPrjAttrToPkgAttr\"\n                            value: true\n                      - atxTextSetting:\n                            group: ATTRIBUTE\n                            name: \"excludePrjAttrPrefixFor\"\n                      - atxBooleanSetting:\n                            group: ATTRIBUTE\n                            name: \"includePkgSVNRevision\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: ATTRIBUTE\n                            name: \"mapSwkIdsAsAttribute\"\n                            value: true\n                      - atxTextSetting:\n                            group: TBC_CONSTANTS\n                            name: \"coveredConstants\"\n                            value: \"*; SWK_Version; TT_*; TBC_*; TCF_*\"\n                      - atxBooleanSetting:\n                            group: TBC_CONSTANTS\n                            name: \"mapTbcToolAsConstant\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: TCF_CONSTANTS\n                            name: \"mapTcfTesterAsConstant\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: TCF_CONSTANTS\n                            name: \"mapTCFPropertyAsConstant\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: TCF_CONSTANTS\n                            name: \"mapUserDefinedReportDataAsConstant\"\n                            value: true\n                      - atxTextSetting:\n                            group: TCF_CONSTANTS\n                            name: \"setConstants\"\n                      - atxTextSetting:\n                            group: TCF_CONSTANTS\n                            name: \"setAttributes\"\n                      - atxBooleanSetting:\n                            group: REVIEW\n                            name: \"skipCaptureReviews\"\n                            value: false\n                      - atxTextSetting:\n                            group: REVIEW\n                            name: \"setReviewTags\"\n                      - atxBooleanSetting:\n                            group: REVIEW\n                            name: \"reviewUseAbortCodeAsCustomEvaluation\"\n                            value: false\n                      - atxTextSetting:\n                            group: REVIEW\n                            name: \"detectReviewTags\"\n                      - atxTextSetting:\n                            group: REVIEW\n                            name: \"detectReviewDefects\"\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"autoATXGeneratorUpdate\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"includeToolIdentifier\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"includePkgTestSteps\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"onlyIncludePkgTestCases\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"overrideParamSetNameMapping\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"mapProjectElementNameAsTestCaseName\"\n                            value: false\n                      - atxTextSetting:\n                            group: SPECIAL\n                            name: \"mapSubPackageAsTestCaseLevel\"\n                            value: \"0\"\n                      - atxTextSetting:\n                            group: SPECIAL\n                            name: \"captureSubPackageOnVerdict\"\n                      - atxTextSetting:\n                            group: SPECIAL\n                            name: \"captureSpecialTestSteps\"\n                            value: \"\"\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"mapSeparateProjectExecutionAsSingleTestplan\"\n                            value: false\n                      - atxTextSetting:\n                            group: SPECIAL\n                            name: \"mapAttributeAsConstant\"\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"mapTestReportPathAsConstant\"\n                            value: false\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"includeResourceAdapterInfo\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"captureExecutionTime\"\n                            value: true\n                      - atxBooleanSetting:\n                            group: SPECIAL\n                            name: \"useNewUploadApi\"\n                            value: true\n                  customSettings:\n                      - atxCustomBooleanSetting:\n                            name: \"customOption\"\n                            checked: true\n                      - atxCustomTextSetting:\n                            name: \"customLabel\"\n                            value: \"test\"\n```\n\u003c/details\u003e\n\n### Warnings NG Plugin\n\nThe [Warnings NG Plugin](https://plugins.jenkins.io/warnings-ng/) is used to record and manage issues within your Jenkins Pipelines. Supported versions of this plugin start at **11.0.0**. It is recommended to use these versions to ensure compatibility and stability.\n\n## Debugging\n\nTo change the job console log level to debug, the system property `ecutest.debugLog` should be set to `true`. This could be done either at startup\n\n`java -Decutest.debugLog=true -jar jenkins.war`\n\nor at runtime in the console under `Jenkins -\u003e Manage Jenkins -\u003e Script Console`\n\n`System.setProperty(\"ecutest.debugLog\", \"true\")`\n\nTo get a more debug output about plugin COM API communication a new log recorder with following logger instances could be created under `Manage Jenkins -\u003e System Log -\u003e New Log Recorder`. Set a preferable name, add loggers `de.tracetronic.jenkins.plugins.ecutest.wrapper.com.ETComClient`, `de.tracetronic.jenkins.plugins.ecutest.wrapper.com.ETComDispatch` and set the log level to at least `FINE`.\n\n![Create new COM API log recorder](docs/images/create_new_debug_log_recorder.png \"Create new COM API log recorder\")\n\n## Issues\n\nTo report a bug or request an enhancement to this plugin please raise a new [GitHub issue](https://github.com/jenkinsci/ecutest-plugin/issues/new/choose) or create a [ticket in JIRA](https://issues.jenkins.io/secure/CreateIssueDetails!init.jspa?pid=10172\u0026components=20856\u0026issuetype=1\u0026priority=4).\n\n## Known limitations\n\nWhen using the plugin in a agent-based setup (especially running the agent at command line via JNLP) you also need to restart the agent when restarting the master.\nThis is due to already loaded libraries, for more information see this [blog post](http://jenkins-ci.org/content/your-java-web-start-slaves-will-be-always-clean) and related issue [JENKINS-31961](https://issues.jenkins-ci.org/browse/JENKINS-31961).\n\nRelease 1.8 implemented an extension point that will workaround this issue. In order to work a new task has to be created in the Windows Task Scheduler named [RESTART_JENKINS_AGENT](docs/RESTART_JENKINS_AGENT.xml) and configured with actions how to restart the agent.\n\nPlease note that from [ecu.test](https://www.tracetronic.com/products/ecu-test/) Version 2022.3 on, **invalid escape \nsequences in expressions within ecu.test are disallowed.** This means, in particular, that backslashes in Windows \npaths need to be escaped properly (e.g. *C:\\\\\\my\\\\\\path* instead of *C:\\my\\path*) - otherwise, this will lead to an \nerror within ecu.test.\n\nSince [release 2.39](https://github.com/jenkinsci/ecutest-plugin/releases/tag/ecutest-2.39) we test only against \n[ecu.test](https://www.tracetronic.com/products/ecu-test/) versions, that are inside the support window of the \ntracetronic tool support terms. Please consult the [compatibility matrix](#compatibility) for detailed \ninformation.\n\nDue to the deprecation and the feature freeze of this plugin it will not support this new PRF file format. Consider \nmigrating to the [ecu.test execution plugin](https://plugins.jenkins.io/ecu-test-execution/) if you want to publish \nthe new PRF files to Jenkins.\n\n## FAQ\n\nFrequently asked questions, common issues and error messages about the [ecu.test Jenkins Plugin](https://github.com/jenkinsci/ecutest-plugin) and [ecu.test](https://www.tracetronic.com/products/ecu-test/) itself\ncan be found in the [tracetronic Knowledge Base](https://kb.tracetronic.com/display/KB/Jenkins+Plugin).\n\n## Compatibility\n\n- Jenkins LTS 2.426.3 or higher\n- Java SE Runtime Environment 17 or higher\n- Check [min versions](toolDependencies.yml) for tt tools \n \u003cdetails\u003e\n    \u003csummary\u003e\u003ca href=\"https://www.tracetronic.com/products/ecu-test\"\u003eecu.test\u003c/a\u003e compat matrix (min 2024.1)\u003c/summary\u003e\n\n| Version |   latest - 2.45    |        2.44        |    2.43 - 2.39     |    2.38 - 2.26     |\n|:-------:|:------------------:|:------------------:|:------------------:|:------------------:|\n| 2024.4  | :heavy_check_mark: |        :x:         |        :x:         |        :x:         |\n| 2024.3  | :heavy_check_mark: |        :x:         |        :x:         |        :x:         |\n| 2024.2  | :heavy_check_mark: | :heavy_check_mark: |        :x:         |        :x:         |\n| 2024.1  | :heavy_check_mark: | :heavy_check_mark: |        :x:         |        :x:         |\n| 2023.4  |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 2023.3  |        :x:         | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 2023.2  |        :x:         | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 2023.1  |        :x:         | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 2022.4  |        :x:         |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |\n| 2022.3  |        :x:         |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |\n| 2022.2  |        :x:         |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |\n| 2022.1  |        :x:         |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |\n| 2021.4  |        :x:         |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |\n| 2021.3  |        :x:         |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |\n| 2021.2  |        :x:         |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |\n| 2021.1  |        :x:         |  :grey_question:   | :heavy_check_mark: | :heavy_check_mark: |\n \n  **Explanation:** :heavy_check_mark: -\u003e compatible | :grey_question: -\u003e not tested, might be compatible | :x: -\u003e not \n  compatible \n\n  \u003c/details\u003e\n \u003cdetails\u003e\n    \u003csummary\u003eoptional: \u003ca href=\"https://www.tracetronic.com/products/test-guide\"\u003etest.guide\u003c/a\u003e compat matrix (min  1.87.0) \u003c/summary\u003e\n\n| Version |   latest - 2.45    |        2.44        |    2.43 - 2.26     |    2.25 - 2.23     |\n|:-------:|:------------------:|:------------------:|:------------------:|:------------------:|\n| 1.187.0 | :heavy_check_mark: |        :x:         |        :x:         |        :x:         |\n| 1.169.1 | :heavy_check_mark: | :heavy_check_mark: |        :x:         |        :x:         |\n| 1.129.0 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 1.120.0 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 1.113.0 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 1.104.0 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 1.95.0  | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |        :x:         |\n| 1.87.0  | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |\n| 1.84.2  |        :x:         |        :x:         | :heavy_check_mark: | :heavy_check_mark: |\n\n* Note that some lacking version incompatibilities in the test.guide - ecu.test-Plugin compatibility matrix are due \nto configuration fields which are not natively supported. You may still add these lacking configurations via the \n*custom fields* in the test.guide configuration on the Jenkins server. \n\u003c/details\u003e\n\n## License\n\nThis plugin is licensed under 3-clause BSD license.\nMore information can be found inside the [LICENSE](LICENSE) file or within the [LICENSES](./LICENSES) folder. Using\nthe [REUSE helper tool](https://github.com/fsfe/reuse-tool), you can run `reuse spdx` to get a bill of materials.\n\n\n## Changelog\n\n- See [GitHub Releases](https://github.com/jenkinsci/ecutest-plugin/releases) for recent versions (2.9 and above)\n- See [CHANGELOG.md](docs/CHANGELOG.md) for previous releases (2.8 and below)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenkinsci%2Fecutest-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjenkinsci%2Fecutest-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenkinsci%2Fecutest-plugin/lists"}