diff --git a/.github/auto_assign.yml b/.github/auto_assign.yml new file mode 100644 index 00000000..3d239709 --- /dev/null +++ b/.github/auto_assign.yml @@ -0,0 +1,10 @@ +addReviewers: false +addAssignees: true + +assignees: + - TimSVector + +skipKeywords: + - wip + +numberOfAssignees: 0 diff --git a/.github/check-md-links.json b/.github/check-md-links.json new file mode 100644 index 00000000..b6cf7559 --- /dev/null +++ b/.github/check-md-links.json @@ -0,0 +1,11 @@ +{ + "httpHeaders": [ + { + "urls": ["https://github.com/", "https://guides.github.com/", "https://help.github.com/", "https://docs.github.com/", "https://classroom.github.com"], + "headers": { + "Accept-Encoding": "zstd, br, gzip, deflate" + } + } + ], + "aliveStatusCodes": [200, 500, 503] +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..6fe8aae3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,33 @@ +version: 2 +updates: + - package-ecosystem: maven + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 + commit-message: + prefix: "" + ignore: + - dependency-name: org.eclipse.collections:eclipse-collections + versions: + - ">= 10.a" + - dependency-name: org.eclipse.collections:eclipse-collections-api + versions: + - ">= 10.a" + - dependency-name: net.javacrumbs.json-unit:json-unit-assertj + versions: + - ">= 3.0.0" + + - package-ecosystem: "github-actions" + directory: "/" + commit-message: + prefix: "" + schedule: + interval: "daily" + + - package-ecosystem: "npm" + directory: "/" + commit-message: + prefix: "" + schedule: + interval: "daily" diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 00000000..cf5f006b --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,36 @@ +- name: bug + description: Bugs or performance problems + color: CC0000 +- name: enhancement + description: Enhancement of existing functionality + color: 0366d6 +- name: feature + color: 1d76db + description: New features +- name: breaking + description: Breaking Changes + color: e4b21d +- name: tests + description: Enhancement of tests + color: 0e8a16 +- name: documentation + description: Enhancement of documentation + color: bfafea +- name: internal + description: Internal changes without user or API impact + color: e6e6e6 +- name: dependencies + description: Update of dependencies + color: e6e6e6 +- name: java + description: Pull requests that update Maven Java dependencies + color: b6b6b6 +- name: javascript + description: Pull requests that update Node Javascript dependencies + color: b6b6b6 +- name: github_actions + description: Pull requests that update Github Actions workflows + color: 909090 +- name: hacktoberfest + description: Pull requests that participate in Hacktoberfest + color: 7057ff diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 00000000..b3371837 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,46 @@ +name-template: 'v$RESOLVED_VERSION 🎁' +tag-template: 'v$RESOLVED_VERSION' + +template: | + $CHANGES + +# Emoji reference: https://gitmoji.carloscuesta.me/ +categories: + - title: 💥 Breaking Changes + label: breaking + - title: 🚀 New Features + label: feature + - title: ✨ Improvements + label: enhancement + - title: 🐛 Bug Fixes + label: bug + - title: 📝 Documentation + label: documentation + - title: 📦 Dependency Updates + label: dependencies + - title: 🔧 Internal Changes + label: internal + - title: 🚦 Tests + label: tests + +version-resolver: + major: + labels: + - 'removed' + minor: + labels: + - 'feature' + - 'enhancement' + - 'deprecated' + - 'dependencies' + - 'documentation' + - 'tests' + - 'internal' + patch: + labels: + - 'bug' + default: minor + +replacers: + - search: '/\[*JENKINS-(\d+)\]*\s*-*\s*/g' + replace: '[JENKINS-$1](https://issues.jenkins.io/browse/JENKINS-$1) - ' diff --git a/.github/workflows/assign-pr.yml b/.github/workflows/assign-pr.yml new file mode 100644 index 00000000..b5fbba3e --- /dev/null +++ b/.github/workflows/assign-pr.yml @@ -0,0 +1,12 @@ +name: 'Auto Assign PR' + +on: pull_request_target + +jobs: + assign-pr: + name: 'Auto Assign PR' + runs-on: ubuntu-latest + steps: + - uses: kentaro-m/auto-assign-action@v2.0.0 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/check-md-links.yml b/.github/workflows/check-md-links.yml new file mode 100644 index 00000000..9b5d40e1 --- /dev/null +++ b/.github/workflows/check-md-links.yml @@ -0,0 +1,14 @@ +name: 'Link Checker' + +on: push + +jobs: + check-markdown-links: + name: 'Check Markdown links' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + check-modified-files-only: 'no' + config-file: '.github/check-md-links.json' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..e5b0894f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,36 @@ +name: 'GitHub CI' + +on: + push: + branches: + - master + pull_request: + +jobs: + build: + + strategy: + matrix: + platform: [ubuntu-latest, windows-latest] + jdk: [11, 17, 21] + + runs-on: ${{ matrix.platform }} + name: on ${{ matrix.platform }} with JDK ${{ matrix.jdk }} + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK ${{ matrix.jdk }} + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '${{ matrix.jdk }}' + check-latest: true + cache: 'maven' + - name: Set up Maven + uses: stCarolas/setup-maven@v5 + with: + maven-version: 3.9.6 + - name: Build with Maven + env: + BROWSER: chrome-container + run: mvn -V --color always -ntp clean verify --file pom.xml '-Djenkins.test.timeout=5000' '-Dgpg.skip' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..c0023a0c --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,72 @@ +name: "CodeQL" + +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + schedule: + - cron: "32 3 * * 0" + +jobs: + analyze: + name: Analyze code + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ java ] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: maven + + - name: Set up Maven + uses: stCarolas/setup-maven@v5 + with: + maven-version: 3.9.6 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Build with Maven + run: mvn -V --color always -ntp clean verify -Plint --file pom.xml -Pskip + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + upload: false + output: sarif-results + category: "/language:${{ matrix.language }}" + + - name: Filter SARIF results + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -**/*Assert* + input: sarif-results/${{ matrix.language }}.sarif + output: sarif-results/${{ matrix.language }}.sarif + + - name: Upload SARIF results + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: sarif-results/${{ matrix.language }}.sarif diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..6d28c2ff --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,35 @@ +name: 'CodeCov' + +on: + push: + branches: + - master + - main + pull_request: + +jobs: + coverage: + + runs-on: ubuntu-latest + name: Create and upload coverage report + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + check-latest: true + cache: 'maven' + - name: Set up Maven + uses: stCarolas/setup-maven@v5 + with: + maven-version: 3.9.6 + - name: Generate coverage with JaCoCo + run: mvn -V --color always -ntp clean verify --file pom.xml + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4.5.0 + with: + files: 'target/site/jacoco/jacoco.xml' + token: ${{secrets.CODECOV_TOKEN}} diff --git a/.github/workflows/enforce-labels.yml b/.github/workflows/enforce-labels.yml new file mode 100644 index 00000000..d58d2144 --- /dev/null +++ b/.github/workflows/enforce-labels.yml @@ -0,0 +1,18 @@ +name: Label Checker +on: + pull_request: + types: [opened, labeled, unlabeled, synchronize] +jobs: + enforce-labels: + name: 'Enforce PR labels' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: mheap/github-action-required-labels@v5 + with: + mode: minimum + count: 1 + labels: "bug,feature,enhancement,breaking,tests,documentation,internal,dependencies" + message: "Maintainer needs to assign at least one label before merge" diff --git a/.github/workflows/jenkins-security-scan.yml b/.github/workflows/jenkins-security-scan.yml new file mode 100644 index 00000000..79662bde --- /dev/null +++ b/.github/workflows/jenkins-security-scan.yml @@ -0,0 +1,22 @@ +name: Jenkins Security Scan + +on: + push: + branches: + - master + pull_request: + types: [ opened, synchronize, reopened ] + workflow_dispatch: + +permissions: + security-events: write + contents: read + actions: read + +jobs: + security-scan: + uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2 + with: + java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate. + java-version: 11 # Optionally specify what version of Java to set up for the build, or remove to use a recent default. + diff --git a/.github/workflows/run-release-drafter.yml b/.github/workflows/run-release-drafter.yml new file mode 100644 index 00000000..9eed0915 --- /dev/null +++ b/.github/workflows/run-release-drafter.yml @@ -0,0 +1,15 @@ +name: 'Release Drafter' + +on: + push: + branches: + - master + +jobs: + update-release-draft: + name: 'Update Release Draft' + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v6.0.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 00000000..e770fa0e --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,20 @@ +name: Sync labels +on: + push: + branches: + - master + paths: + - .github/labels.yml + - .github/workflows/sync-labels.yml + +jobs: + sync-labels: + name: Sync labels + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: micnncim/action-label-syncer@v1.3.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + manifest: .github/labels.yml diff --git a/README.md b/README.md index 40a04fc7..bd388d38 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,132 @@ +[![CodeCov](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/coverage.yml/badge.svg?branch=tms_078)](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/coverage.yml) +[![CodeQL](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/codeql.yml/badge.svg?branch=tms_078)](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/codeql.yml) +[![GitHub CI](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/ci.yml/badge.svg?branch=tms_078)](https://github.com/jenkinsci/vectorcast-execution-plugin/actions/workflows/ci.yml) # Summary -This plugin allows the user to create Single and Pipeline Jobs to build and execute [VectorCAST](http://vector.com/vectorcast) Projects. Coverage is displayed using the [VectorCAST Coverage Plugin](https://wiki.jenkins.io/display/JENKINS/VectorCAST+Coverage+Plugin). +This plugin allows the user to create Single and Pipeline Jobs to build and execute [VectorCAST](http://vector.com/vectorcast) Projects. Test results are display with the [Jenkins JUnit Plugin](https://plugins.jenkins.io/junit/) and code coverage is displayed using either +- [Jenkins Coverage Plugin](https://plugins.jenkins.io/coverage) +- [VectorCAST Coverage Plugin](https://wiki.jenkins.io/display/JENKINS/VectorCAST+Coverage+Plugin). + +# Table of Contents + + +* [Summary](#summary) +* [Table of Contents](#table-of-contents) +* [Setup/Configuration](#setupconfiguration) +* [Usage](#usage) + * [Job Types](#job-types) + * [Single Job](#single-job) + * [Pipeline Job](#pipeline-job) + * [Coverage Display Selection](#coverage-display-selection) + * [Information about Jenkins Coverage Plugin](#information-about-jenkins-coverage-plugin) + * [Advanced Settings for Jenkins Coverage Plugin](#advanced-settings-for-jenkins-coverage-plugin) + * [Information about legacy VectorCAST Coverage Plugin](#information-about-legacy-vectorcast-coverage-plugin) + * [Job Creation Options](#job-creation-options) + * [Job Name](#job-name-) + * [Shared Artifact Directory](#shared-artifact-directory) + * [Maximum Parallel Queued Jobs](#maximum-parallel-queued-jobs) + * [Use Coverage History](#use-coverage-history) + * [Use Strict Test Case Importing](#use-strict-test-case-importing) + * [Use Requirements Gateway 3 capabilities](#use-requirements-gateway-3-capabilities) + * [Use Imported Results](#use-imported-results) + * [Using Local Imported Results](#using-local-imported-results) + * [Using External Imported Results](#using-external-imported-results) + * [Additional Tools](#additional-tools) + * [PC-lint Plus](#pc-lint-plus) + * [Squore](#squore) + * [TESTinsights](#testinsights) + * [Controlling Where Jobs Run](#controlling-where-jobs-run) + * [Build Summary](#build-summary) + * [Test Results](#test-results) + * [Passing Test Case](#passing-test-case) + * [Failing Test Case](#failing-test-case) + * [Known Issues](#known-issues) + * [VectorCAST Reports and Jenkins Content Security](#vectorcast-reports-and-jenkins-content-security-) + * [JUnit publisher failing environment with no test cases](#junit-publisher-failing-environment-with-no-test-cases) + * [Potential loss of requirements information](#potential-loss-of-requirements-information) + * [Test and code coverage reporting with Imported Results](#test-and-code-coverage-reporting-with-imported-results) + * [Using Change Based Testing Imported Results with QA Project](#using-change-based-testing-imported-results-with-qa-project) + * [Disabled environments may add coverage metrics](#disabled-environments-may-add-coverage-metrics) + * [Change Log](#change-log) + * [Version 0.78 (10 Sep 2024)](#version-078-10-sep-2024) + * [Version 0.77 (21 Aug 2024)](#version-077-21-aug-2024) + * [Version 0.76 (19 Jan 2023)](#version-076-19-jan-2023) + * [Version 0.75 (23 Dec 2022)](#version-075-23-dec-2022) + * [Version 0.74 (27 Sep 2022)](#version-074-27-sep-2022) + * [Version 0.73 (22 Aug 2022)](#version-073-22-aug-2022) + * [Version 0.72 (24 May 2022)](#version-072-24-may-2022) + * [Version 0.71 (29 Sept 2021)](#version-071-29-sept-2021) + * [Version 0.70 (2 Aug 2021)](#version-070-2-aug-2021) + * [Version 0.69 (7 Jun 2021)](#version-069-7-jun-2021) + * [Version 0.68 (14 May 2021)](#version-068-14-may-2021) + * [Version 0.67 (30 March 2021)](#version-067-30-march-2021) + * [Version 0.66 (10 Feb 2021)](#version-066-10-feb-2021) + * [Version 0.65 (20 Jan 2021)](#version-065-20-jan-2021) + * [Version 0.64 (17 Nov 2020)](#version-064-17-nov-2020) + * [Version 0.63 (30 April 2020)](#version-063-30-april-2020) + * [Version 0.62 (10 March 2020)](#version-062-10-march-2020) + * [Version 0.61 (21 Dec 2019)](#version-061-21-dec-2019) + * [Version 0.60 (2 Oct 2019)](#version-060-2-oct-2019) + * [Version 0.59 (13 Sept 2019)](#version-059-13-sept-2019) + * [Version 0.58 (11 Sept 2019)](#version-058-11-sept-2019) + * [Version 0.57 (6 Sept 2019)](#version-057-6-sept-2019) + * [Version 0.56 (5 Sept 2019)](#version-056-5-sept-2019) + * [Version 0.55 (4 Sept 2019)](#version-055-4-sept-2019) + * [Version 0.54 (28 Aug 2019)](#version-054-28-aug-2019) + * [Version 0.53 (20 Aug 2019)](#version-053-20-aug-2019) + * [Version 0.52 (13 Aug 2019)](#version-052-13-aug-2019) + * [Version 0.51 (8 Aug 2019)](#version-051-8-aug-2019) + * [Version 0.50 (11 Jul 2019)](#version-050-11-jul-2019) + * [Version 0.49 (1 Jul 2019)](#version-049-1-jul-2019) + * [Version 0.48 (26 Jun 2019)](#version-048-26-jun-2019) + * [Version 0.47 (18 Jun 2019)](#version-047-18-jun-2019) + * [Version 0.46 (30 May 2019)](#version-046-30-may-2019) + * [Version 0.45 (10 May 2019)](#version-045-10-may-2019) + * [Version 0.44 (1 May 2019)](#version-044-1-may-2019) + * [Version 0.43 (26 Apr 2019)](#version-043-26-apr-2019) + * [Version 0.42 (25 Apr 2019)](#version-042-25-apr-2019) + * [Version 0.41 (12 Apr 2019)](#version-041-12-apr-2019) + * [Version 0.40 (10 Apr 2019)](#version-040-10-apr-2019) + * [Version 0.39 (19 Mar 2019)](#version-039-19-mar-2019) + * [Version 0.38 (23 Jan 2019)](#version-038-23-jan-2019) + * [Version 0.37 (10 Jan 2019)](#version-037-10-jan-2019) + * [Version 0.36 (27 Sept 2018)](#version-036-27-sept-2018) + * [Version 0.35 (15 May 2018)](#version-035-15-may-2018) + * [Version 0.34 (10 May 2018)](#version-034-10-may-2018) + * [Version 0.33 (18 Jan 2018)](#version-033-18-jan-2018) + * [Version 0.32 (15 Jan 2018)](#version-032-15-jan-2018) + * [Version 0.31 (13 Dec 2017)](#version-031-13-dec-2017) + * [Version 0.30 (5 Dec 2017)](#version-030-5-dec-2017) + * [Version 0.29 (27 Nov 2017)](#version-029-27-nov-2017) + * [Version 0.28 (2 Nov 2017)](#version-028-2-nov-2017) + * [Version 0.27 (2 Nov 2017)](#version-027-2-nov-2017) + * [Version 0.26 (1 Nov 2017](#version-026-1-nov-2017) + * [Version 0.25 (26 Oct 2017)](#version-025-26-oct-2017) + * [Version 0.24 (25 Oct 2017)](#version-024-25-oct-2017) + * [Version 0.23 (17 Oct 2017)](#version-023-17-oct-2017) + * [Version 0.22 (26 Sept 2017](#version-022-26-sept-2017) + * [Version 0.21 (24 Jul 2017)](#version-021-24-jul-2017) + * [Version 0.20 (18 Jul 2017)](#version-020-18-jul-2017) + * [Version 0.19 (23 Jun 2017)](#version-019-23-jun-2017) + * [Version 0.18 (20 Mar 2017)](#version-018-20-mar-2017) + * [Version 0.17 (17 Mar 2017)](#version-017-17-mar-2017) + * [Version 0.16 (15 Mar 2017)](#version-016-15-mar-2017) + * [Version 0.15 (2 Jan 2017)](#version-015-2-jan-2017) + * [Version 0.14 (16 Dec 2016)](#version-014-16-dec-2016) + * [Version 0.13 (14 Dec 2016)](#version-013-14-dec-2016) + * [Version 0.12 (9 Dec 2016)](#version-012-9-dec-2016) + * [Version 0.11 (7 Dec 2016)](#version-011-7-dec-2016) + * [Version 0.10 (23 Nov 2016)](#version-010-23-nov-2016) + + + +# Setup/Configuration + +- VectorCAST must be installed and setup on each node. +- The environment variables **VECTORCAST\_DIR** and **VECTOR\_LICENSE** must be set. +- Jenkins must be installed and setup. +- **BUILD\_URL** must be defined (in Jenkins-\>Manage Jenkins-\>Configure System and define 'Jenkins URL' and save the settings). # Usage @@ -11,7 +136,7 @@ This plugin adds a new top-level menu item to the Jenkins sidebar. Select the ** ## Job Types -![](docs/images/image2017-10-17_18_14_2.png) + There are two build/execute job types and one diagnostic job type. @@ -66,54 +191,121 @@ For Pipeline Jobs, the plugin processes the build log to determine which tests h ![](docs/images/test_results.png) -## Job Creation Options +### Coverage Display Selection + +The VectorCAST Execution Plugin is transitioning from using the older VectorCAST Coverage Plugin (Legacy Plugin) to the Jenkins Coverage Plugin. Until that transition is complete, the use is offered a choice to decide which coverage display to use. + + + +#### Information about Jenkins Coverage Plugin +The [Jenkins Coverage Plugin](https://plugins.jenkins.io/coverage) publishes a report of the code and mutation coverage in your build, so you can navigate to a summary report from the main build page. Additionally, the plugin gathers several metrics (lines of code, cyclomatic complexity, number of tests per class) and visualizes these results along with the coverage information. + +By using the Jenkins Coverage Plugin, users can also dive into the details: +- Tree charts that show the distribution of the metrics by type (line, branch, complexity, tests, etc.) +- Tabular listing of all files with their coverage, complexity and number of tests +- Source code of the files with the coverage highlighted +- Trend charts of the coverage over time + +![](docs/images/report_overview_screen.png) + +#### Advanced Settings for Jenkins Coverage Plugin + +Two classes of settings can be accessed in the Jenkins Coverage Plugin +- Quality Gates +- Advanced Options + +To access the advanced settings: + +- Pipeline Jobs - You can access the Snippet Generator and use the configure a new pipeline snippet. Once you have the step configured, you can use the Generate Pipeline Script button, copy that snippet and replace the existing Coverage snippet in the job configuration. For more information regarding the advanced settings of the Jenkins Coverage Plugin, please refer to the documentation +Settings to process VectorCAST Coverage Results: + - Sample Step: recordCoverage: Record code coverage results + - Code Coverage Tool > Coverage Parser: VectorCAST Coverage Results + - Code Coverage Tool > Report File Pattern: xml_data/cobertura/coverage_results*.html +- Single Job - The setup for the Single Job will be one of the post-build steps. + +#### Information about legacy VectorCAST Coverage Plugin +The [VectorCAST Coverage Plugin](https://plugins.jenkins.io/vectorcast-coverage/) Processes code coverage metrics from for VectorCAST Projects +This legacy plugin allows you to capture code coverage reports from VectorCAST Projects. Jenkins will generate the trend report of coverage. This plugin is used automatically with the VectorCAST Execution Plugin +Coverage information from tests runs that has been converted to XML files is read and displayed by this plugin. + +It shows coverage trends and allows drilling down to more detailed coverage information: + +- Tree charts that show the distribution of the metrics by type (line, branch, MC/DC Pairs, Function Coverage, etc.) +- Tabular listing of all environments/files with their coverage and complexity +- Trend charts of the coverage over time + +:warning: Legacy Plugin Info +This is a legacy plugin and will have no futher development beyond bug fixes and security updates + + + +### Job Creation Options The user can customize additional parameters for job creation by selecting the **Job Creation Options**: -![](docs/images/job_creation_options.png) + -Use the **Job Name** setting for changing the created pipeline job name. Default is *VectorCASTProjectName*\_vcast\_pipeline +#### Job Name +Use the Job Name setting for changing the created pipeline job name. Default is *VectorCASTProjectName*\_vcast\_pipeline -The **Shared Artifact Directory** option allows VectorCAST Project's build artifacts to be stored in a different location from the default *VectorCASTProjectName*/build. If stored in a location that can be maintained between builds, VectorCAST's Change Based Testing can accelerate testing +#### Shared Artifact Directory +The Shared Artifact Directory (Pipeline Job Only) option allows VectorCAST Project's build artifacts to be stored in a different location from the default *VectorCASTProjectName*/build. If stored in a location that can be maintained between builds, VectorCAST's Change Based Testing can accelerate testing -**Maximum Parallel Queued Jobs** allows the job to specify the maximum number of unit test jobs to queue up at any one time for parallel execution. To queue all jobs, leave blank or set to zero (0). The use case for this option would be if you don't want to queue the Jenkins server with all VectorCAST environment build/execute jobs; thus, allowing other jobs to queue up as well. +#### Maximum Parallel Queued Jobs +Maximum Parallel Queued Jobs (Pipeline Job Only) allows the job to specify the maximum number of unit test jobs to queue up at any one time for parallel execution. To queue all jobs, leave blank or set to zero (0). The use case for this option would be if you don't want to queue the Jenkins server with all VectorCAST environment build/execute jobs; thus, allowing other jobs to queue up as well. -**Use Coverage History** marks build as failed if statement or branch coverage decrease by comparing the previous non-failing build's statement and branch coverage to the current build's statement and branch coverage. If either of the coverages have decreased the job will be marked as failed +#### Use Coverage History +Use Coverage History marks build as failed if statement or branch coverage decrease by comparing the previous non-failing build's statement and branch coverage to the current build's statement and branch coverage. If either of the coverages have decreased the job will be marked as failed. -**Use Strict Test Case Importing** allows the job to mark individual test cases as failures if errors encountered during test script import. This option enables strict testcase importing for the VectorCAST Project. This option give a more reliable metrics for pass/fail test cases as without strict test case import, bad test cases are just ignored. The default is enabled. +:information_source: When using the Jenkins Coverage Plugin, this will be completed by adding a quality gate for any drop in Statement or Branch coverages. It will be denoted in the Coverage Report section of the Build Status_ -**Use Imported Results** allows jobs to previous test results as input for the current job execution phase. This option allows VectorCAST Change Based Testing to have a known result to work from. This option works in conjunction with **Use Change Based Testing**. The user can selected between internal imported results or external result files + -![](docs/images/use_imported_results.png) +#### Use Strict Test Case Importing +Use Strict Test Case Importing allows the job to mark individual test cases as failures if errors encountered during test script import. This option enables strict testcase importing for the VectorCAST Project. This option give a more reliable metrics for pass/fail test cases as without strict test case import, bad test cases are just ignored. The default is enabled. -When using imported results and the **Use Local Imported Results** option, the job will export results from the current build and save that result file as an job artifact. The next build will pull the result archive from the last SUCCESS or UNSTABLE build and use change based testing against that result baseline. If existing build artifacts exist, the combined results will be used for change based testing. +#### Use Requirements Gateway 3 capabilities +This option allows test environments with existing tests linked to an Requirements Gateway v3 implementation, that uses seperate .json files, to execute in parallel and export data at the end of the run. -When using imported results and the **Use External Result File** option, the job will use an external results from the a specified location to use as a baseline for the the current job. If existing build artifacts exist, the combined results will be used for change based testing. The user will need to specify an external result filename (.vcr) in the **External Result Filename** option. This file would be typically stored in the repository. This external result file could be updated by a main branch or periodic build to establish a current baseline. +#### Use Imported Results +Use Imported Results allows jobs to previous test results as input for the current job execution phase. This option allows VectorCAST Change Based Testing to have a known result to work from. This option works in conjunction with _Use Change Based Testing_. The user can selected between internal imported results or external result files -## Additional Tools + + +#### Using Local Imported Results +When using imported results and the Use Local Imported Results option, the job will export results from the current build and save that result file as an job artifact. The next build will pull the result archive from the last SUCCESS or UNSTABLE build and use change based testing against that result baseline. If existing build artifacts exist, the combined results will be used for change based testing. + +#### Using External Imported Results +When using imported results and the Use External Result File option, the job will use an external results from the a specified location to use as a baseline for the the current job. If existing build artifacts exist, the combined results will be used for change based testing. The user will need to specify an external result filename (.vcr) in the External Result Filename option. This file would be typically stored in the repository. This external result file could be updated by a main branch or periodic build to establish a current baseline. + +### Additional Tools Other Vector tool integrations are supported by this plugin. -- **PC-lint Plus** -- **Squore** -- **TESTinsights** +- PC-lint Plus +- Squore +- TESTinsights ![](docs/images/additional.png) -- For **PC-lint Plus**, the user must provide the command or script that executes PC-lint Plus analysis. It is important that the following format properties are included to ensure the results file is readable by the Warnings-NG plugin: +#### PC-lint Plus +For [PC-lint Plus](https://pclintplus.com/), the user must provide the command or script that executes PC-lint Plus analysis. It is important that the following format properties are included to ensure the results file is readable by the Warnings-NG plugin: ``` -v // turn off verbosity -width(0) // don't insert line breaks (unlimited output width) -"format=%f(%l): %t %n: %m" -hs1 // The height of a message should be 1 -``` -- For **Squore** analysis, the user must provide the Squore command found on the last page of the Squore project's configuration/build page. -- For **TESTinsights**, if the user is using Git or Subversion for SCM, the plugin will attempt to have the SCM version linked to the TESTinsights project for team access and distributed change based testing. The user must provide the following: +``` +#### Squore +For [Squore](https://www.vector.com/int/en/products/products-a-z/software/squore/) analysis, the user must provide the Squore command found on the last page of the Squore project's configuration/build page. + +#### TESTinsights +For [TESTinsights](https://www.vector.com/int/en/products/products-a-z/software/vectorcast/vectorcast-testinsights), if the user is using Git or Subversion for SCM, the plugin will attempt to have the SCM version linked to the TESTinsights project for team access and distributed change based testing. The user must provide the following: - TESTinsights URL - The URL to TESTinsights server and project (Use Copy Team Area Url). - TESTinsights Project - The Project Name in TESTinsights to push the results (leave blank to use the Jenkins Job Name). - TESTinsights Credential ID - The Credential ID from Jenkins for TESTinsights. - The proxy to push to TESTinsights server in the format **proxy.address:port** (optional) -## Controlling Where Jobs Run +### Controlling Where Jobs Run When using a Pipeline Job, the sub jobs are created to run on specific node related to the compiler chosen for the environment. For example: @@ -123,25 +315,47 @@ Make sure to set the labels on the relevant Jenkins nodes. Manage Jenkins -\> Ma ![](docs/images/restrict_node.png) -## Setup/Configuration +## Build Summary -- VectorCAST must be installed and setup on each node. -- The environment variables **VECTORCAST\_DIR** and **VECTOR\_LICENSE** must be set. -- Jenkins must be installed and setup. -- **BUILD\_URL** must be defined (in Jenkins-\>Manage Jenkins-\>Configure System and define 'Jenkins URL' and save the settings). +The build summary show the following sections: + +- General Jenkins Information including + - Any errors or warnings that occurred during the build will be shown beneath the build number and date + - Build Artifacts including HTML reports, XML reports, pass/fail counts in text file, complete build log + - [Test Results](#test-results) section that can expand to show you test results +- Code Coverage Differences (Only available when using the VectorCAST Code Coverage Plugin) +- VectorCAST Project Incremental Rebuild Report (Only available when using Change Based Testing) +- VectorCAST Project Full Status Report +- VectorCAST Project Metrics Report + +![](docs/images/build_summary_vcc.png) + +## Test Results + +The test results will display which test cases passed, failed, or were skipped during Change-Based Testing. + +By selecting individual cases, you can view the execution reports, providing insight into why a test case failed. + +### Passing Test Case + + + +### Failing Test Case + + ## Known Issues ### VectorCAST Reports and Jenkins Content Security -VectorCAST HTML reports for metrics were updated to use cascading style sheets (CSS) in the 2019 release and 2020 for top level project metrics. This was done to give users more flexibility in what and how metrics are displayed. To maintain single file HTML format, VectorCAST Reports used inline CSS. Inline CSS was disallowed under Jenkins more restrictive CSP. +VectorCAST HTML reports for metrics were updated to use cascading style sheets (CSS) in the 2019 release and 2020 for top level project metrics. This was done to offer users greater flexibility in displaying metrics. To maintain single file HTML format, VectorCAST Reports used inline CSS. Inline CSS was disallowed under Jenkins more restrictive CSP. "Jenkins 1.641 / Jenkins 1.625.3 introduce the `Content-Security-Policy` header to static files served by Jenkins (specifically, `DirectoryBrowserSupport`). This header is set to a very restrictive default set of permissions to protect Jenkins users from malicious HTML/JS files in workspaces, `/userContent`, or archived artifacts." The result of this combination incorrectly formatted the VectorCAST reports. -Numerous options are available to correct this: +There are several available options to correct this: - Use the Jenkins Resource Root URL (Manage Jenkins > Configure System) - Reconfigure VectorCAST Jobs to use external CSS (**VCAST_RPTS_SELF_CONTAINED=FALSE**) combined with enabling anonymous reads from the Manage Jenkins > Configure Global Security > Authorization - Reconfigure the Jenkins Content Security Policy @@ -170,11 +384,23 @@ VectorCAST/QA projects cannot use imported results for change based testing ### Disabled environments may add coverage metrics In rare cases, VectorCAST projects will have disabled environment with results stored before they were disabled. In cases where the disabled environments share source file with enabled environments, this may lead addition coverage metrics. It is recommended to clean the -environment before disabling. This takes into account enviornments that are directly disabled or disabled at the Compiler or TestSuite Nodes. +environment before disabling. This takes into account enviornments that are directly disabled or disabled at the Compiler or TestSuite Nodes. To avoid this, please clean environments before disabling them ## Change Log -### Version 0.77 (26 Dec 2023) +### Version 0.78 (16 Nov 2024) +- Moved to minimum Jenkins version: 2.452.1 and Java 11 +- Adding in following capabilities + - Extended Cobertura format output for use with [Jenkins Coverage Plugin](https://github.com/jenkinsci/coverage-plugin) + - Unit Test Data format output in SonarQube format + - Adding capability to generate an index.html for all .html reports +- Refactored New Job code to reduce duplication +- Added BETA support for RGW3 +- Removed VectorCAST Project Environment report +- Removed extra options for Update job as the plugin doesn't support Update job +- Added a check for bad option combination + +### Version 0.77 (21 Aug 2024) - Updated for findbugs to spotbugs - Fixed changed based testing analysis for compound tests being shown as Skipped - Fixed getjobs.py script to account for disabled compiler/testsuite nodes @@ -189,6 +415,7 @@ environment before disabling. This takes into account enviornments that are dir - Fixed copy_build_dir.py ability to handle relative paths in the database. - Removed duplicate code/variables in NewPipeline.java. - Switched from CustomReport.report_from_api to api.report to solve corner case +- Fixed remote copy of VCAST_VC_SCRIPTS ### Version 0.76 (19 Jan 2023) - Added support in VectorCAST version 2023 Projects for environments that are not in a group diff --git a/docs/images/build_summary_vcc.png b/docs/images/build_summary_vcc.png new file mode 100644 index 00000000..516a5e9e Binary files /dev/null and b/docs/images/build_summary_vcc.png differ diff --git a/docs/images/coverage_display_config.png b/docs/images/coverage_display_config.png new file mode 100644 index 00000000..7a02a9be Binary files /dev/null and b/docs/images/coverage_display_config.png differ diff --git a/docs/images/coverage_plugin_quality_gates.png b/docs/images/coverage_plugin_quality_gates.png new file mode 100644 index 00000000..6a9f9956 Binary files /dev/null and b/docs/images/coverage_plugin_quality_gates.png differ diff --git a/docs/images/individual_test_case_exec.png b/docs/images/individual_test_case_exec.png new file mode 100644 index 00000000..26eae55a Binary files /dev/null and b/docs/images/individual_test_case_exec.png differ diff --git a/docs/images/job_creation_options.png b/docs/images/job_creation_options.png index 6cab6d6f..c5dbedd3 100644 Binary files a/docs/images/job_creation_options.png and b/docs/images/job_creation_options.png differ diff --git a/docs/images/image2017-10-17_18_14_2.png b/docs/images/job_types.png similarity index 100% rename from docs/images/image2017-10-17_18_14_2.png rename to docs/images/job_types.png diff --git a/docs/images/passed_skipped_test.png b/docs/images/passed_skipped_test.png new file mode 100644 index 00000000..d768e528 Binary files /dev/null and b/docs/images/passed_skipped_test.png differ diff --git a/docs/images/pipeline_create.png b/docs/images/pipeline_create.png index 9e92183b..8adbf20d 100644 Binary files a/docs/images/pipeline_create.png and b/docs/images/pipeline_create.png differ diff --git a/docs/images/report_overview_screen.png b/docs/images/report_overview_screen.png new file mode 100644 index 00000000..c12c6223 Binary files /dev/null and b/docs/images/report_overview_screen.png differ diff --git a/docs/images/single.png b/docs/images/single.png index 943ad4c5..ca35fdd9 100644 Binary files a/docs/images/single.png and b/docs/images/single.png differ diff --git a/docs/images/test_results_overview.png b/docs/images/test_results_overview.png new file mode 100644 index 00000000..f3f486f7 Binary files /dev/null and b/docs/images/test_results_overview.png differ diff --git a/docs/images/vcc_cov_report.png b/docs/images/vcc_cov_report.png new file mode 100644 index 00000000..a515f0ca Binary files /dev/null and b/docs/images/vcc_cov_report.png differ diff --git a/pom.xml b/pom.xml index 3d00d8f4..a4cb29c8 100644 --- a/pom.xml +++ b/pom.xml @@ -1,21 +1,18 @@ 4.0.0 - org.jenkins-ci.plugins plugin - 3.54 - + 4.88 + - VectorCAST Execution Run VectorCAST manage jobs from Jenkins vectorcast-execution - 0.77-SNAPSHOT + 0.78-SNAPSHOT hpi https://github.com/jenkinsci/vectorcast-execution-plugin - MIT License @@ -23,25 +20,17 @@ repo - UTF-8 UTF-8 UTF-8 - 3.0.4 false - - 2.289.3 - 8 - 2.56 - 1.6.2 + 2.462.3 - Vector Informatik, GmbH https://www.vector.com/ - TimSVector @@ -50,19 +39,21 @@ Vector Informatik, GmbH - scm:git:https://github.com/jenkinsci/vectorcast-execution-plugin.git scm:git:https://github.com/jenkinsci/vectorcast-execution-plugin.git https://github.com/jenkinsci/vectorcast-execution-plugin HEAD - repo.jenkins-ci.org https://repo.jenkins-ci.org/public/ + + incremental.jenkins-ci.org + https://repo.jenkins-ci.org/incrementals/ + @@ -70,255 +61,196 @@ https://repo.jenkins-ci.org/public/ - io.jenkins.tools.bom - bom-2.289.x - 1246.va_b_50630c1d19 - import + bom-2.462.x + 3387.v0f2773fa_3200 pom - + - - - org.jenkins-ci.plugins.workflow - workflow-aggregator - 2.5 - - org.jenkinsci.plugins - pipeline-model-api - 1.9.3 + io.jenkins.plugins + warnings-ng + 11.10.0 - - org.jenkins-ci.plugins.workflow - workflow-job - 1145.v7f2433caa07f - test - + - org.mockito - mockito-all - 1.10.19 - test + io.jenkins.plugins + coverage + 1.16.1 + - org.powermock - powermock-core - ${powermock.version} - test + org.jenkins-ci.plugins + vectorcast-coverage + 0.22 + - org.powermock - powermock-module-junit4 - ${powermock.version} - test + org.jvnet.hudson.plugins + groovy-postbuild + 264.vf6e02a_77d5b_c + - org.powermock - powermock-api-mockito - ${powermock.version} - test + org.jenkins-ci.plugins + copyartifact + 749.vfb_dca_a_9b_6549 + - org.powermock - powermock-reflect - ${powermock.version} - test + org.jenkins-ci.plugins + ws-cleanup + 0.46 - - com.google.code.findbugs - jsr305 - 3.0.1 - test - - com.google.code.findbugs - annotations - 3.0.1 - test + com.github.spotbugs + spotbugs-annotations + 4.8.6 - org.jenkins-ci.plugins - vectorcast-coverage - 0.21 + org.mockito + mockito-core + 5.14.1 + test - org.jvnet.hudson.plugins - groovy-postbuild - 2.4 + org.jenkins-ci.plugins + credentials-binding + 681.vf91669a_32e45 + + - org.jenkins-ci.plugins.workflow - workflow-cps + org.jenkins-ci.plugins + junit + 1300.v03d9d8a_cf1fb_ + + + org.jenkins-ci.plugins - copyartifact - 1.44 + display-url-api + 2.204.vf6fddd8a_8b_e9 + org.jenkins-ci.main maven-plugin - 3.4 + 3.23 + - org.jenkins-ci.plugins - ws-cleanup - 0.28 + io.jenkins.plugins + commons-text-api + 1.12.0-129.v99a_50df237f7 + - commons-io - commons-io - 2.11.0 + org.jenkins-ci.plugins + trilead-api + 2.147.vb_73cc728a_32e - - io.jenkins.plugins - warnings-ng - 9.11.1 - - - org.slf4j - slf4j-api - 1.7.36 - - - org.slf4j - jcl-over-slf4j - 1.7.36 - - - org.slf4j - slf4j-simple - 1.6.2 - - - com.github.spotbugs - spotbugs-annotations - 4.6.0 - - - io.jenkins.plugins - echarts-api - 5.3.0-2 - - - org.ow2.asm - asm-analysis - 9.3 - - - org.ow2.asm - asm-tree - 9.3 - - - org.slf4j - log4j-over-slf4j - 1.7.36 - - - org.slf4j - slf4j-jdk14 - 1.7.36 - test - - - org.jenkins-ci - annotation-indexer - 1.16 - - - org.kohsuke - access-modifier-annotation - 1.27 - provided - - - org.json - json - 20230227 - - - io.jenkins.plugins - forensics-api - 1.12.0 - - - io.jenkins.plugins - bootstrap5-api - 5.1.3-6 - - - io.jenkins.plugins - data-tables-api - 1.11.4-4 - - - org.apache.commons - commons-lang3 - 3.12.0 - - - org.apache.ant - ant - 1.10.12 - - - org.hamcrest - hamcrest - 2.2 - test - - - org.jenkins-ci.plugins - pipeline-utility-steps - - - org.codehaus.plexus - plexus-utils - 3.4.1 - + + + io.jenkins.plugins + caffeine-api + 3.1.8-133.v17b_1ff2e0599 + + + io.jenkins.plugins + commons-lang3-api + 3.17.0-84.vb_b_938040b_078 + + + org.jenkins-ci.plugins.workflow + workflow-support + 930.vf51d22b_ce488 + + + + org.jenkins-ci.plugins.workflow + workflow-cps + 3969.vdc9d3a_efcc6a_ + - + + + + lint + + -Xlint:all,-processing + + + + jacoco + + + + org.jacoco + jacoco-maven-plugin + 0.8.12 + + + + prepare-agent + + + + + report + test + + report + + + + + + + + - org.apache.maven.plugins - maven-release-plugin - 3.0.0-M1 + org.apache.maven.plugins + maven-release-plugin + 3.0.0-M1 + + - org.apache.maven.plugins - maven-scm-plugin - 1.11.2 - - connection - + org.apache.maven.plugins + maven-scm-plugin + 2.1.0 + + connection + org.apache.maven.plugins maven-compiler-plugin - 2.3.2 + 3.13.0 1.8 1.8 + + ${lintCompilerArgs} + org.codehaus.mojo build-helper-maven-plugin - - add-localizer-source-folder generate-sources @@ -333,45 +265,42 @@ - org.jenkins-ci.tools maven-hpi-plugin + 3.55 true - - 2.0 - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.4 + com.github.spotbugs + spotbugs-maven-plugin + 4.8.5.0 true - ${findbugs.failOnError} + false - run-findbugs - verify + run-spotbugs + verify + + check + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs - check + jar - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java index ecc6be7a..bacdd782 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBase.java @@ -33,33 +33,34 @@ import jenkins.model.Jenkins; /** - * Base job + * Base job. */ -public abstract class JobBase implements ExtensionPoint, Action, Describable { - /** SCM to use initially */ +public abstract class JobBase implements ExtensionPoint, Action, + Describable { + /** SCM to use initially. */ private SCM scm; /** - * Default Constructor + * Default Constructor. */ public JobBase() { scm = new NullSCM(); } /** - * Get the SCM + * Get the SCM. * @return the SCM */ public SCM getTheScm() { return scm; } /** - * Set the SCM object - * @param scm new SCM + * Set the SCM object. + * @param inScm new SCM */ - public void setTheScm(SCM scm) { - this.scm = scm; + public void setTheScm(final SCM inScm) { + this.scm = inScm; } /** - * Default icon name + * Default icon name. * @return icon name */ @Override @@ -67,7 +68,7 @@ public String getIconFileName() { return "/plugin/vectorcast-execution/icons/vector_favicon.png"; } /** - * Default URL name + * Default URL name. * @return url name */ @Override @@ -83,17 +84,12 @@ public String getDisplayName() { return getClass().getSimpleName(); } /** - * Default descriptor + * Default descriptor. * @return descriptor */ @Override public JobBaseDescriptor getDescriptor() { - Jenkins instance = Jenkins.getInstance(); - if (instance == null) { - return null; - } else { - return (JobBaseDescriptor) instance.getDescriptorOrDie(getClass()); - } + return (JobBaseDescriptor) Jenkins.get().getDescriptorOrDie(getClass()); } /** @@ -101,11 +97,6 @@ public JobBaseDescriptor getDescriptor() { * @return all extensions based on JobBase */ public static ExtensionList all() { - Jenkins instance = Jenkins.getInstance(); - if (instance == null) { - return null; - } else { - return instance.getExtensionList(JobBase.class); - } + return Jenkins.get().getExtensionList(JobBase.class); } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBaseDescriptor.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBaseDescriptor.java index ec5b7186..48c6bb95 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBaseDescriptor.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/JobBaseDescriptor.java @@ -26,9 +26,13 @@ import hudson.model.Descriptor; /** - * Base descriptor for the VectorCAST jobs + * Base descriptor for the VectorCAST jobs. */ public abstract class JobBaseDescriptor extends Descriptor { + /** + * Gets the display name. + * @return String display name + */ @Override public String getDisplayName() { return clazz.getSimpleName(); diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand.java index b9d76cf9..69ba77b9 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTCommand.java @@ -44,81 +44,101 @@ /** * This class allows a command script to be specified for both Linux and Windows - * and the build step will test and run the correct command + * and the build step will test and run the correct command. */ public class VectorCASTCommand extends Builder implements SimpleBuildStep { + /** windows environment setup command. */ private final String winCommand; + + /** unix environment setup command. */ private final String unixCommand; /** - * Get the windows variant of the command - * @return windows command + * Get the windows variant of the command. + * @return windows command. */ public final String getWinCommand() { return winCommand; } /** - * Get the Unix variant of the command - * @return unix command + * Get the Unix variant of the command. + * @return unix command. */ public final String getUnixCommand() { return unixCommand; } - + /** - * Create a VectorCAST command + * Create a VectorCAST command. * @param winCommand the windows variant of the command * @param unixCommand the unix variant of the command */ @DataBoundConstructor - public VectorCASTCommand(String winCommand, String unixCommand) { + @SuppressWarnings("checkstyle:HiddenField") + public VectorCASTCommand(final String winCommand, + final String unixCommand) { this.winCommand = winCommand; this.unixCommand = unixCommand; } - + + /** + * Perform the script to run the job. + * @param build info + * @param workspace info + * @param launcher info + * @param listener info + */ @Override - public void perform(Run build, FilePath workspace, Launcher launcher, TaskListener listener) { + public void perform(final Run build, final FilePath workspace, + final Launcher launcher, final TaskListener listener) { // Windows check and run batch command - // - // Get the windows batch command and run it if this node is Windows - // if (!launcher.isUnix()) { + // Get the windows batch command and run it if this node is Windows + // String windowsCmd = getWinCommand(); BatchFile batchFile = new BatchFile(windowsCmd); try { - if (!batchFile.perform((AbstractBuild)build, launcher, (BuildListener)listener)) { + if (!batchFile.perform((AbstractBuild) build, + launcher, (BuildListener) listener)) { build.setResult(Result.FAILURE); } } catch (InterruptedException ex) { - Logger.getLogger(VectorCASTCommand.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(VectorCASTCommand.class.getName()) + .log(Level.SEVERE, null, ex); build.setResult(Result.FAILURE); } } - // + // Linux check and batch command - // - // Get the Linux/Unix batch command and run it if this node is not Windows - // if (launcher.isUnix()) { + // Get the Linux/Unix batch command and + // run it if this node is not Windows String unixCmd = getUnixCommand(); Shell shell = new Shell(unixCmd); try { - if (!shell.perform((AbstractBuild)build, launcher, (BuildListener)listener)) { + if (!shell.perform((AbstractBuild) build, + launcher, (BuildListener) listener)) { build.setResult(Result.FAILURE); } } catch (InterruptedException ex) { - Logger.getLogger(VectorCASTCommand.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(VectorCASTCommand.class.getName()). + log(Level.SEVERE, null, ex); build.setResult(Result.FAILURE); } } } + /** + * Get the descriptor. + * @return descriptor + */ + @Override public DescriptorImpl getDescriptor() { - return (DescriptorImpl)super.getDescriptor(); + return (DescriptorImpl) super.getDescriptor(); } /** @@ -126,18 +146,26 @@ public DescriptorImpl getDescriptor() { * The class is marked as public so that it can be accessed from views. */ @Extension - public static final class DescriptorImpl extends BuildStepDescriptor { + public static final class DescriptorImpl extends + BuildStepDescriptor { /** - * In order to load the persisted global configuration, you have to + * In order to load the persisted global configuration, you have to * call load() in the constructor. */ public DescriptorImpl() { load(); } + /** + * Override to fill out the class. + * @param aClass - generic class + * @return boolean - always true + */ @Override - public boolean isApplicable(Class aClass) { - // Indicates that this builder can be used with all kinds of project types + public boolean isApplicable( + final Class aClass) { + // Indicates that this builder can be used + // with all kinds of project types return true; } @@ -152,4 +180,3 @@ public String getDisplayName() { } } - diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag.java index 1813f82c..6b5c1297 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobDiag.java @@ -36,15 +36,22 @@ import org.kohsuke.stapler.interceptor.RequirePOST; /** - * Create VectorCAST diagnostic job + * Create VectorCAST diagnostic job. */ @Extension public class VectorCASTJobDiag extends JobBase { - /** Name of diagnostic job */ + + /** The request from jenkins. */ + private StaplerRequest jenkinsRequest; + + /** The response to jenkins. */ + private StaplerResponse jenkinsResponse; + + /** Name of diagnostic job. */ public static final String PROJECT_NAME = "VectorCAST-Diagnostics"; - + /** - * Get the diagnostics job URL + * Get the diagnostics job URL. * @return url */ @Override @@ -56,161 +63,212 @@ public String getUrlName() { public static final class DescriptorImpl extends JobBaseDescriptor { } /** - * Check if the diagnostics job exists + * Check if the diagnostics job exists. * @return true if it exists and false if not */ public boolean isExists() { - Jenkins instance = Jenkins.getInstance(); - if (instance != null && instance.getJobNames().contains(PROJECT_NAME)) { - return true; - } else { - return false; - } + Jenkins instance = Jenkins.get(); + + return instance.getJobNames().contains(PROJECT_NAME); } /** - * Create the diagnostics job + * Gets the configuration for a unix diagnostic job. + * @return String for unix diagnostic job + */ + private String getUnixCommand() { + return "#!/bin/sh\n" + + "\n" + + "echo\n" + + "echo\n" + + "\n" + + "RET_VAL=0\n" + + "if [ \"$VECTORCAST_DIR\" = \"\" ] ; then\n" + + " echo\n" + + " echo VECTORCAST_DIR...ERROR\n" + + " echo \" Environment Variable not set. Either set " + + "VECTORCAST_DIR in System Environment Variables or add " + + "to Jenkins Configuration\"\n" + + " echo\n" + + " RET_VAL=$(($RET_VAL-1))\n" + + " exit $RET_VAL\n" + + "else\n" + + " echo VECTORCAST_DIR...OKAY\n" + + " echo VECTORCAST_DIR = $VECTORCAST_DIR\n" + + "fi\n" + + "\n" + + "if [ \"$JENKINS_URL\" = \"\" ] ; then\n" + + " echo\n" + + " echo JENKINS_URL...ERROR\n" + + " echo \" Environment Variable not set. Define the " + + "URL in Jenkins configuration\"\n" + + " echo\n" + + " RET_VAL=$(($RET_VAL-1))\n" + + " exit $RET_VAL\n" + + "else\n" + + " echo JENKINS_URL...OKAY\n" + + " echo JENKINS_URL = $JENKINS_URL\n" + + "fi\n" + + "\n" + + "if [ \"$VECTOR_LICENSE_FILE\" = \"\" ] ; then\n" + + " if [ \"$LM_LICENSE_FILE\" = \"\" ] ] ; then\n" + + " echo\n" + + " echo License Environment Variable...ERROR\n" + + " echo \" Neither VECTOR_LICENSE_FILE nor " + + "LM_LICENSE_FILE environment variable set...\"\n" + + " echo \" ...Set either VECTOR_LICENSE_FILE or " + + "LM_LICENSE_FILE in System Environment Variables or add " + + "to Jenkins Configuration\"\n" + + " RET_VAL=$(($RET_VAL-1))\n" + + " exit $REV_VAL\n" + + " else\n" + + " echo License Environment Variable...OKAY\n" + + " fi \n" + + "else \n" + + " echo License Environment Variable...OKAY\n" + + "fi\n" + + "\n" + + "$VECTORCAST_DIR/manage --help > help.log\n" + + "\n" + + "if [ \"$?\" != \"0\" ] ; then\n" + + " echo\n" + + " echo VectorCAST Project License...ERROR\n" + + " echo Error Starting VectorCAST Project. Check " + + "the log below for details\n" + + " echo\n" + + " cat help.log\n" + + " echo\n" + + " RET_VAL=$(($RET_VAL-1))\n" + + "else\n" + + " echo VectorCAST Project License...OKAY\n" + + "fi\n" + + "\n" + + "rm -rf help.log\n" + + "\n" + + "exit $RET_VAL"; + } + + /** + * Gets the configuration for a windows diagnostic job. + * @return String for windows diagnostic job + */ + private String getWindowsCommand() { + return "@echo off\n" + + "\n" + + "echo.\n" + + "echo.\n" + + "\n" + + "set RET_VAL=0\n" + + "if \"%VECTORCAST_DIR%\"==\"\" (\n" + + " echo.\n" + + " echo VECTORCAST_DIR...ERROR\n" + + " echo Environment Variable not set. Either set " + + "VECTORCAST_DIR in System Environment Variables or add" + + "to Jenkins Configuration\n" + + " echo.\n" + + " set /a RET_VAL=%RET_VAL%-1\n" + + " goto end\n" + + ") else (\n" + + " echo VECTORCAST_DIR...OKAY\n" + + " echo VECTORCAST_DIR = %VECTORCAST_DIR%\n" + + ")\n" + + "\n" + + "if \"%JENKINS_URL%\"==\"\" (\n" + + " echo.\n" + + " echo JENKINS_URL...ERROR\n" + + " echo Environment Variable not set. Define the URL" + + " in Jenkins configuration\n" + + " echo.\n" + + " set /a RET_VAL=%RET_VAL%-1\n" + + " goto end\n" + + ") else (\n" + + " echo JENKINS_URL...OKAY\n" + + " echo JENKINS_URL = %JENKINS_URL%\n" + + ")\n" + + "\n" + + "if \"%VECTOR_LICENSE_FILE%\"==\"\" ( \n" + + " if \"%LM_LICENSE_FILE%\"==\"\" (\n" + + " echo.\n" + + " echo License Environment Variable...ERRRO\n" + + " echo Neither VECTOR_LICENSE_FILE nor " + + "LM_LICENSE_FILE environment variable set...\n" + + " echo ...Set either VECTOR_LICENSE_FILE or " + + "LM_LICENSE_FILE in System Environment Variables or add " + + "to Jenkins Configuration\n" + + " echo.\n" + + " set /a RET_VAL=%RET_VAL%-1\n" + + " goto end\n" + + " ) else (\n" + + " echo License Environment Variable...OKAY\n" + + " )\n" + + ") else (\n" + + " echo License Environment Variable...OKAY\n" + + ")\n" + + "\n" + + "%VECTORCAST_DIR%\\manage --help > help.log\n" + + "if \"%errorlevel%\"==\"1\" (\n" + + " echo.\n" + + " echo VectorCAST Project License...ERROR\n" + + " echo Error Starting VectorCAST Project. Check " + + "the log below for details\n" + + " echo.\n" + + " type help.log\n" + + " echo.\n" + + " set /a RET_VAL=%RET_VAL%-1\n" + + ") else (\n" + + " echo VectorCAST Project License...OKAY\n" + + ")\n" + + "\n" + + ":end\n" + + "\n" + + "@echo off\n" + + "\n" + + "\n" + + "EXIT /B %RET_VAL%"; + } + + /** + * Get response. + * @return response + */ + protected StaplerResponse getResponse() { + return jenkinsResponse; + } + + /** + * Get request. + * @return request + */ + protected StaplerRequest getRequest() { + return jenkinsRequest; + } + + /** + * Create the diagnostics job. * @param request request objext * @param response response object - * @return response + * @return http response * @throws ServletException exception * @throws IOException exception * @throws hudson.model.Descriptor.FormException exception */ @RequirePOST - public HttpResponse doCreate(final StaplerRequest request, final StaplerResponse response) throws ServletException, IOException, Descriptor.FormException { - Jenkins instance = Jenkins.getInstance(); - if (instance != null && !instance.getJobNames().contains(PROJECT_NAME)) { - FreeStyleProject project = instance.createProject(FreeStyleProject.class, PROJECT_NAME); - String winCommand = -"@echo off\n" + -"\n" + -"echo.\n" + -"echo.\n" + -"\n" + -"set RET_VAL=0\n" + -"if \"%VECTORCAST_DIR%\"==\"\" (\n" + -" echo.\n" + -" echo VECTORCAST_DIR...ERROR\n" + -" echo Environment Variable not set. Either set VECTORCAST_DIR in System Environment Variables or add to Jenkins Configuration\n" + -" echo.\n" + -" set /a RET_VAL=%RET_VAL%-1\n" + -" goto end\n" + -") else (\n" + -" echo VECTORCAST_DIR...OKAY\n" + -" echo VECTORCAST_DIR = %VECTORCAST_DIR%\n" + -")\n" + -"\n" + -"if \"%JENKINS_URL%\"==\"\" (\n" + -" echo.\n" + -" echo JENKINS_URL...ERROR\n" + -" echo Environment Variable not set. Define the URL in Jenkins configuration\n" + -" echo.\n" + -" set /a RET_VAL=%RET_VAL%-1\n" + -" goto end\n" + -") else (\n" + -" echo JENKINS_URL...OKAY\n" + -" echo JENKINS_URL = %JENKINS_URL%\n" + -")\n" + -"\n" + -"if \"%VECTOR_LICENSE_FILE%\"==\"\" ( \n" + -" if \"%LM_LICENSE_FILE%\"==\"\" (\n" + -" echo.\n" + -" echo License Environment Variable...ERRRO\n" + -" echo Neither VECTOR_LICENSE_FILE nor LM_LICENSE_FILE environment variable set...\n" + -" echo ...Set either VECTOR_LICENSE_FILE or LM_LICENSE_FILE in System Environment Variables or add to Jenkins Configuration\n" + -" echo.\n" + -" set /a RET_VAL=%RET_VAL%-1\n" + -" goto end\n" + -" ) else (\n" + -" echo License Environment Variable...OKAY\n" + -" )\n" + -") else (\n" + -" echo License Environment Variable...OKAY\n" + -")\n" + -"\n" + -"%VECTORCAST_DIR%\\manage --help > help.log\n" + -"if \"%errorlevel%\"==\"1\" (\n" + -" echo.\n" + -" echo VectorCAST Project License...ERROR\n" + -" echo Error Starting VectorCAST Project. Check the log below for details\n" + -" echo.\n" + -" type help.log\n" + -" echo.\n" + -" set /a RET_VAL=%RET_VAL%-1\n" + -") else (\n" + -" echo VectorCAST Project License...OKAY\n" + -")\n" + -"\n" + -":end\n" + -"\n" + -"@echo off\n" + -"\n" + -"\n" + -"EXIT /B %RET_VAL%"; - String unixCommand = -"#!/bin/sh\n" + -"\n" + -"echo\n" + -"echo\n" + -"\n" + -"RET_VAL=0\n" + -"if [ \"$VECTORCAST_DIR\" = \"\" ] ; then\n" + -" echo\n" + -" echo VECTORCAST_DIR...ERROR\n" + -" echo \" Environment Variable not set. Either set VECTORCAST_DIR in System Environment Variables or add to Jenkins Configuration\"\n" + -" echo\n" + -" RET_VAL=$(($RET_VAL-1))\n" + -" exit $RET_VAL\n" + -"else\n" + -" echo VECTORCAST_DIR...OKAY\n" + -" echo VECTORCAST_DIR = $VECTORCAST_DIR\n" + -"fi\n" + -"\n" + -"if [ \"$JENKINS_URL\" = \"\" ] ; then\n" + -" echo\n" + -" echo JENKINS_URL...ERROR\n" + -" echo \" Environment Variable not set. Define the URL in Jenkins configuration\"\n" + -" echo\n" + -" RET_VAL=$(($RET_VAL-1))\n" + -" exit $RET_VAL\n" + -"else\n" + -" echo JENKINS_URL...OKAY\n" + -" echo JENKINS_URL = $JENKINS_URL\n" + -"fi\n" + -"\n" + -"if [ \"$VECTOR_LICENSE_FILE\" = \"\" ] ; then\n" + -" if [ \"$LM_LICENSE_FILE\" = \"\" ] ] ; then\n" + -" echo\n" + -" echo License Environment Variable...ERROR\n" + -" echo \" Neither VECTOR_LICENSE_FILE nor LM_LICENSE_FILE environment variable set...\"\n" + -" echo \" ...Set either VECTOR_LICENSE_FILE or LM_LICENSE_FILE in System Environment Variables or add to Jenkins Configuration\"\n" + -" RET_VAL=$(($RET_VAL-1))\n" + -" exit $REV_VAL\n" + -" else\n" + -" echo License Environment Variable...OKAY\n" + -" fi \n" + -"else \n" + -" echo License Environment Variable...OKAY\n" + -"fi\n" + -"\n" + -"$VECTORCAST_DIR/manage --help > help.log\n" + -"\n" + -"if [ \"$?\" != \"0\" ] ; then\n" + -" echo\n" + -" echo VectorCAST Project License...ERROR\n" + -" echo Error Starting VectorCAST Project. Check the log below for details\n" + -" echo\n" + -" cat help.log\n" + -" echo\n" + -" RET_VAL=$(($RET_VAL-1))\n" + -"else\n" + -" echo VectorCAST Project License...OKAY\n" + -"fi\n" + -"\n" + -"rm -rf help.log\n" + -"\n" + -"exit $RET_VAL"; - VectorCASTCommand cmd = new VectorCASTCommand(winCommand, unixCommand); + public HttpResponse doCreate(final StaplerRequest request, + final StaplerResponse response) throws ServletException, + IOException, Descriptor.FormException { + Jenkins j = Jenkins.get(); + + this.jenkinsRequest = request; + this.jenkinsResponse = response; + + if (j != null && !j.getJobNames().contains(PROJECT_NAME)) { + FreeStyleProject project = j.createProject( + FreeStyleProject.class, PROJECT_NAME); + + String winCommand = getWindowsCommand(); + String unixCommand = getUnixCommand(); + + VectorCASTCommand cmd = + new VectorCASTCommand(winCommand, unixCommand); project.getBuildersList().add(cmd); project.save(); } @@ -218,3 +276,4 @@ public HttpResponse doCreate(final StaplerRequest request, final StaplerResponse return new HttpRedirect("done"); } } + diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobPipeline.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobPipeline.java index 3eca0bb3..2f429516 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobPipeline.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobPipeline.java @@ -29,8 +29,7 @@ import com.vectorcast.plugins.vectorcastexecution.job.ScmConflictException; import com.vectorcast.plugins.vectorcastexecution.job.ExternalResultsFileException; import com.vectorcast.plugins.vectorcastexecution.job.NewPipelineJob; - - +import com.vectorcast.plugins.vectorcastexecution.job.BadOptionComboException; import hudson.Extension; import hudson.model.Descriptor; @@ -45,47 +44,47 @@ import org.kohsuke.stapler.interceptor.RequirePOST; /** - * Create multiple jobs + * Create multiple jobs. */ @Extension public class VectorCASTJobPipeline extends JobBase { - /** Job exists exception */ + /** Job exists exception. */ private JobAlreadyExistsException exception; - /** Job exists exception */ + /** Job exists exception. */ private ScmConflictException scmException; - - /** Job exists exception */ + + /** Job exists exception. */ private ExternalResultsFileException extResException; - - /** project name */ - private String projectName; - /** Pipeline job object */ + /** project name. */ + private String projectName; + + /** Pipeline job object. */ private NewPipelineJob job; /** - * Get the pipeline job object + * Get the pipeline job object. * @return pipeline job */ public NewPipelineJob getJob() { return job; } /** - * Get the project name + * Get the project name. * @return project name */ public String getProjectName() { return projectName; } /** - * Get the job already exists exception + * Get the job already exists exception. * @return job already exists exception */ public JobAlreadyExistsException getException() { return exception; } /** - * Get the job already scm conflict exception + * Get the job already scm conflict exception. * @return job already scm conflict exception */ public ScmConflictException getScmException() { @@ -93,7 +92,7 @@ public ScmConflictException getScmException() { } /** - * Get the job already scm conflict exception + * Get the job already scm conflict exception. * @return job already scm conflict exception */ public ExternalResultsFileException getResException() { @@ -101,7 +100,7 @@ public ExternalResultsFileException getResException() { } /** - * URL for creating pipeline job + * URL for creating pipeline job. * @return url */ @Override @@ -113,7 +112,7 @@ public String getUrlName() { public static final class DescriptorImpl extends JobBaseDescriptor { } /** - * Create pipeline job + * Create pipeline job. * @param request request objext * @param response response object * @return response @@ -122,26 +121,33 @@ public static final class DescriptorImpl extends JobBaseDescriptor { * @throws hudson.model.Descriptor.FormException exception */ @RequirePOST - public HttpResponse doCreate(final StaplerRequest request, final StaplerResponse response) throws ServletException, IOException, Descriptor.FormException { + public HttpResponse doCreate(final StaplerRequest request, + final StaplerResponse response) + throws ServletException, IOException, Descriptor.FormException { try { // Create Pipeline job job = new NewPipelineJob(request, response); - job.create(false); + job.create(); projectName = job.getProjectName(); - Logger.getLogger(VectorCASTJobPipeline.class.getName()).log(Level.SEVERE, "Pipeline Project Name: " + projectName, "Pipeline Project Name: " + projectName); + Logger.getLogger(VectorCASTJobPipeline.class.getName()) + .log(Level.SEVERE, "Pipeline Project Name: " + projectName, + "Pipeline Project Name: " + projectName); return new HttpRedirect("created"); } catch (ScmConflictException ex) { scmException = ex; return new HttpRedirect("conflict"); - }catch (JobAlreadyExistsException ex) { + } catch (JobAlreadyExistsException ex) { exception = ex; return new HttpRedirect("exists"); } catch (InvalidProjectFileException ex) { - // cannot happen on pipeline job as we don't read the project + // cannot happen on pipeline job as we don't read the project return new HttpRedirect("exists"); } catch (ExternalResultsFileException ex) { - // blank external results file exception + // blank external results file exception return new HttpRedirect("extresblank"); + } catch (BadOptionComboException ex) { + // blank external results file exception + return new HttpRedirect("badoptioncombo"); } } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java index 07a5aa30..161ceee3 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobRoot.java @@ -28,8 +28,6 @@ import java.util.List; import jenkins.model.Jenkins; -import java.util.logging.Level; -import java.util.logging.Logger; import hudson.security.Permission; import hudson.security.PermissionGroup; import hudson.security.PermissionScope; @@ -37,62 +35,76 @@ import com.vectorcast.plugins.vectorcastexecution.common.VcastUtils; /** - * Top level of VectorCAST job control + * Top level of VectorCAST job control. */ @Extension public class VectorCASTJobRoot implements RootAction { - - public static final PermissionGroup PERMISSIONS_GROUP = new PermissionGroup( - VectorCASTJobRoot.class,Messages._VectorCASTRootAction_PermissionGroup()); - private static final PermissionScope scope[] = {PermissionScope.JENKINS}; - public static final Permission VIEW = new Permission(PERMISSIONS_GROUP, - "View", Messages._VectorCASTRootAction_ViewPermissionDescription(), - Jenkins.ADMINISTER, true, scope); - - + + /** Permission for Jenkins. */ + public static final PermissionGroup PERMISSIONS_GROUP = + new PermissionGroup(VectorCASTJobRoot.class, + Messages._VectorCASTRootAction_PermissionGroup()); + + /** Permission Scope for Jenkins. */ + private static final PermissionScope[] SCOPE = {PermissionScope.JENKINS}; + + /** Permission View for Jenkins. */ + public static final Permission VIEW = new Permission(PERMISSIONS_GROUP, + "View", Messages._VectorCASTRootAction_ViewPermissionDescription(), + Jenkins.ADMINISTER, true, SCOPE); + + /** * Get the icon to use. * @return icon to use or null if user does not have permissions */ + @Override public String getIconFileName() { - Boolean permission = false; + final int colorChangeMinor = 361; + final int colorChangeMajor = 2; + boolean permission = false; + if (Jenkins.get().hasPermission(VIEW)) { permission = true; } - + // Always display - assume that Jenkins permission checking // will catch and report any permissions issues if (permission) { String iconName; - String jenkinsVersion = Jenkins.getInstance().VERSION; - String version[] = jenkinsVersion.split("\\."); - Integer major, minor; - Boolean colorIcon = true; + String jenkinsVersion = Jenkins.VERSION; + String[] version = jenkinsVersion.split("\\."); + int major; + int minor; + boolean colorIcon = true; try { major = Integer.parseInt(version[0]); minor = Integer.parseInt(version[1]); - if ((major >= 2) && (minor >=361)) { + if ((major >= colorChangeMajor) + && (minor >= colorChangeMinor)) { colorIcon = false; } } catch (Exception e) { e.printStackTrace(); } - + if (colorIcon) { - iconName = "/plugin/vectorcast-execution/icons/vector_favicon.png"; + iconName = + "/plugin/vectorcast-execution/icons/vector_favicon.png"; } else { - iconName = "/plugin/vectorcast-execution/icons/vector_favicon_bw.png"; + iconName = + "/plugin/vectorcast-execution/icons/vector_favicon_bw.png"; } - + return iconName; } else { return null; } } /** - * Display name for the top-level action/menu-item + * Display name for the top-level action/menu-item. * @return display name */ @Override @@ -100,7 +112,7 @@ public String getDisplayName() { return Messages.VectorCASTCommand_AddVCJob(); } /** - * Get name of top-level action/url + * Get name of top-level action/url. * @return url */ @Override @@ -112,26 +124,27 @@ public String getUrlName() { * @return version */ public String getVersion() { - return VcastUtils.getVersion().orElse( "Error - Could not determine version" ); + return VcastUtils.getVersion(). + orElse("Error - Could not determine version"); } /** - * Get dynamic 'job' - used by Stapler + * Get dynamic 'job' - used by Stapler. * @param name name to find * @return dynamic job */ - public JobBase getDynamic(String name) { - for (JobBase ui : getAll()) - try { - if (ui.getUrlName().equals(name)) - return ui; - } catch (NullPointerException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + public JobBase getDynamic(final String name) { + for (JobBase ui : getAll()) { + if (ui != null) { + String urlName = ui.getUrlName(); + if (urlName != null && urlName.equals(name)) { + return ui; + } } + } return null; } /** - * Get all actions associated with this URL + * Get all actions associated with this URL. * @return list of actions */ public List getAll() { diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobSingle.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobSingle.java index 81642379..aff195d7 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobSingle.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTJobSingle.java @@ -26,6 +26,7 @@ import com.vectorcast.plugins.vectorcastexecution.job.InvalidProjectFileException; import com.vectorcast.plugins.vectorcastexecution.job.JobAlreadyExistsException; import com.vectorcast.plugins.vectorcastexecution.job.ExternalResultsFileException; +import com.vectorcast.plugins.vectorcastexecution.job.BadOptionComboException; import com.vectorcast.plugins.vectorcastexecution.job.NewSingleJob; import hudson.Extension; import hudson.model.Descriptor; @@ -40,30 +41,31 @@ import org.kohsuke.stapler.interceptor.RequirePOST; /** - * Create single job + * Create single job. */ @Extension public class VectorCASTJobSingle extends JobBase { - /** Job already exists exception */ + /** Job already exists exception. */ private JobAlreadyExistsException exception; - /** Project name */ + /** Project name. */ private String projectName; + /** - * Get the project name + * Get the project name. * @return project name */ public String getProjectName() { return projectName; } /** - * Get job already exists exception + * Get job already exists exception. * @return exception */ public JobAlreadyExistsException getException() { return exception; } /** - * Get url name for creating single job + * Get url name for creating single job. * @return url */ @Override @@ -71,11 +73,14 @@ public String getUrlName() { return "single-job"; } + /** + * Extension of JobBaseDescriptor. + */ @Extension public static final class DescriptorImpl extends JobBaseDescriptor { } /** - * Create the single job + * Create the single job. * @param request request object * @param response response object * @return response @@ -84,12 +89,14 @@ public static final class DescriptorImpl extends JobBaseDescriptor { * @throws hudson.model.Descriptor.FormException exception */ @RequirePOST - public HttpResponse doCreate(final StaplerRequest request, final StaplerResponse response) throws ServletException, IOException, Descriptor.FormException { + public HttpResponse doCreate(final StaplerRequest request, + final StaplerResponse response) + throws ServletException, IOException, Descriptor.FormException { try { // Create single-job NewSingleJob job = new NewSingleJob(request, response); - job.create(false); + job.create(); projectName = job.getProjectName(); return new HttpRedirect("created"); } catch (JobAlreadyExistsException ex) { @@ -97,10 +104,14 @@ public HttpResponse doCreate(final StaplerRequest request, final StaplerResponse return new HttpRedirect("exists"); } catch (InvalidProjectFileException ex) { // Can't happen for the single job - Logger.getLogger(VectorCASTJobSingle.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(VectorCASTJobSingle.class.getName()) + .log(Level.SEVERE, null, ex); return new HttpRedirect("exists"); } catch (ExternalResultsFileException ex) { return new HttpRedirect("extresblank"); + } catch (BadOptionComboException ex) { + // blank external results file exception + return new HttpRedirect("badoptioncombo"); } } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java index eb4a4238..66af43bc 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/VectorCASTSetup.java @@ -31,8 +31,6 @@ import hudson.model.AbstractProject; import hudson.model.Run; import hudson.model.TaskListener; -import hudson.scm.NullSCM; -import hudson.scm.SCM; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import java.io.File; @@ -51,734 +49,81 @@ import hudson.EnvVars; /** - * VectorCAST setup build action + * VectorCAST setup build action. */ public class VectorCASTSetup extends Builder implements SimpleBuildStep { - /** script directory */ + /** script directory. */ private static final String SCRIPT_DIR = "/scripts/"; - /** Environment setup for windows */ - private String environmentSetupWin; - /** Environment setup for unix */ - private String environmentSetupUnix; - /** Execute preamble for windows */ - private String executePreambleWin; - /** Execute preamble for unix */ - private String executePreambleUnix; - /** Environment tear down for windows */ - private String environmentTeardownWin; - /** Environment tear down for unix */ - private String environmentTeardownUnix; - /** Use Jenkins reporting */ - private boolean optionUseReporting; - /** What error-level to use */ - private String optionErrorLevel; - /** Use HTML in build description */ - private String optionHtmlBuildDesc; - /** Generate execution report */ - private boolean optionExecutionReport; - /** Clean workspace */ - private boolean optionClean; - /** Use CI License */ - private boolean useCILicenses; - /** Use strict testcase import */ - private boolean useStrictTestcaseImport; - /** Use imported results */ - private boolean useImportedResults = false; - private boolean useLocalImportedResults = false; - private boolean useExternalImportedResults = false; - private String externalResultsFilename; - /** Use coverage history to control build status */ - private boolean useCoverageHistory; - /** Wait loops */ - private Long waitLoops; - /** Wait time */ - private Long waitTime; - /** Maximum number of parallal jobs to queue up */ - private Long maxParallel; - /** Using some form of SCM */ - private boolean usingSCM; - /** SCM if using */ - private SCM scm; - /** Manage project name */ - private String manageProjectName; - /** Base Job name */ - private String jobName; - /** Node label */ - private String nodeLabel; - /** PC Lint Plus Command */ - private String pclpCommand = ""; - /** PC Lint Plus Path */ - private String pclpResultsPattern; - /** PC Lint Plus Path */ - private String squoreCommand; - - /** TESTinsights Push information **/ - private String TESTinsights_URL; - private String TESTinsights_project; - private String TESTinsights_credentials_id; - private String TESTinsights_proxy; - private String TESTinsights_SCM_URL; - private String TESTinsights_SCM_Tech; - - /** - * Get the number of wait loops to do - * @return number of loops - */ - public Long getWaitLoops() { - return waitLoops; - } - /** - * Set the number of wait loops - * @param waitLoops number of loops - */ - public void setWaitLoops(Long waitLoops) { - this.waitLoops = waitLoops; - } - /** - * Get the wait time for license retries - * @return the wait time - */ - public Long getWaitTime() { - return waitTime; - } - /** - * Set the wait time for license retries - * @param waitTime the wait time - */ - public void setWaitTime(Long waitTime) { - this.waitTime = waitTime; - } - /** - * Get for maxParallel to control maximum number of jobs to be queue at at any one point - * @return maxParallel Long number - */ - public Long getMaxParallel() { - return maxParallel; - } - /** - * Set option for maxParallel to control maximum number of jobs to be queue at at any one point - * @param maxParallel Long number - */ - public void setMaxParallel(Long maxParallel) { - this.maxParallel = maxParallel; - } - /** - * Get environment for windows setup - * @return environment setup - */ - public String getEnvironmentSetupWin() { - return environmentSetupWin; - } - /** - * Set environment setup for windows - * @param environmentSetupWin environment setup - */ - public void setEnvironmentSetupWin(String environmentSetupWin) { - this.environmentSetupWin = environmentSetupWin; - } - /** - * Get environment setup for unix - * @return environment setup - */ - public String getEnvironmentSetupUnix() { - return environmentSetupUnix; - } - /** - * Set environment setup for unix - * @param environmentSetupUnix environment setup - */ - public void setEnvironmentSetupUnix(String environmentSetupUnix) { - this.environmentSetupUnix = environmentSetupUnix; - } - /** - * Get execute preamble for windows - * @return execute preamble - */ - public String getExecutePreambleWin() { - return executePreambleWin; - } - /** - * Set execute preamble for windows - * @param executePreambleWin execute preamble - */ - public void setExecutePreambleWin(String executePreambleWin) { - this.executePreambleWin = executePreambleWin; - } - /** - * Get execute preamble for unix - * @return execute preamble - */ - public String getExecutePreambleUnix() { - return executePreambleUnix; - } - /** - * Set execute preamble for unix - * @param executePreambleUnix execute preamble - */ - public void setExecutePreambleUnix(String executePreambleUnix) { - this.executePreambleUnix = executePreambleUnix; - } - /** - * Get environment teardown for windows - * @return environment teardown - */ - public String getEnvironmentTeardownWin() { - return environmentTeardownWin; - } - /** - * Set environment teardown for windows - * @param environmentTeardownWin environment teardown - */ - public void setEnvironmentTeardownWin(String environmentTeardownWin) { - this.environmentTeardownWin = environmentTeardownWin; - } - /** - * Get environment teardown for unix - * @return environment teardown - */ - public String getEnvironmentTeardownUnix() { - return environmentTeardownUnix; - } - /** - * Set environment teardown for unix - * @param environmentTeardownUnix environment teardown - */ - public void setEnvironmentTeardownUnix(String environmentTeardownUnix) { - this.environmentTeardownUnix = environmentTeardownUnix; - } - /** - * Get option to use reporting - * @return true/false - */ - public boolean getOptionUseReporting() { - return optionUseReporting; - } /** - * Set option to use reporting - * @param optionUseReporting true/false + * Default constructor. + * */ - public void setOptionUseReporting(boolean optionUseReporting) { - this.optionUseReporting = optionUseReporting; - } - /** - * Get option error level - * @return error level - */ - public String getOptionErrorLevel() { - return optionErrorLevel; - } - /** - * Set option error level - * @param optionErrorLevel error level - */ - public void setOptionErrorLevel(String optionErrorLevel) { - this.optionErrorLevel = optionErrorLevel; - } - /** - * Get option for HTML Build Description - * @return "HTML" or "TEXT" - */ - public String getOptionHtmlBuildDesc() { - return optionHtmlBuildDesc; - } - /** - * Set option for HTML build description * - * @param optionHtmlBuildDesc HTML or TEXT - */ - public void setOptionHtmlBuildDesc(String optionHtmlBuildDesc) { - this.optionHtmlBuildDesc = optionHtmlBuildDesc; - } - /** - * Get option for execution report - * @return true/false - */ - public boolean getOptionExecutionReport() { - return optionExecutionReport; - } - /** - * Set option for execution report - * @param optionExecutionReport true/false - */ - public void setOptionExecutionReport(boolean optionExecutionReport) { - this.optionExecutionReport = optionExecutionReport; - } - /** - * Get option for cleaning workspace - * @return true/false - */ - public boolean getOptionClean() { - return optionClean; - } - /** - * Set option for cleaning workspace - * @param optionClean true/false - */ - public void setOptionClean(boolean optionClean) { - this.optionClean = optionClean; - } - /** - * Get option to use CI licenses - * @return true to use CI licenses, false to not - */ - public boolean getUseCILicenses() { - return useCILicenses; - } - /** - * Set option to use CI licenses - * @param useCILicenses true to use CI licenses, false to not - */ - public void setUseCILicenses(boolean useCILicenses) { - this.useCILicenses = useCILicenses; - } - /** - * Get option to Use strict testcase import - * @return true to Use strict testcase import, false to not - */ - public boolean getUseStrictTestcaseImport() { - return useStrictTestcaseImport; - } - /** - * Set option to Use strict testcase import - * @param useStrictTestcaseImport true to Use strict testcase import, false to not - */ - public void setUseStrictTestcaseImport(boolean useStrictTestcaseImport) { - this.useStrictTestcaseImport = useStrictTestcaseImport; - } - /** - * Get option to Use imported results - * @return true to Use imported results, false to not - */ - public boolean getUseImportedResults() { - return useImportedResults; - } - /** - * Set option to Use imported results - * @param useImportedResults true to Use imported results, false to not - */ - public void setUseImportedResults(boolean useImportedResults) { - this.useImportedResults = useImportedResults; - } - - /** - * Get option to Use local imported results - * @return true to Use local imported results, false to not - */ - public boolean getUseLocalImportedResults() { - return useLocalImportedResults; - } - /** - * Set option to Use imported results - * @param useLocalImportedResults true to Use local imported results, false to not - */ - public void setUseLocalImportedResults(boolean useLocalImportedResults) { - this.useLocalImportedResults = useLocalImportedResults; - } - - /** - * Get option to Use external imported results - * @return true to Use external imported results, false to not - */ - public boolean getUseExternalImportedResults() { - return useExternalImportedResults; - } - /** - * Set option to Use imported results - * @param useExternalImportedResults true to Use external imported results, false to not - */ - public void setUseExternalImportedResults(boolean useExternalImportedResults) { - this.useExternalImportedResults = useExternalImportedResults; - } - /** - * Get option to Use as external result filename - * @return string external result filename - */ - public String getExternalResultsFilename() { - return externalResultsFilename; - } - /** - * Set option to Use imported results - * @param externalResultsFilename true to Use external imported results, false to not - */ - public void setExternalResultsFilename(String externalResultsFilename) { - this.externalResultsFilename = externalResultsFilename; - } - - /** - * Get option to Use coverage history to control build status - * @return true to Use imported results, false to not - */ - public boolean getUseCoverageHistory() { - return useCoverageHistory; - } - /** - * Set option to Use coverage history to control build status - * @param useCoverageHistory true to Use imported results, false to not - */ - public void setUseCoverageHistory(boolean useCoverageHistory) { - this.useCoverageHistory = useCoverageHistory; - } - /** - * Get using SCM - * @return true/false - */ - public boolean getUsingSCM() { - return usingSCM; - } - /** - * Set using SCM (true yes, false no) - * @param usingSCM true/false - */ - public void setUsingSCM(boolean usingSCM) { - this.usingSCM = usingSCM; - } - /** - * Get the SCM to use - * @return SCM - */ - public SCM getSCM() { - return scm; - } - /** - * Set the SCM being used - * @param scm SCM - */ - public void setSCM(SCM scm) { - this.scm = scm; - } - /** - * Get the Manage project file/name - * @return Manage project name - */ - public String getManageProjectName() { - return manageProjectName; - } - /** - * Set the Manage project file/name - * @param manageProjectName Manage project name - */ - public void setManageProjectName(String manageProjectName) { - this.manageProjectName = manageProjectName; - } - /** - * Get the job name - * @return job name - */ - public String getJobName() { - return jobName; - } - /** - * Set the job name - * @param jobName job name - */ - public void setJobName(String jobName) { - this.jobName = jobName; - } - /** - * Get the node label - * @return node label - */ - public String getNodeLabel() { - return nodeLabel; - } - /** - * Set the node label - * @param nodeLabel node label - */ - public void setNodeLabel(String nodeLabel) { - this.nodeLabel = nodeLabel; - } - /** - * Get pc-lint plus command - * @return pc-lint plus command - */ - public String getPclpCommand() { - return pclpCommand; - } - /** - * Get pc-lint plus command - * @param pclpCommand - Pc Lint Plus Command - */ - public void setPclpCommand(String pclpCommand) { - this.pclpCommand = pclpCommand; - } - /** - * Get using pc-lint plus command - * @return true/false if we have a PC Lint Command - */ - public boolean getUsingPCLP() { - return (pclpCommand.length() != 0); - } - /** - * Get pc-lint plus result pattern - * @return pc-lint plus result pattern - */ - public String getPclpResultsPattern() { - return pclpResultsPattern; - } - /** - * Get pc-lint plus result pattern - * @param pclpResultsPattern - PC Lint Result pattern - */ - public void setPclpResultsPattern(String pclpResultsPattern) { - this.pclpResultsPattern = pclpResultsPattern; - } - - /** - * Get using getUsingPCLP command - * @return true/false if we have a squoreCommand - */ - public boolean getUsingSquoreCommand() { - return (squoreCommand.length() != 0); - } - - /** - * Get Squore command - * @return Squore command - */ - public String getSquoreCommand() { - return squoreCommand; - } - - /** - * Set Squore command - * @param squoreCommand - Squore Command - */ - public void setSquoreCommand(String squoreCommand) { - this.squoreCommand = squoreCommand; - } - - /** - * Get URL for TESTinsights - * @return TESTinsights URL - */ - public String getTESTinsights_URL() { - return TESTinsights_URL; - } - /** - * Set URL for TESTinsights - * @param TESTinsights_URL - TESTinsights URL - */ - public void setTESTinsights_URL(String TESTinsights_URL) { - this.TESTinsights_URL = TESTinsights_URL; - } - /** - * Get Project for TESTinsights - * @return TESTinsights Project - */ - public String getTESTinsights_project() { - return TESTinsights_project; - } - /** - * Set Project for TESTinsights - * @param TESTinsights_project - Project for TESTinsights - */ - public void setTESTinsights_project(String TESTinsights_project) { - this.TESTinsights_project = TESTinsights_project; - } - /** - * Get Proxy for TESTinsights - * @return TESTinsights proxy - */ - public String getTESTinsights_proxy() { - return TESTinsights_proxy; - } - /** - * Set Proxy for TESTinsights - * @param TESTinsights_proxy TESTinsights proxy - */ - public void setTESTinsights_proxy(String TESTinsights_proxy) { - this.TESTinsights_proxy = TESTinsights_proxy; - } - /** - * Get Credentials ID for TESTinsights - * @return TESTinsights Credentials - */ - public String getTESTinsights_credentials_id() { - return TESTinsights_credentials_id; - } - /** - * Set Credentials ID for TESTinsights - * @param TESTinsights_credentials_id - Credentials ID for TESTinsights - */ - public void setTESTinsights_credentials_id(String TESTinsights_credentials_id) { - this.TESTinsights_credentials_id = TESTinsights_credentials_id; - } - /** - * Get SCM URL for TESTinsights - * @return TESTinsights SCM URL - */ - public String getTESTinsights_SCM_URL() { - return TESTinsights_SCM_URL; - } - /** - * Get SCM Technology TESTinsights - * @return TESTinsights SCM Technology - */ - public String getTESTinsights_SCM_Tech() { - return TESTinsights_SCM_Tech; - } - /** - * Set SCM URL for TESTinsights - * @param TESTinsights_SCM_URL - URL for TESTinsights - */ - public void setTESTinsights_SCM_URL(String TESTinsights_SCM_URL) { - this.TESTinsights_SCM_URL = TESTinsights_SCM_URL; - } - /** - * Set SCM Technology TESTinsights - * @param TESTinsights_SCM_Tech - SCM Technology TESTinsights (git or svn) - */ - - public void setTESTinsights_SCM_Tech(String TESTinsights_SCM_Tech) { - this.TESTinsights_SCM_Tech = TESTinsights_SCM_Tech; - } - /** - * Create setup step - * @param environmentSetupWin environment setup for windows - * @param environmentSetupUnix environment setup for unix - * @param executePreambleWin execute preamble for windows - * @param executePreambleUnix execute preamble for unix - * @param environmentTeardownWin environment teardown for windows - * @param environmentTeardownUnix environment teardown for unix - * @param optionUseReporting use reporting - * @param optionErrorLevel error level - * @param optionHtmlBuildDesc HTML Build description - * @param optionExecutionReport execution report - * @param optionClean clean - * @param useCILicenses use CI licenses - * @param useStrictTestcaseImport Use strict testcase import - * @param useImportedResults use imported results - * @param useLocalImportedResults use local imported results - * @param useExternalImportedResults use extern imported results - * @param externalResultsFilename use extern result filename - * @param useCoverageHistory use imported results - * @param waitLoops wait loops - * @param waitTime wait time - * @param maxParallel maximum number of jobs to queue in parallel - * @param manageProjectName manage project name - * @param jobName job name - * @param nodeLabel node label - * @param pclpCommand PC Lint Plus command - * @param pclpResultsPattern PC Lint Plus result patter - * @param squoreCommand Squore command - * @param TESTinsights_URL URL for TESTinsights - * @param TESTinsights_project Project for for TESTinsights - * @param TESTinsights_credentials_id Credentials for for TESTinsights - * @param TESTinsights_proxy Proxy for for TESTinsights - * @param TESTinsights_SCM_URL SCM URL for for TESTinsights - * @param TESTinsights_SCM_Tech SCM technology for for TESTinsights - */ @DataBoundConstructor - public VectorCASTSetup(String environmentSetupWin, - String environmentSetupUnix, - String executePreambleWin, - String executePreambleUnix, - String environmentTeardownWin, - String environmentTeardownUnix, - boolean optionUseReporting, - String optionErrorLevel, - String optionHtmlBuildDesc, - boolean optionExecutionReport, - boolean optionClean, - boolean useCILicenses, - boolean useStrictTestcaseImport, - boolean useImportedResults, - boolean useLocalImportedResults, - boolean useExternalImportedResults, - String externalResultsFilename, - boolean useCoverageHistory, - Long waitLoops, - Long waitTime, - Long maxParallel, - String manageProjectName, - String jobName, - String nodeLabel, - String pclpCommand, - String pclpResultsPattern, - String squoreCommand, - String TESTinsights_URL, - String TESTinsights_project, - String TESTinsights_credentials_id, - String TESTinsights_proxy, - String TESTinsights_SCM_URL, - String TESTinsights_SCM_Tech) { - this.environmentSetupWin = environmentSetupWin; - this.environmentSetupUnix = environmentSetupUnix; - this.executePreambleWin = executePreambleWin; - this.executePreambleUnix = executePreambleUnix; - this.environmentTeardownWin = environmentTeardownWin; - this.environmentTeardownUnix = environmentTeardownUnix; - this.optionUseReporting = optionUseReporting; - this.optionErrorLevel = optionErrorLevel; - this.optionHtmlBuildDesc = optionHtmlBuildDesc; - this.optionExecutionReport = optionExecutionReport; - this.optionClean = optionClean; - this.useCILicenses = useCILicenses; - this.useStrictTestcaseImport = useStrictTestcaseImport; - this.useImportedResults = useImportedResults; - this.useLocalImportedResults = useLocalImportedResults; - this.useExternalImportedResults = useExternalImportedResults; - this.externalResultsFilename = externalResultsFilename; - this.useCoverageHistory = useCoverageHistory; - this.usingSCM = false; - this.scm = new NullSCM(); - this.waitLoops = waitLoops; - this.waitTime = waitTime; - this.maxParallel = maxParallel; - this.manageProjectName = manageProjectName; - this.jobName = jobName; - this.nodeLabel = nodeLabel; - this.pclpCommand = pclpCommand; - this.pclpResultsPattern = pclpResultsPattern; - this.squoreCommand = squoreCommand; - this.TESTinsights_URL = TESTinsights_URL; - this.TESTinsights_project = TESTinsights_project; - this.TESTinsights_credentials_id = TESTinsights_credentials_id; - this.TESTinsights_proxy = TESTinsights_proxy; - this.TESTinsights_SCM_URL = TESTinsights_SCM_URL; - this.TESTinsights_SCM_Tech = TESTinsights_SCM_Tech; + public VectorCASTSetup() { } + /** * Copy the files in a directory recursively to the job workspace. - * This is used when the source is NOT a jar file - * - * @param dir directory to process + * This is used when the source is NOT a jar file. + * + * @param scriptDir directory to process * @param base base * @param destDir destination directory + * @param directDir direct dir to copy * @throws IOException exception * @throws InterruptedException exception */ - private void processDir(File scriptDir, String base, FilePath destDir, Boolean directDir) throws IOException, InterruptedException { + + private void processDir(final File scriptDir, + final String base, + final FilePath destDir, + final Boolean directDir) throws IOException, InterruptedException { + destDir.mkdirs(); File[] files = scriptDir.listFiles(); if (files == null) { return; } for (File file : files) { + if (file.isDirectory()) { FilePath newDest = new FilePath(destDir, file.getName()); - processDir(file, base + "/" + file.getName(), newDest, directDir); + processDir(file, + base + "/" + file.getName(), + newDest, directDir); } else { if (directDir) { - File newFile = new File(destDir + File.separator + file.getName()); - File inFile = new File(scriptDir + File.separator + file.getName()); + + // change the copy mechanism + // to copy file to remote node + File newFile = new File(destDir + + File.separator + + file.getName()); + File inFile = new File(scriptDir + + File.separator + + file.getName()); + FilePath dest = new FilePath(destDir, newFile.getName()); InputStream is = null; try { - is = new FileInputStream(inFile); - dest.copyFrom(is); - } - finally { + is = new FileInputStream(inFile); + dest.copyFrom(is); + } finally { + if (is != null) { is.close(); } } } else { FilePath newFile = new FilePath(destDir, file.getName()); - try (InputStream is = VectorCASTSetup.class.getResourceAsStream(SCRIPT_DIR + base + "/" + file.getName())) { + try (InputStream is = VectorCASTSetup.class. + getResourceAsStream(SCRIPT_DIR + + base + + "/" + + file.getName())) { newFile.copyFrom(is); } } @@ -786,40 +131,56 @@ private void processDir(File scriptDir, String base, FilePath destDir, Boolean d } } - private void printVersion( PrintStream logger ) - { - logger.println( "[VectorCAST Execution Version]: " + VcastUtils.getVersion().orElse( "Error - Could not determine version" ) ); + /** + * Prints the version of the plugin that's being used. + * @param logger - where to log the info + */ + private void printVersion(final PrintStream logger) { + logger.println("[VectorCAST Execution Version]: " + + VcastUtils.getVersion(). + orElse("Error - Could not determine version")); } /** - * Perform the build step. Copy the scripts from the archive/directory to the workspace + * Perform the build step. Copy the scripts from the + * archive/directory to the workspace. * @param build build * @param workspace workspace + * @param env environment variables * @param launcher launcher * @param listener listener - * @throws IOException exception - */ + * @throws IOException exception + */ @Override - public void perform(Run build, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException { + public void perform(final Run build, final FilePath workspace, + final EnvVars env, final Launcher launcher, + final TaskListener listener) throws IOException { + + final int initPathLen = 8; FilePath destScriptDir = new FilePath(workspace, "vc_scripts"); JarFile jFile = null; try { String path = null; - String override_path = System.getenv("VCAST_VC_SCRIPTS"); - String extra_script_path = SCRIPT_DIR; + String overridePath = System.getenv("VCAST_VC_SCRIPTS"); + String extraScriptPath = SCRIPT_DIR; Boolean directDir = false; - if (override_path != null && !override_path.isEmpty()) { - path = override_path; - extra_script_path = ""; + if (overridePath != null && !overridePath.isEmpty()) { + path = overridePath; + extraScriptPath = ""; directDir = true; - String msg = "VectorCAST - overriding vc_scripts. Copying from '" + path + "'"; - Logger.getLogger(VectorCASTSetup.class.getName()).log(Level.ALL, msg); + String msg = " " + + "VectorCAST - overriding vc_scripts. Copying from '" + + path + "'"; + Logger. + getLogger( + VectorCASTSetup.class.getName()).log(Level.ALL, msg); } else { - path = VectorCASTSetup.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + path = VectorCASTSetup.class.getProtectionDomain(). + getCodeSource().getLocation().getPath(); path = URLDecoder.decode(path, "utf-8"); } File testPath = new File(path); - printVersion( listener.getLogger() ); + printVersion(listener.getLogger()); if (testPath.isFile()) { // Have jar file... jFile = new JarFile(testPath); @@ -827,73 +188,108 @@ public void perform(Run build, FilePath workspace, Launcher launcher, TaskL while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); if (entry.getName().startsWith("scripts")) { - String fileOrDir = entry.getName().substring(8); // length of scripts/ + + String fileOrDir = + entry.getName().substring(initPathLen); + + /* check to solve jenkins security scanner */ + File destDir = new File(destScriptDir.getName()); + File destFile = new File(destDir, fileOrDir); + if (!destFile.toPath().normalize(). + startsWith(destDir.toPath())) { + throw new IOException("Bad entry in scripts.jar: " + + entry.getName()); + } + FilePath dest = new FilePath(destScriptDir, fileOrDir); if (entry.getName().endsWith("/")) { // Directory, create destination dest.mkdirs(); } else { + + String destString = "/" + fileOrDir; + /* check to solve jenkins security scanner */ + destDir = new File(destScriptDir.getName()); + destFile = new File(destDir, destString); + if (!destFile.toPath().normalize(). + startsWith(destDir.toPath())) { + throw new IOException("" + + "Bad entry in scripts.jar: " + + entry.getName()); + } + // File, copy it - InputStream is = VectorCASTSetup.class.getResourceAsStream("/" + entry.getName()); + InputStream is = VectorCASTSetup.class. + getResourceAsStream("/" + entry.getName()); dest.copyFrom(is); } } } } else { // Have directory - File scriptDir = new File(path + extra_script_path); + File scriptDir = new File(path + extraScriptPath); processDir(scriptDir, "./", destScriptDir, directDir); } } catch (IOException ex) { - Logger.getLogger(VectorCASTSetup.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(VectorCASTSetup.class.getName()). + log(Level.INFO, null, ex); } catch (InterruptedException ex) { - Logger.getLogger(VectorCASTSetup.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(VectorCASTSetup.class.getName()). + log(Level.INFO, null, ex); } finally { if (jFile != null) { try { jFile.close(); } catch (IOException ex) { - // Ignore + assert true; } } } - + // clean up old xml_data files - + File[] files = new File(workspace + "/xml_data/").listFiles(); - if (files != null) - { - for (File file : files) - { - if (file.isFile()) - { - if (!file.delete()) { - throw new IOException("Unable to delete file: " + file.getAbsolutePath()); - } + if (files != null) { + for (File file : files) { + if (file.isFile() && !file.delete()) { + throw new IOException("Unable to delete file: " + + file.getAbsolutePath()); } } } } + /** + * getDescriptor for {@link VectorCASTSetup}. + * @return DescriptorImpl descriptor + */ @Override public DescriptorImpl getDescriptor() { - return (DescriptorImpl)super.getDescriptor(); + return (DescriptorImpl) super.getDescriptor(); } /** * Descriptor for {@link VectorCASTSetup}. Used as a singleton. * The class is marked as public so that it can be accessed from views. */ @Extension - public static final class DescriptorImpl extends BuildStepDescriptor { + public static final class DescriptorImpl + extends BuildStepDescriptor { /** - * In order to load the persisted global configuration, you have to + * In order to load the persisted global configuration, you have to * call load() in the constructor. */ public DescriptorImpl() { load(); } + /** + * Override call to isApplicable. + * @param aClass AbstractProject Project Class + * @return boolean always true + * call load() in the constructor. + */ @Override - public boolean isApplicable(Class aClass) { - // Indicates that this builder can be used with all kinds of project types + @SuppressWarnings("rawtypes") + public boolean isApplicable( + final Class aClass) { return true; } /** @@ -905,47 +301,4 @@ public String getDisplayName() { return Messages.VectorCASTSetup_DisplayName(); } } - private static final Logger logger = Logger.getLogger(VectorCASTSetup.class.getName()); - - @Override - public String toString() { - - String string = "\nVectorCASTSetup: \n" - + "\t environmentSetupUnix: " + environmentSetupUnix + "\n" - + "\t executePreambleWin: " + executePreambleWin + "\n" - + "\t executePreambleUnix: " + executePreambleUnix + "\n" - + "\t environmentTeardownWin: " + environmentTeardownWin + "\n" - + "\t environmentTeardownUnix: " + environmentTeardownUnix + "\n" - + "\t optionUseReporting: " + optionUseReporting + "\n" - + "\t optionErrorLevel: " + optionErrorLevel + "\n" - + "\t optionHtmlBuildDesc: " + optionHtmlBuildDesc + "\n" - + "\t optionHtmlBuildDesc: " + optionHtmlBuildDesc + "\n" - + "\t optionExecutionReport: " + optionExecutionReport + "\n" - + "\t optionClean: " + optionClean + "\n" - + "\t useCILicenses: " + useCILicenses + "\n" - + "\t useStrictTestcaseImport: " + useStrictTestcaseImport + "\n" - + "\t useImportedResults: " + useImportedResults + "\n" - + "\t useLocalImportedResults: " + useLocalImportedResults + "\n" - + "\t useExternalImportedResults: " + useExternalImportedResults + "\n" - + "\t externalResultsFilename: " + externalResultsFilename + "\n" - + "\t useCoverageHistory: " + useCoverageHistory + "\n" - + "\t usingSCM: " + usingSCM + "\n" - + "\t scm: " + scm + "\n" - + "\t waitLoops: " + waitLoops + "\n" - + "\t waitTime: " + waitTime + "\n" - + "\t maxParallel: " + maxParallel + "\n" - + "\t manageProjectName: " + manageProjectName + "\n" - + "\t jobName: " + jobName + "\n" - + "\t nodeLabel: " + nodeLabel + "\n" - + "\t pclpCommand: " + pclpCommand + "\n" - + "\t pclpResultsPattern: " + pclpResultsPattern + "\n" - + "\t squoreCommand: " + squoreCommand + "\n" - + "\t TESTinsights_URL: " + TESTinsights_URL + "\n" - + "\t TESTinsights_project: " + TESTinsights_project + "\n" - + "\t TESTinsights_credentials_id: " + TESTinsights_credentials_id + "\n" - + "\t TESTinsights_proxy: " + TESTinsights_proxy + "\n" - + "\t TESTinsights_SCM_URL: " + TESTinsights_SCM_URL + "\n" - + "\t TESTinsights_SCM_Tech: " + TESTinsights_SCM_Tech + "\n"; - return string; - } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java index 3af62814..d4b971cb 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/VcastUtils.java @@ -27,28 +27,37 @@ import java.io.IOException; import java.net.URLDecoder; import java.util.Optional; -import java.util.jar.Attributes; import java.util.jar.JarFile; -import java.util.jar.Manifest; +import java.io.FileNotFoundException; -public class VcastUtils -{ - public static Optional< String > getVersion() - { - Optional< String > version = Optional.empty(); +/** Utility class for VectorCAST. */ + +public class VcastUtils { + /** + * Gets the version of the plugins. + * @return Optional returns the version + */ + public static Optional getVersion() { + Optional version = Optional.empty(); try { - File file = new File( URLDecoder.decode( VcastUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "utf-8" ) ); - JarFile jarfile = new JarFile( file ); - version = Optional.ofNullable( jarfile.getManifest().getMainAttributes().getValue( "Plugin-Version" ) ); + File file = new File(URLDecoder.decode( + VcastUtils.class.getProtectionDomain().getCodeSource() + .getLocation().getPath(), "utf-8")); + JarFile jarfile = new JarFile(file); + version = Optional.ofNullable(jarfile.getManifest() + .getMainAttributes().getValue("Plugin-Version")); jarfile.close(); - - } catch ( IOException e ) { + } catch (FileNotFoundException e) { e.printStackTrace(); - } catch ( NullPointerException e ) { + } catch (IOException e) { e.printStackTrace(); } + return version; + } + protected VcastUtils() { + // prevents calls from subclass + throw new UnsupportedOperationException(); + } - return version; - } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/package-info.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/package-info.java new file mode 100644 index 00000000..b60acd6a --- /dev/null +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/common/package-info.java @@ -0,0 +1,32 @@ +/* + * The MIT License + * + * Copyright 2024 Vector Informatik, GmbH. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Common VCE java utilities. + * + * @author Vector Informatik, GmbH. + */ + +package com.vectorcast.plugins.vectorcastexecution.common; + diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BadOptionComboException.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BadOptionComboException.java new file mode 100644 index 00000000..f2b01106 --- /dev/null +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BadOptionComboException.java @@ -0,0 +1,62 @@ +/* + * The MIT License + * + * Copyright 2016 Vector Software, East Greenwich, Rhode Island USA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.vectorcast.plugins.vectorcastexecution.job; + +/** + * Exception raised if job being created already exists. + */ +public class BadOptionComboException extends Exception { + /** serial Version UID. */ + private static final long serialVersionUID = 4219732918348691554L; + + /** Name of option one. */ + private final String option1; + + /** Name of option two. */ + private final String option2; + + /** + * Constructor. + * @param opt1 option1 conflicts with + * @param opt2 this option + */ + public BadOptionComboException(final String opt1, final String opt2) { + this.option1 = opt1; + this.option2 = opt2; + } + /** + * Get option one name. + * @return option one name + */ + public String getOption1() { + return option1; + } + /** + * Get option two name. + * @return option two name + */ + public String getOption2() { + return option2; + } +} diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java index 836d3741..c853d74b 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/BaseJob.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright 2016 Vector Software, East Greenwich, Rhode Island USA + * Copyright 2024 Vector Software, East Greenwich, Rhode Island USA * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,892 +46,807 @@ import hudson.tasks.junit.JUnitResultArchiver; import io.jenkins.plugins.analysis.warnings.PcLint; import io.jenkins.plugins.analysis.core.steps.IssuesRecorder; +import io.jenkins.plugins.coverage.metrics.steps.CoverageRecorder; +import io.jenkins.plugins.coverage.metrics.steps.CoverageTool; +import io.jenkins.plugins.coverage.metrics.steps.CoverageTool.Parser; +import io.jenkins.plugins.coverage.metrics.steps.CoverageQualityGate; +import io.jenkins.plugins.coverage.metrics.model.Baseline; +import io.jenkins.plugins.util.QualityGate.QualityGateCriticality; +import edu.hm.hafner.coverage.Metric; +import io.jenkins.plugins.forensics.reference.SimpleReferenceRecorder; import org.jenkinsci.plugins.credentialsbinding.impl.SecretBuildWrapper; import org.jenkinsci.plugins.credentialsbinding.impl.UsernamePasswordMultiBinding; import org.jenkinsci.plugins.credentialsbinding.MultiBinding; import java.util.List; import java.util.Collections; -import java.util.logging.Logger; -import java.util.logging.Level; +import java.util.ArrayList; + +import java.net.URL; + /** - * Base job management - create/delete/update + * Base job management - create/delete/update. */ -abstract public class BaseJob { - /** Jenkins instance */ +public abstract class BaseJob { + /** Coverage Delta threshold. */ + private static final float COVERAGE_THRESHOLD = -0.001f; + + /** VectorCAST Coverage plugin selection. */ + private static final long USE_VCC_PLUGIN = 2; + + /** Zero percent indicator. */ + private static final int ZERO_PERCENT = 0; + /** Seventy percent indicator. */ + private static final int SEVENTY_PERCENT = 70; + /** Eighty percent indicator. */ + private static final int EIGHTY_PERCENT = 80; + /** 100% indicator. */ + private static final int ONE_HUNDREAD_PERCENT = 100; + /** Maximum string length. */ + private static final int MAX_STRING_LEN = 1000; + /** Default wait time. */ + private static final int DEFAULT_WAIT_TIME = 30; + /** Default number of wait loops. */ + private static final int DEFAULT_WAIT_LOOP = 1; + + /** Project name. */ + private String projectName; + /** Jenkins instance. */ private Jenkins instance; - /** Request */ + /** Request. */ private StaplerRequest request; - /** Response */ + /** Response. */ private StaplerResponse response; - /** Manage project name */ + /** Manage project name. */ private String manageProjectName; - /** Base name generated from the manage project name */ + /** Base name generated from the manage project name. */ private String baseName; - /** Top-level project */ - private Project topProject; - /** Environment setup for windows */ + /** Top-level project. */ + private Project topProject; + /** Environment setup for windows. */ private String environmentSetupWin; - /** Environment setup for unix */ + /** Environment setup for unix. */ private String environmentSetupUnix; - /** Execute preamble for windows */ + /** Execute preamble for windows. */ private String executePreambleWin; - /** Execute preamble for unix */ + /** Execute preamble for unix. */ private String executePreambleUnix; - /** Environment tear down for windows */ + /** Environment tear down for windows. */ private String environmentTeardownWin; - /** Environment tear down for unix */ + /** Environment tear down for unix. */ private String environmentTeardownUnix; - /** Use Jenkins reporting */ + /** Use Jenkins reporting. */ private boolean optionUseReporting; - /** What error-level to use */ - private String optionErrorLevel; - /** Use HTML in build description */ + /** What error-level to use. */ + private int optionErrorLevel; + /** Use HTML in build description. */ private String optionHtmlBuildDesc; - /** Generate execution report */ + /** Generate execution report. */ private boolean optionExecutionReport; - /** Clean workspace */ + /** Clean workspace. */ private boolean optionClean; - /** Use CI license */ + /** Use CI license. */ private boolean useCILicenses; - /** Use strict testcase import */ + /** Use strict testcase import. */ private boolean useStrictTestcaseImport; - /** Use imported results */ + /** Allow RGW3 test to be executed and exported. */ + private boolean useRGW3; + + /** Use coveagePlugin. */ + private boolean useCoveragePlugin; + + /** Use imported results. */ private boolean useImportedResults = false; + /** Use local/artifact imported results. */ private boolean useLocalImportedResults = false; + /** Use external file for imported results. */ private boolean useExternalImportedResults = false; + /** Filename for external results. */ private String externalResultsFilename; - - /** Use coverage history to control build status */ + + /** Use coverage history to control build status. */ private boolean useCoverageHistory; - /** Using some form of SCM */ - private boolean usingSCM; - /** The SCM being used */ + /** Using some form of SCM. */ + private boolean usingScm; + /** The SCM being used. */ private SCM scm; - /** Use saved data or not */ - private boolean useSavedData; - /** Wait time */ + /** Wait time. */ private Long waitTime; - /** Wait loops */ + /** Wait loops. */ private Long waitLoops; - /** Base Job name */ + /** Base Job name. */ private String jobName; - /** Node label */ + /** Node label. */ private String nodeLabel; - /** Maximum number of parallal jobs to queue up */ + /** Maximum number of parallal jobs to queue up. */ private Long maxParallel; - - /** PC Lint Plus Command */ + + /** PC Lint Plus Command. */ private String pclpCommand; - /** PC Lint Plus Path */ + /** PC Lint Plus Path. */ private String pclpResultsPattern; - /* Squore execution command */ + /** Squore execution command. */ private String squoreCommand; - /* TESTinsights Push information */ - private String TESTinsights_URL; - private String TESTinsights_project; - private String TESTinsights_credentials_id; - private String TESTinsights_proxy; - private String TESTinsights_SCM_URL; - private String TESTinsights_SCM_Tech; - - /** - * Constructor - * @param request request object - * @param response response object - * @param useSavedData use saved data true/false + /** TESTinsights URL information. */ + private String testInsightsUrl; + /** TESTinsights Project information. */ + private String testInsightsProject; + /** TESTinsights credentials information. */ + private String testInsightsCredentialsId; + /** TESTinsights Proxy information. */ + private String testInsightsProxy; + /** TESTinsights SCM information. */ + private String testInsightsScmUrl; + /** TESTinsights SCM Tech information. */ + private String testInsightsScmTech; + + /** + * Constructor. + * @param req request object + * @param resp response object * @throws ServletException exception * @throws IOException exception * @throws ExternalResultsFileException exception - */ - protected BaseJob(final StaplerRequest request, final StaplerResponse response, boolean useSavedData) throws ServletException, IOException, ExternalResultsFileException { - instance = Jenkins.getInstance(); - this.request = request; - this.response = response; + * @throws IllegalArgumentException exception + * @throws BadOptionComboException exception + */ + protected BaseJob(final StaplerRequest req, + final StaplerResponse resp) + throws ServletException, IOException, + ExternalResultsFileException, IllegalArgumentException, + BadOptionComboException { + + instance = Jenkins.get(); + request = req; + response = resp; JSONObject json = request.getSubmittedForm(); - - Logger.getLogger(BaseJob.class.getName()).log(Level.INFO, "JSON Info for Base Job Create: " + json.toString()); manageProjectName = json.optString("manageProjectName"); + if (manageProjectName.length() > MAX_STRING_LEN) { + throw new IllegalArgumentException( + "manageProjectName too long > 1000" + ); + } + if (!manageProjectName.isEmpty()) { // Force unix style path to avoid problems later - manageProjectName = manageProjectName.replace('\\','/'); - manageProjectName = manageProjectName.replaceAll("^[ \t]+|[ \t]+$", ""); - if (! manageProjectName.toLowerCase().endsWith(".vcm")) manageProjectName += ".vcm"; - } + manageProjectName = manageProjectName.replace('\\', '/'); + manageProjectName = manageProjectName.trim(); + if (!manageProjectName.toLowerCase().endsWith(".vcm")) { + manageProjectName += ".vcm"; + } + } baseName = FilenameUtils.getBaseName(manageProjectName); - this.useSavedData = useSavedData; - if (useSavedData) { - // Data will be set later - } else { - this.usingSCM = false; - - environmentSetupWin = json.optString("environmentSetupWin"); - executePreambleWin = json.optString("executePreambleWin"); - environmentTeardownWin = json.optString("environmentTeardownWin"); - - environmentSetupUnix = json.optString("environmentSetupUnix"); - executePreambleUnix = json.optString("executePreambleUnix"); - environmentTeardownUnix = json.optString("environmentTeardownUnix"); - - optionUseReporting = json.optBoolean("optionUseReporting", true); - optionErrorLevel = json.optString("optionErrorLevel", "Unstable"); - optionHtmlBuildDesc = json.optString("optionHtmlBuildDesc", "HTML"); - optionExecutionReport = json.optBoolean("optionExecutionReport", true); - optionClean = json.optBoolean("optionClean", false); - - waitTime = json.optLong("waitTime", 5); - waitLoops = json.optLong("waitLoops", 2); - - jobName = json.optString("jobName", null); - - if (jobName != null) { - // Remove all non-alphanumeric characters from the Jenkins Job name - jobName = jobName.replaceAll("[^a-zA-Z0-9_]","_"); + environmentSetupWin = json.optString("environmentSetupWin"); + executePreambleWin = json.optString("executePreambleWin"); + environmentTeardownWin = json.optString("environmentTeardownWin"); + + environmentSetupUnix = json.optString("environmentSetupUnix"); + executePreambleUnix = json.optString("executePreambleUnix"); + environmentTeardownUnix = json.optString("environmentTeardownUnix"); + + optionUseReporting = json.optBoolean("optionUseReporting", true); + String errLevel = json.optString("optionErrorLevel", "unstable"); + if (errLevel.equals("nothing")) { + optionErrorLevel = 0; + } else if (errLevel.equals("unstable")) { + optionErrorLevel = 1; + } else if (errLevel.equals("failure")) { + optionErrorLevel = 2; + } + + optionHtmlBuildDesc = json.optString("optionHtmlBuildDesc", "HTML"); + optionExecutionReport = json.optBoolean("optionExecutionReport", true); + optionClean = json.optBoolean("optionClean", false); + + waitTime = json.optLong("waitTime", DEFAULT_WAIT_TIME); + waitLoops = json.optLong("waitLoops", DEFAULT_WAIT_LOOP); + + jobName = json.optString("jobName", null); + + if (jobName != null) { + // Remove all non-alphanumeric characters from the Jenkins Job name + jobName = jobName.replaceAll("[^a-zA-Z0-9_]", "_"); + } + + nodeLabel = json.optString("nodeLabel", ""); + + useCILicenses = json.optBoolean("useCiLicense", false); + useStrictTestcaseImport = json + .optBoolean("useStrictTestcaseImport", true); + useRGW3 = json.optBoolean("useRGW3", false); + useImportedResults = json.optBoolean("useImportedResults", false); + + + /* since Coverage is a radio button, we need to unpack it */ + JSONObject jsonCovPlugin = json.optJSONObject("coverageDisplayOption"); + + /* If there's something specified, check which one to use */ + if (jsonCovPlugin != null) { + final long whichPlugin = + jsonCovPlugin.optLong("value", USE_VCC_PLUGIN); + if (whichPlugin == USE_VCC_PLUGIN) { + useCoveragePlugin = false; + } else { + useCoveragePlugin = true; } - - nodeLabel = json.optString("nodeLabel", ""); - - useCILicenses = json.optBoolean("useCiLicense", false); - useStrictTestcaseImport = json.optBoolean("useStrictTestcaseImport", true); - useImportedResults = json.optBoolean("useImportedResults", false); - externalResultsFilename = ""; - - if (useImportedResults) { - JSONObject jsonImportResults = json.optJSONObject("importedResults"); - - if (jsonImportResults != null) { - Long int_ext = jsonImportResults.optLong("value",0); - - if (int_ext == 1) { - useLocalImportedResults = true; - useExternalImportedResults = false; - externalResultsFilename = ""; - } else if (int_ext == 2) { - useLocalImportedResults = false; - useExternalImportedResults = true; - externalResultsFilename = jsonImportResults.optString("externalResultsFilename",""); - externalResultsFilename = externalResultsFilename.replace('\\','/'); - if (externalResultsFilename.length() == 0) { - throw new ExternalResultsFileException(); - } + } else { + /* If there's nothing specified, use VCC */ + useCoveragePlugin = false; + } + + externalResultsFilename = ""; + + if (useImportedResults) { + JSONObject jsonImpRes = json.optJSONObject("importedResults"); + + if (jsonImpRes != null) { + final long intExt = jsonImpRes.optLong("value", 0); + + if (intExt == 1) { + useLocalImportedResults = true; + useExternalImportedResults = false; + externalResultsFilename = ""; + } else if (intExt == 2) { + useLocalImportedResults = false; + useExternalImportedResults = true; + externalResultsFilename = jsonImpRes + .optString("externalResultsFilename", ""); + externalResultsFilename = + externalResultsFilename.replace('\\', '/'); + if (externalResultsFilename.length() == 0) { + throw new ExternalResultsFileException(); } } - Logger.getLogger(BaseJob.class.getName()).log(Level.INFO, "ImportedResults: " + jsonImportResults); - } - useCoverageHistory = json.optBoolean("useCoverageHistory", false); - maxParallel = json.optLong("maxParallel", 0); - - /* Additional Tools */ - pclpCommand = json.optString("pclpCommand", "").replace('\\','/');; - pclpResultsPattern = json.optString("pclpResultsPattern", ""); - squoreCommand = json.optString("squoreCommand", "").replace('\\','/'); - TESTinsights_URL = json.optString("TESTinsights_URL", ""); - TESTinsights_project = json.optString("TESTinsights_project", ""); - if (TESTinsights_project.length() == 0) { - TESTinsights_project = "env.JOB_BASE_NAME"; } - TESTinsights_credentials_id = json.optString("TESTinsights_credentials_id", ""); - TESTinsights_proxy = json.optString("TESTinsights_proxy", ""); - } - } - /** - * Use Saved Data - * @param savedData saved data to use - */ - public void useSavedData(VectorCASTSetup savedData) { - environmentSetupWin = savedData.getEnvironmentSetupWin(); - executePreambleWin = savedData.getExecutePreambleWin(); - environmentTeardownWin = savedData.getEnvironmentTeardownWin(); - - environmentSetupUnix = savedData.getEnvironmentSetupUnix(); - executePreambleUnix = savedData.getExecutePreambleUnix(); - environmentTeardownUnix = savedData.getEnvironmentTeardownUnix(); - - optionUseReporting = savedData.getOptionUseReporting(); - optionErrorLevel = savedData.getOptionErrorLevel(); - optionHtmlBuildDesc = savedData.getOptionHtmlBuildDesc(); - optionExecutionReport = savedData.getOptionExecutionReport(); - optionClean = savedData.getOptionClean(); - useCILicenses = savedData.getUseCILicenses(); - useStrictTestcaseImport = savedData.getUseStrictTestcaseImport(); - useImportedResults = savedData.getUseImportedResults(); - useLocalImportedResults = savedData.getUseLocalImportedResults(); - useExternalImportedResults = savedData.getUseExternalImportedResults(); - externalResultsFilename = savedData.getExternalResultsFilename(); - useCoverageHistory = savedData.getUseCoverageHistory(); - maxParallel = savedData.getMaxParallel(); - - usingSCM = savedData.getUsingSCM(); - scm = savedData.getSCM(); - - waitTime = savedData.getWaitTime(); - waitLoops = savedData.getWaitLoops(); - jobName = savedData.getJobName(); - nodeLabel = savedData.getNodeLabel(); - pclpCommand = savedData.getPclpCommand(); - pclpResultsPattern = savedData.getPclpResultsPattern(); - squoreCommand = savedData.getSquoreCommand(); - TESTinsights_URL = savedData.getTESTinsights_URL(); - TESTinsights_project = savedData.getTESTinsights_project(); - TESTinsights_proxy = savedData.getTESTinsights_proxy(); - TESTinsights_credentials_id = savedData.getTESTinsights_credentials_id(); - TESTinsights_SCM_URL = savedData.getTESTinsights_SCM_URL(); - TESTinsights_SCM_Tech = savedData.getTESTinsights_SCM_Tech(); - } - /** - * Using some form of SCM + } + useCoverageHistory = json.optBoolean("useCoverageHistory", false); + maxParallel = json.optLong("maxParallel", 0); + + /* Additional Tools */ + pclpCommand = json.optString("pclpCommand", "").replace('\\', '/'); + pclpResultsPattern = json.optString("pclpResultsPattern", ""); + squoreCommand = json.optString("squoreCommand", "").replace('\\', '/'); + testInsightsUrl = json.optString("TESTinsights_URL", ""); + testInsightsProject = json.optString("TESTinsights_project", ""); + if (testInsightsProject.length() == 0) { + testInsightsProject = "env.JOB_BASE_NAME"; + } + testInsightsCredentialsId = + json.optString("TESTinsights_credentials_id", ""); + testInsightsProxy = json.optString("TESTinsights_proxy", ""); + + } + + /** + * Using some form of SCM. * @return true or false */ - protected boolean isUsingSCM() { - return usingSCM; + protected boolean isUsingScm() { + return usingScm; } /** - * Set using some form of SCM - * @param usingSCM true/false + * Set using some form of SCM. + * @param useScm true/false */ - protected void setUsingSCM(boolean usingSCM) { - this.usingSCM = usingSCM; + protected void setUsingSCM(final boolean useScm) { + this.usingScm = useScm; } /** - * Get environment setup for windows + * Get environment setup for windows. * @return setup */ protected String getEnvironmentSetupWin() { return environmentSetupWin; } - - /** - * Set environment setup for windows - * @param environmentSetupWin windows environment setup - */ - protected void setEnvironmentSetupWin(String environmentSetupWin) { - this.environmentSetupWin = environmentSetupWin; - } + /** - * Get execute preamble for windows + * Get execute preamble for windows. * @return preamble */ protected String getExecutePreambleWin() { return executePreambleWin; } /** - * Set execute preamble for windows - * @param executePreambleWin execute preamble for windows - */ - protected void setExecutePreambleWin(String executePreambleWin) { - this.executePreambleWin = executePreambleWin; - } - /** - * Get environment tear down for windows + * Get environment tear down for windows. * @return environment tear down for windows */ protected String getEnvironmentTeardownWin() { return environmentTeardownWin; } /** - * Set environment tear down for windows - * @param environmentTeardownWin environment tear down for windows - */ - protected void setEnvironmentTeardownWin(String environmentTeardownWin) { - this.environmentTeardownWin = environmentTeardownWin; - } - /** - * Get environment setup for unix + * Get environment setup for unix. * @return environment setup */ protected String getEnvironmentSetupUnix() { return environmentSetupUnix; } /** - * Set environment setup for unix - * @param environmentSetupUnix environment setup for unix - */ - protected void setEnvironmentSetupUnix(String environmentSetupUnix) { - this.environmentSetupUnix = environmentSetupUnix; - } - /** - * Get execute preamble for unix + * Get execute preamble for unix. * @return preamble */ protected String getExecutePreambleUnix() { return executePreambleUnix; } /** - * Set execute preamble for unix - * @param executePreambleUnix execute preamble for unix - */ - protected void setExecutePreambleUnix(String executePreambleUnix) { - this.executePreambleUnix = executePreambleUnix; - } - /** - * Get environment tear down for unix + * Get environment tear down for unix. * @return teardown */ protected String getEnvironmentTeardownUnix() { return environmentTeardownUnix; } /** - * Set environment teardown for unix - * @param environmentTeardownUnix environment tear down for unix - */ - protected void setEnvironmentTeardownUnix(String environmentTeardownUnix) { - this.environmentTeardownUnix = environmentTeardownUnix; - } - /** - * Get use Jenkins reporting option + * Get use Jenkins reporting option. * @return true to use, false to not */ protected boolean getOptionUseReporting() { return optionUseReporting; } /** - * Set use Jenkins reporting option - * @param optionUseReporting true to use, false to not + * Get error level. + * @return int 0 - Do nothing, 1 - Unstable, 2 - Error */ - protected void setOptionUseReporting(boolean optionUseReporting) { - this.optionUseReporting = optionUseReporting; - } - /** - * Get error level - * @return Unstable or Failure - */ - protected String getOptionErrorLevel() { + protected int getOptionErrorLevel() { return optionErrorLevel; } /** - * Set option error level - * @param optionErrorLevel Unstable or Failure - */ - protected void setOptionErrorLevel(String optionErrorLevel) { - this.optionErrorLevel = optionErrorLevel; - } - /** - * Use HTML Build Description + * Use HTML Build Description. * @return HTML or TEXT */ protected String getOptionHTMLBuildDesc() { return optionHtmlBuildDesc; } /** - * Set use HTML Build description - * @param optionHtmlBuildDesc HTML build description - */ - protected void setOptionHTMLBuildDesc(String optionHtmlBuildDesc) { - this.optionHtmlBuildDesc = optionHtmlBuildDesc; - } - /** - * Use execution report + * Use execution report. * @return true to use, false to not */ protected boolean getOptionExecutionReport() { return optionExecutionReport; } /** - * Set use execution report - * @param optionExecutionReport true to use, false to not - */ - protected void setOptionExecutionReport(boolean optionExecutionReport) { - this.optionExecutionReport = optionExecutionReport; - } - /** - * Get option to clean workspace before build + * Get option to clean workspace before build. * @return true to clean, false to not */ protected boolean getOptionClean() { return optionClean; } /** - * Set option to clean workspace before build - * @param optionClean true to clean, false to not - */ - protected void setOptionClean(boolean optionClean) { - this.optionClean = optionClean; - } - /** - * Get option to use CI licenses + * Get option to use CI licenses. * @return true to use CI licenses, false to not */ protected boolean getUseCILicenses() { return useCILicenses; } /** - * Set option to use CI licenses - * @param useCILicenses true to use CI licenses, false to not - */ - protected void setUseCILicenses(boolean useCILicenses) { - this.useCILicenses = useCILicenses; - } - /** - * Get option to Use strict testcase import + * Get option to Use strict testcase import. * @return true to Use strict testcase import, false to not */ protected boolean getUseStrictTestcaseImport() { return useStrictTestcaseImport; } /** - * Set option to Use strict testcase import - * @param useStrictTestcaseImport true to Use strict testcase import, false to not + * Get option to Use RGW3 capabilities. + * @return true use RGW3 capabilities, false to not */ - protected void setUseStrictTestcaseImport(boolean useStrictTestcaseImport) { - this.useStrictTestcaseImport = useStrictTestcaseImport; - } + protected boolean getUseRGW3() { + return useRGW3; + } /** - * Get option to Use imported results + * Get option to use coverage plugin or vectorcast coverage plugin. + * @return true use coverage plugin or vectorcast coverage plugin + */ + protected boolean getUseCoveragePlugin() { + return useCoveragePlugin; + } + /** + * Get option to Use imported results. * @return true to Use imported results, false to not */ protected boolean getUseImportedResults() { return useImportedResults; } - /** - * Set option to Use imported results - * @param useImportedResults true to Use imported results, false to not - */ - protected void setUseImportedResults(boolean useImportedResults) { - this.useImportedResults = useImportedResults; - } /** - * Get option to Use local imported results + * Get option to Use local imported results. * @return true to Use local imported results, false to not */ protected boolean getUseLocalImportedResults() { return useLocalImportedResults; } /** - * Set option to Use imported results - * @param useLocalImportedResults true to Use local imported results, false to not - */ - protected void setUseLocalImportedResults(boolean useLocalImportedResults) { - this.useLocalImportedResults = useLocalImportedResults; - } - - /** - * Get option to Use external imported results + * Get option to Use external imported results. * @return true to Use external imported results, false to not */ protected boolean getUseExternalImportedResults() { return useExternalImportedResults; } - /** - * Set option to Use imported results - * @param useExternalImportedResults true to Use external imported results, false to not - */ - protected void setUseExternalImportedResults(boolean useExternalImportedResults) { - this.useExternalImportedResults = useExternalImportedResults; - } /** - * Get option to Use as external result filename + * Get option to Use as external result filename. * @return string external result filename */ protected String getExternalResultsFilename() { return externalResultsFilename; } /** - * Set option to Use imported results - * @param externalResultsFilename true to Use external imported results, false to not - */ - protected void setExternalResultsFilename(String externalResultsFilename) { - this.externalResultsFilename = externalResultsFilename; - } - - /** - * Get option to Use coverage history to control build status + * Get option to Use coverage history to control build status. * @return true to Use imported results, false to not */ - protected boolean getUseCoverageHistory() { + public boolean getUseCoverageHistory() { return useCoverageHistory; } /** - * Set option to Use coverage history to control build status - * @param useCoverageHistory true to Use imported results, false to not - */ - protected void setUseCoverageHistory(boolean useCoverageHistory) { - this.useCoverageHistory = useCoverageHistory; - } - - /** - * Get for maxParallel to control maximum number of jobs to be queue at at any one point + * Get for maxParallel to control maximum number of + * jobs to be queue at at any one point. * @return MaxParallel integer number */ protected Long getMaxParallel() { return maxParallel; } - /** - * Set option for maxParallel to control maximum number of jobs to be queue at at any one point - * @param maxParallel Long number - */ - protected void setMaxParallel(Long maxParallel) { - this.maxParallel = maxParallel; - } /** - * Get environment setup for windows - * @return setup + * Get use CI license for Linux. + * @return String command to set */ protected String getUseCILicensesWin() { String ciEnvVars = ""; - + if (useCILicenses) { - ciEnvVars = "set VCAST_USING_HEADLESS_MODE=1\nset VCAST_USE_CI_LICENSES=1\n"; + ciEnvVars = "set VCAST_USING_HEADLESS_MODE=1\n" + + "set VCAST_USE_CI_LICENSES=1\n"; } return ciEnvVars; } + /** + * Get use CI license for Linux. + * @return String command to set + */ protected String getUseCILicensesUnix() { String ciEnvVars = ""; - + if (useCILicenses) { - ciEnvVars = "export VCAST_USING_HEADLESS_MODE=1\nexport VCAST_USE_CI_LICENSES=1\n"; + ciEnvVars = "export VCAST_USING_HEADLESS_MODE=1\n" + + "export VCAST_USE_CI_LICENSES=1\n"; } return ciEnvVars; } /** - * Get the time to wait between retries + * Get the time to wait between retries. * @return number of seconds */ protected Long getWaitTime() { return waitTime; } /** - * Get the number of wait loops + * Get the number of wait loops. * @return number of iterations */ protected Long getWaitLoops() { return waitLoops; } /** - * Get the user-specified job name + * Get the user-specified job name. * @return job name (null for use default) */ protected String getJobName() { return jobName; } /** - * Get top-level project + * Get top-level project. * @return project */ - protected Project getTopProject() { + protected Project getTopProject() { return topProject; } /** - * Get manage project name + * Get manage project name. * @return manage project name */ protected String getManageProjectName() { return manageProjectName; } /** - * Get base name of manage project + * Get base name of manage project. * @return base name */ protected String getBaseName() { return baseName; } /** - * Get node label + * Get node label. * @return node label */ protected String getNodeLabel() { return nodeLabel; } /** - * Get pc-lint plus command + * Get pc-lint plus command. * @return pc-lint plus command */ protected String getPclpCommand() { return pclpCommand; } /** - * Get pc-lint plus result pattern + * Get pc-lint plus result pattern. * @return pc-lint plus result pattern */ protected String getPclpResultsPattern() { return pclpResultsPattern; } - + /** - * Get command for running Squore + * Get command for running Squore. * @return Squore command */ protected String getSquoreCommand() { return squoreCommand; - } + } /** - * Get URL for TESTinsights + * Get URL for TESTinsights. * @return TESTinsights URL */ - protected String getTESTinsights_URL() { - return TESTinsights_URL; - } + protected String getTestInsightsUrl() { + return testInsightsUrl; + } /** - * Get Project for TESTinsights + * Get Project for TESTinsights. * @return TESTinsights Project */ - protected String getTESTinsights_project() { - return TESTinsights_project; - } + protected String getTestInsightsProject() { + return testInsightsProject; + } /** - * Set Project for TESTinsights - * @param TESTinsights_project TESTinsights project name + * set Project for TESTinsights. + * @param project TESTinsights Project */ - protected void setTESTinsights_project(String TESTinsights_project) { - this.TESTinsights_project = TESTinsights_project; - } + protected void setTestInsightsProject(final String project) { + this.testInsightsProject = project; + } /** - * Get Proxy for TESTinsights - * @return TESTinsights proxy + * Get Proxy for TESTinsights. + * @return proxy TESTinsights proxy */ - protected String getTESTinsights_proxy() { - return TESTinsights_proxy; - } + protected String getTestInsightsProxy() { + return testInsightsProxy; + } /** - * Get Credentials for TESTinsights + * Get Credentials for TESTinsights. * @return TESTinsights Credentials */ - protected String getTESTinsights_credentials_id() { - return TESTinsights_credentials_id; - } + protected String getTestInsightsCredentialsId() { + return testInsightsCredentialsId; + } /** - * Get SCM URL for TESTinsights + * Set SCM URL for TESTinsights. + * @param url TESTinsights SCM URL + */ + protected void setTestInsightsScmUrl(final String url) { + this.testInsightsScmUrl = url; + } + /** + * Get SCM URL for TESTinsights. * @return TESTinsights SCM URL */ - protected String getTESTinsights_SCM_URL() { - return TESTinsights_SCM_URL; - } + protected String getTestInsightsScmUrl() { + return testInsightsScmUrl; + } /** - * Get SCM Technology TESTinsights + * Get SCM Technology TESTinsights. * @return TESTinsights SCM Technology */ - protected String getTESTinsights_SCM_Tech() { - return TESTinsights_SCM_Tech; - } + protected String getTestInsightsScmTech() { + return testInsightsScmTech; + } /** - * Set SCM URL for TESTinsights - * @param TESTinsights_SCM_URL - String TESTinsights SCM URL + * Set SCM Technology TESTinsights. + * @param tech TESTinsights SCM Technology */ - - protected void setTESTinsights_SCM_URL(String TESTinsights_SCM_URL) { - this.TESTinsights_SCM_URL = TESTinsights_SCM_URL; - } - /** - * Set SCM Technology TESTinsights - * @param TESTinsights_SCM_Tech - String TESTinsights SCM Techology (git or svn) - */ - protected void setTESTinsights_SCM_Tech(String TESTinsights_SCM_Tech) { - this.TESTinsights_SCM_Tech = TESTinsights_SCM_Tech; - } + protected void setTestInsightsScmTech(final String tech) { + this.testInsightsScmTech = tech; + } /** - * Get request + * Get request. * @return request */ protected StaplerRequest getRequest() { return request; } /** - * Get Jenkins instance + * Get Jenkins instance. * @return Jenkins instance */ protected Jenkins getInstance() { return instance; } /** - * Get response + * Get the name of the project. + * @return the project name + */ + public String getProjectName() { + return projectName; + } + /** + * Sets the name of the project. + * @param pName - project name + */ + public void setProjectName(final String pName) { + this.projectName = pName; + } + /** + * Get response. * @return response */ protected StaplerResponse getResponse() { return response; } /** - * Add the delete workspace before build starts option + * Add the delete workspace before build starts option. * @param project project to add to */ - protected void addDeleteWorkspaceBeforeBuildStarts(Project project) { + protected void addDelWSBeforeBuild(final Project project) { if (optionClean) { - PreBuildCleanup cleanup = new PreBuildCleanup(/*patterns*/null, true, /*cleanup param*/"", /*external delete*/""); + PreBuildCleanup cleanup = new PreBuildCleanup( + null, /*patterns*/ + true, + "", /*cleanup param*/ + "", /*external delete*/ + false /*disableDeferredWipeout*/ + ); project.getBuildWrappersList().add(cleanup); } } /** - * Create the job(s) - * @param update true/false + * Create the job(s). * @throws IOException exception * @throws ServletException exception * @throws hudson.model.Descriptor.FormException exception * @throws JobAlreadyExistsException exception * @throws InvalidProjectFileException exception */ - public void create(boolean update) throws IOException, ServletException, Descriptor.FormException, JobAlreadyExistsException, InvalidProjectFileException { + public void create() + throws IOException, ServletException, + Descriptor.FormException, + JobAlreadyExistsException, + InvalidProjectFileException { // Create the top-level project topProject = createProject(); if (topProject == null) { - Logger.getLogger(BaseJob.class.getName()).log(Level.INFO, "Could not create topProject"); return; } - if (!useSavedData) { - // Read the SCM setup - scm = SCMS.parseSCM(request, topProject); - if (scm == null) { - scm = new NullSCM(); - } - if (scm instanceof NullSCM) { - usingSCM = false; + // Read the SCM setup + scm = SCMS.parseSCM(request, topProject); + if (scm == null) { + scm = new NullSCM(); + } + if (scm instanceof NullSCM) { + usingScm = false; + } else { + usingScm = true; + + // for TESTinsights SCM connector + String scmName = scm.getDescriptor().getDisplayName(); + if (scmName.equals("Git")) { + testInsightsScmTech = "git"; + } else if (scmName.equals("Subversion")) { + testInsightsScmTech = "svn"; } else { - usingSCM = true; - - // for TESTinsights SCM connector - String scmName = scm.getDescriptor().getDisplayName(); - if (scmName == "Git") { - TESTinsights_SCM_Tech = "git"; - } else if (scmName == "Subversion") { - TESTinsights_SCM_Tech = "svn"; - } else { - TESTinsights_SCM_Tech = ""; - } - Logger.getLogger(BaseJob.class.getName()).log(Level.INFO, "SCM Info: " + scmName); + testInsightsScmTech = ""; } } topProject.setScm(scm); - addDeleteWorkspaceBeforeBuildStarts(topProject); + addDelWSBeforeBuild(topProject); try { - doCreate(update); + doCreate(); } catch (InvalidProjectFileException ex) { cleanupProject(); throw ex; } } /** - * Create top-level project + * Create top-level project. * @return created project * @throws IOException exception * @throws JobAlreadyExistsException exception */ - abstract protected Project createProject() throws IOException, JobAlreadyExistsException; + protected abstract Project createProject() + throws IOException, JobAlreadyExistsException; /** - * Cleanup top-level project, as in delete + * Cleanup top-level project, as in delete. */ - abstract protected void cleanupProject(); + protected abstract void cleanupProject(); /** - * Do create of project details - * @param update true if doing an update rather than a create + * Do create of project details. * @throws IOException exception * @throws ServletException exception * @throws hudson.model.Descriptor.FormException exception * @throws InvalidProjectFileException exception */ - abstract protected void doCreate(boolean update) throws IOException, ServletException, Descriptor.FormException, InvalidProjectFileException ; + protected abstract void doCreate() + throws IOException, + ServletException, + Descriptor.FormException, + InvalidProjectFileException; + /** - * Add the VectorCAST setup step to copy the python scripts to + * Add the VectorCAST setup step to copy the python scripts to. * the workspace * @param project project * @return the setup build step */ - protected VectorCASTSetup addSetup(Project project) { - VectorCASTSetup setup = - new VectorCASTSetup(environmentSetupWin, - environmentSetupUnix, - executePreambleWin, - executePreambleUnix, - environmentTeardownWin, - environmentTeardownUnix, - optionUseReporting, - optionErrorLevel, - optionHtmlBuildDesc, - optionExecutionReport, - optionClean, - useCILicenses, - useStrictTestcaseImport, - useImportedResults, - useLocalImportedResults, - useExternalImportedResults, - externalResultsFilename, - useCoverageHistory, - waitLoops, - waitTime, - maxParallel, - manageProjectName, - jobName, - nodeLabel, - pclpCommand, - pclpResultsPattern, - squoreCommand, - TESTinsights_URL, - TESTinsights_project, - TESTinsights_credentials_id, - TESTinsights_proxy, - TESTinsights_SCM_URL, - TESTinsights_SCM_Tech); - - setup.setUsingSCM(usingSCM); - setup.setSCM(scm); + protected VectorCASTSetup addSetup(final Project project) + throws IOException { + VectorCASTSetup setup = new VectorCASTSetup(); project.getBuildersList().add(setup); + return setup; } /** - * Add archive artifacts step + * Add archive artifacts step. * @param project project to add to */ - protected void addArchiveArtifacts(Project project) { + protected void addArchiveArtifacts(final Project project) { String pclpArchive = ""; - String TIArchive = ""; - + String tiArchive = ""; + if (pclpCommand.length() != 0) { pclpArchive = ", " + pclpResultsPattern; } - if (TESTinsights_URL.length() != 0) { - TIArchive = ", TESTinsights_Push.log"; + if (testInsightsUrl.length() != 0) { + tiArchive = ", TESTinsights_Push.log"; } - String addToolsArchive = pclpArchive + TIArchive; - - ArtifactArchiver archiver = new ArtifactArchiver( - /*artifacts*/"**/*.html, xml_data/*.xml, unit_test_fail_count.txt, **/*.png, **/*.css, complete_build.log, *_results.vcr" + addToolsArchive, - /*excludes*/"", - /*latest only*/false, - /*allow empty archive*/false); + String addToolsArchive = pclpArchive + tiArchive; + String defaultArchive = "**/*.html, xml_data/**/*.xml," + + "unit_test_*.txt, **/*.png, **/*.css," + + "complete_build.log, *_results.vcr"; + + ArtifactArchiver archiver = + new ArtifactArchiver(defaultArchive + addToolsArchive); + archiver.setExcludes(""); + archiver.setAllowEmptyArchive(false); project.getPublishersList().add(archiver); } /** - * Add archive artifacts step + * Add archive artifacts step. * @param project project to add to */ - protected void addCopyResultsToImport(Project project) { + protected void addCopyResultsToImport(final Project project) { StatusBuildSelector selector = new StatusBuildSelector(); - CopyArtifact archiverCopier = new CopyArtifact( - /* ProjectName */ project.getName(), - /* Parameters */ "", - /* BuildSelector */ selector, - /* filter */ baseName + "_results.vcr", - /* target */ "", - /* flatten */ false, - /* optional */ true - ); + CopyArtifact archiverCopier = new CopyArtifact(project.getName()); + archiverCopier.setParameters(""); + archiverCopier.setSelector(selector); + archiverCopier.setFilter(baseName + "_results.vcr"); + archiverCopier.setTarget(""); + archiverCopier.setFlatten(false); + archiverCopier.setOptional(true); + project.getBuildersList().add(archiverCopier); } /** - * Add JUnit rules step + * Add JUnit rules step. * @param project project to add step to */ - protected void addJunit(Project project) { - JUnitResultArchiver junit = new JUnitResultArchiver("**/test_results_*.xml"); + protected void addJunit(final Project project) { + JUnitResultArchiver junit = + new JUnitResultArchiver("**/test_results_*.xml"); project.getPublishersList().add(junit); } /** - * Add PC-Lint Plus step + * Add PC-Lint Plus step. * @param project project to add step to do PC-Lint Plus */ - protected void addPCLintPlus(Project project) { + protected void addPCLintPlus(final Project project) { if (pclpCommand.length() != 0) { IssuesRecorder recorder = new IssuesRecorder(); @@ -939,25 +854,142 @@ protected void addPCLintPlus(Project project) { pcLintPlus.setPattern(pclpResultsPattern); pcLintPlus.setReportEncoding("UTF-8"); pcLintPlus.setSkipSymbolicLinks(false); - + recorder.setTools(pcLintPlus); project.getPublishersList().add(recorder); } } /** - * Add VectorCAST coverage reporting step + * Add VectorCAST coverage reporting step. * @param project project to add step to */ - protected void addVCCoverage(Project project) { - VectorCASTHealthReportThresholds healthReports = new VectorCASTHealthReportThresholds(0, 100, 0, 70, 0, 80, 0, 80, 0, 80, 0, 80); + protected void addVCCoverage(final Project project) { + VectorCASTHealthReportThresholds healthReports = + new VectorCASTHealthReportThresholds( + ZERO_PERCENT, ONE_HUNDREAD_PERCENT, + ZERO_PERCENT, SEVENTY_PERCENT, + ZERO_PERCENT, EIGHTY_PERCENT, + ZERO_PERCENT, EIGHTY_PERCENT, + ZERO_PERCENT, EIGHTY_PERCENT, + ZERO_PERCENT, EIGHTY_PERCENT); VectorCASTPublisher publisher = new VectorCASTPublisher(); publisher.includes = "**/coverage_results_*.xml"; publisher.healthReports = healthReports; publisher.setUseCoverageHistory(useCoverageHistory); project.getPublishersList().add(publisher); } - protected void addCredentialID(Project project) { - project.getBuildWrappersList().add(new SecretBuildWrapper(Collections.>singletonList(new UsernamePasswordMultiBinding("VC_TI_USR","VC_TI_PWS",TESTinsights_credentials_id)))); + /** + * Add Jenkins coverage reporting step. + * @param project project to add step to + */ + protected void addReferenceBuild(final Project project) { + SimpleReferenceRecorder refRec = new SimpleReferenceRecorder(); + + project.getPublishersList().add(refRec); + } + + /** + * Add Jenkins coverage reporting step. + * @param project project to add step to + */ + protected void addJenkinsCoverage(final Project project) { + + List qualityGates = null; + + CoverageTool tool = new CoverageTool(); + tool.setParser(Parser.VECTORCAST); + tool.setPattern("xml_data/cobertura/coverage_results*.xml"); + + if (getUseCoverageHistory()) { + CoverageQualityGate statement = + new CoverageQualityGate(Metric.LINE); + statement.setBaseline(Baseline.PROJECT_DELTA); + statement.setCriticality(QualityGateCriticality.ERROR); + statement.setThreshold(COVERAGE_THRESHOLD); + + CoverageQualityGate branch = new CoverageQualityGate(Metric.BRANCH); + branch.setBaseline(Baseline.PROJECT_DELTA); + branch.setCriticality(QualityGateCriticality.ERROR); + branch.setThreshold(COVERAGE_THRESHOLD); + + qualityGates = new ArrayList(); + qualityGates.add(statement); + qualityGates.add(branch); + + } + + //tool.setQualityGate(); + List list = new ArrayList(); + list.add(tool); + + CoverageRecorder publisher = new CoverageRecorder(); + publisher.setTools(list); + + if (qualityGates != null) { + publisher.setQualityGates(qualityGates); + } + + project.getPublishersList().add(publisher); + } + /** + * Add credentials for coverage reporting step. + * @param project project to add step to + */ + protected void addCredentialID(final Project project) { + project.getBuildWrappersList().add( + new SecretBuildWrapper(Collections.>singletonList( + new UsernamePasswordMultiBinding("VC_TI_USR", "VC_TI_PWS", + testInsightsCredentialsId)))); + } + + /** + * Call to get baseline windows single job file. + * @return URL for baseline file + */ + protected URL getBaselineWindowsSingleFile() { + // GOOD: The call is always made on an object of the same type. + return BaseJob.class. + getResource("/scripts/baselineSingleJobWindows.txt"); + } + /** + * Call to get baseline linux single job file. + * @return URL for baseline file + */ + protected URL getBaselineLinuxSingleFile() { + // GOOD: The call is always made on an object of the same type. + return BaseJob.class.getResource("/scripts/baselineSingleJobLinux.txt"); + } + /** + * Call to get baseline post-build groovy job file. + * @return URL for baseline file + */ + protected URL getBaselinePostBuildGroovyScript() { + // GOOD: The call is always made on an object of the same type. + return BaseJob.class.getResource("/scripts/baselinePostBuild.groovy"); + } + /** + * Call to get baseline config.xml with parameters for pipeline job . + * @return URL for baseline file + */ + protected URL getPipelineConfigParametersXML() { + // GOOD: The call is always made on an object of the same type. + return BaseJob.class.getResource("/scripts/config_parameters.xml"); + } + /** + * Call to get baseline config.xml for pipeline job . + * @return URL for baseline file + */ + protected URL getPipelineConfigXML() { + // GOOD: The call is always made on an object of the same type. + return BaseJob.class.getResource("/scripts/config.xml"); + } + /** + * Call to get baseline groovy script for pipeline job. + * @return URL for baseline file + */ + protected URL getBaselinePipelineGroovy() { + // GOOD: The call is always made on an object of the same type. + return BaseJob.class.getResource("/scripts/baseJenkinsfile.groovy"); } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ExternalResultsFileException.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ExternalResultsFileException.java index dadb0537..8f6aba26 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ExternalResultsFileException.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/ExternalResultsFileException.java @@ -24,10 +24,16 @@ package com.vectorcast.plugins.vectorcastexecution.job; /** - * Exception raised if the supplied manage project file cannot be read + * Exception raised if the supplied manage project file cannot be read. */ public class ExternalResultsFileException extends Exception { + /** serial version of class fpr serialization. */ + private static final long serialVersionUID = 7429348150624478731L; + + /** + * Classes default construtor to call parent. + */ public ExternalResultsFileException() { super(); - } + } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/InvalidProjectFileException.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/InvalidProjectFileException.java index e71cb803..5957eefa 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/InvalidProjectFileException.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/InvalidProjectFileException.java @@ -24,10 +24,16 @@ package com.vectorcast.plugins.vectorcastexecution.job; /** - * Exception raised if the supplied manage project file cannot be read + * Exception raised if the supplied manage project file cannot be read. */ public class InvalidProjectFileException extends Exception { + /** serial version of class fpr serialization. */ + private static final long serialVersionUID = 3544833590470742391L; + + /** + * Classes default construtor to call parent. + */ public InvalidProjectFileException() { super(); - } + } } diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/JobAlreadyExistsException.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/JobAlreadyExistsException.java index a80bbaab..a06bb79f 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/JobAlreadyExistsException.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/JobAlreadyExistsException.java @@ -24,20 +24,24 @@ package com.vectorcast.plugins.vectorcastexecution.job; /** - * Exception raised if job being created already exists + * Exception raised if job being created already exists. */ public class JobAlreadyExistsException extends Exception { - /** Name of project */ + /** serial Version UID. */ + private static final long serialVersionUID = 2678119599631146760L; + + /** Name of project. */ private final String project; + /** - * Constructor - * @param project name of project + * Constructor. + * @param proj name of project */ - public JobAlreadyExistsException(String project) { - this.project = project; + public JobAlreadyExistsException(final String proj) { + this.project = proj; } /** - * Get project name + * Get project name. * @return project name */ public String getProject() { diff --git a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java index fc1e742c..55e80d8e 100644 --- a/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java +++ b/src/main/java/com/vectorcast/plugins/vectorcastexecution/job/NewPipelineJob.java @@ -30,16 +30,10 @@ import hudson.model.Project; import net.sf.json.JSONObject; -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -49,6 +43,7 @@ import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.interceptor.RequirePOST; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.SAXException; @@ -61,206 +56,225 @@ import java.util.logging.Logger; import java.util.logging.Level; -import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; -import java.nio.charset.StandardCharsets; + +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.nio.file.StandardCopyOption; + +import java.util.EnumSet; /** - * Create a new single job + * Create a new single job. */ public class NewPipelineJob extends BaseJob { - /** project name */ - private String projectName; - private Project topProject; - + /** shared artifact directory. */ private String sharedArtifactDirectory; - + /** Pipeline SCM string - multi-line. */ private String pipelineSCM = ""; - + /** Single Checkout. */ private boolean singleCheckout; - + /** Using change based testing. */ private boolean useCBT; - + /** Use pipeline parameters. */ private boolean useParameters; - + /** Post SCM checkout command. */ private String postSCMCheckoutCommands; - - /** Environment setup script */ + /** Environment setup script. */ private String environmentSetup; - /** Execute preamble */ + /** Execute preamble. */ private String executePreamble; - /** Environment tear down*/ + /** Environment tear down. */ private String environmentTeardown; /** - * Constructor - * + * Constructor. + * * @param request request object * @param response response object * @throws ServletException exception * @throws IOException exception * @throws ScmConflictException exception * @throws ExternalResultsFileException exception + * @throws BadOptionComboException exception */ - public NewPipelineJob(final StaplerRequest request, final StaplerResponse response) - throws ServletException, IOException, ScmConflictException, ExternalResultsFileException { - super(request, response, false); - + public NewPipelineJob( + final StaplerRequest request, + final StaplerResponse response) + throws ServletException, IOException, + ScmConflictException, ExternalResultsFileException, + BadOptionComboException { + super(request, response); + + final int indexNotFound = -1; + JSONObject json = request.getSubmittedForm(); - - sharedArtifactDirectory = json.optString("sharedArtifactDir",""); - pipelineSCM = json.optString("scmSnippet","").trim(); - + + sharedArtifactDirectory = json.optString("sharedArtifactDir", ""); + pipelineSCM = json.optString("scmSnippet", "").trim(); + String[] lines = pipelineSCM.split("\n"); - - List scm_list = new ArrayList(); - scm_list.add("git"); - scm_list.add("svn"); - + + List scmList = new ArrayList(); + scmList.add("git"); + scmList.add("svn"); + String url = ""; - String scm_technology = ""; + String scmTechnology = ""; for (String line : lines) { - - for (String scm : scm_list) { + + for (String scm : scmList) { if (line.startsWith(scm)) { - scm_technology = scm; - - if (line.indexOf("url:") == -2) { + scmTechnology = scm; + + if (line.indexOf("url:") == indexNotFound) { String[] elements = line.split(","); for (String ele : elements) { - + if (ele.startsWith("url:")) { - String[] ele_list = ele.split(" "); - url = ele_list[ele_list.length - 1]; + String[] eleList = ele.split(" "); + url = eleList[eleList.length - 1]; } } } else { - String[] url_ele = line.split(" "); - url = url_ele[url_ele.length - 1]; + String[] urlEle = line.split(" "); + url = urlEle[urlEle.length - 1]; } } } } - setTESTinsights_SCM_URL(url.replace("'","")); - setTESTinsights_SCM_Tech(scm_technology); - + setTestInsightsScmUrl(url.replace("'", "")); + setTestInsightsScmTech(scmTechnology); + singleCheckout = json.optBoolean("singleCheckout", false); - - // remove the win/linux options since there's no platform any more + + // remove the win/linux options since there's no platform any more environmentSetup = json.optString("environmentSetup", null); executePreamble = json.optString("executePreamble", null); environmentTeardown = json.optString("environmentTeardown", null); - postSCMCheckoutCommands = json.optString("postSCMCheckoutCommands", null); + postSCMCheckoutCommands = + json.optString("postSCMCheckoutCommands", null); useCBT = json.optBoolean("useCBT", true); useParameters = json.optBoolean("useParameters", false); if (sharedArtifactDirectory.length() != 0) { - sharedArtifactDirectory = "--workspace="+sharedArtifactDirectory.replace("\\","/"); + sharedArtifactDirectory = "--workspace=" + + sharedArtifactDirectory.replace("\\", "/"); } - - /* absoulte path and SCM checkout of manage project conflicts with - the copy_build_dir.py ability to make LIS files relative path + + /* absoulte path and SCM checkout of manage project conflicts with + the copy_build_dir.py ability to make LIS files relative path */ - String MPName = this.getManageProjectName().replaceAll("^[ \t]+|[ \t]+$", ""); - Boolean absPath = false; - - if (MPName.startsWith("\\\\")) absPath = true; - if (MPName.startsWith("/")) absPath = true; - if (MPName.matches("[a-zA-Z]:.*")) absPath = true; - - if (! MPName.toLowerCase().endsWith(".vcm")) MPName += ".vcm"; - - Logger.getLogger(NewPipelineJob.class.getName()).log(Level.INFO, "MPName: " + MPName + " scmSnippet: " + pipelineSCM); + String mpName = getManageProjectName(); + boolean absPath = false; - if (pipelineSCM.length() != 0 && absPath) { - throw new ScmConflictException(pipelineSCM, MPName); + if (mpName.startsWith("\\\\")) { + absPath = true; } - - if (getTESTinsights_project() == "env.JOB_BASE_NAME") { - setTESTinsights_project("${JOB_BASE_NAME}"); + if (mpName.startsWith("/")) { + absPath = true; + } + if (mpName.matches("[a-zA-Z]:.*")) { + absPath = true; } - } - /** - * Get the name of the project - * - * @return the project name - */ - public String getProjectName() { - Logger.getLogger(NewPipelineJob.class.getName()).log(Level.INFO, "Pipeline Project Name: " + projectName, "Pipeline Project Name: " + projectName); - - return projectName; + if (!mpName.toLowerCase().endsWith(".vcm")) { + mpName += ".vcm"; + } + + if (pipelineSCM.length() != 0 && absPath) { + throw new ScmConflictException(pipelineSCM, mpName); + } + + if (getTestInsightsProject().equals("env.JOB_BASE_NAME")) { + setTestInsightsProject("${JOB_BASE_NAME}"); + } } /** - * Create project - * + * Create project. + * * @return project * @throws IOException exception * @throws JobAlreadyExistsException exception - + */ @Override - protected Project createProject() throws IOException, JobAlreadyExistsException { + protected Project createProject() + throws IOException, JobAlreadyExistsException { + String projectName; if (getBaseName().isEmpty()) { - getResponse().sendError(HttpServletResponse.SC_NOT_MODIFIED, "No project name specified"); + getResponse().sendError(HttpServletResponse.SC_NOT_MODIFIED, + "No project name specified"); return null; } if (getJobName() != null && !getJobName().isEmpty()) { projectName = getJobName(); - } - else { - projectName = getBaseName() + ".vcast.pipeline"; + } else { + projectName = getBaseName() + ".vcast.pipeline"; } // Remove all non-alphanumeric characters from the Jenkins Job name - projectName = projectName.replaceAll("[^a-zA-Z0-9_]","_"); - + projectName = projectName.replaceAll("[^a-zA-Z0-9_]", "_"); + + setProjectName(projectName); + if (getInstance().getJobNames().contains(projectName)) { throw new JobAlreadyExistsException(projectName); } - - Logger.getLogger(NewPipelineJob.class.getName()).log(Level.INFO, "Pipeline Project Name: " + projectName, "Pipeline Project Name: " + projectName); + + Logger.getLogger(NewPipelineJob.class.getName()).log(Level.INFO, + "Pipeline Project Name: " + projectName, + "Pipeline Project Name: " + projectName); return null; } /** - * Add build steps - * - * @param update true to update, false to not + * Add build steps. + * * @throws IOException exception * @throws ServletException exception * @throws hudson.model.Descriptor.FormException exception */ @Override - public void doCreate(boolean update) throws IOException, ServletException, Descriptor.FormException { - + @RequirePOST + public void doCreate() + throws IOException, ServletException, Descriptor.FormException { + // Get config.xml resource from jar and write it to temp - File configFile = writeConfigFile(); + File configFile = writeConfigFileWithFiles(); try { - // Modify XML to include generated pipeline script, remove sandbox restriction + // Modify XML to include generated pipeline script, + // remove sandbox restriction String configPath = configFile.getAbsolutePath(); - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory documentBuilderFactory = + DocumentBuilderFactory.newInstance(); - DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + DocumentBuilder documentBuilder = + documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse(configPath); Node scriptNode = document.getElementsByTagName("script").item(0); scriptNode.setTextContent(generateJenkinsfile()); // Write DOM object to the file - TransformerFactory transformerFactory = TransformerFactory.newInstance(); + TransformerFactory transformerFactory = + TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource domSource = new DOMSource(document); @@ -270,13 +284,14 @@ public void doCreate(boolean update) throws IOException, ServletException, Descr InputStream xmlInput = new FileInputStream(configFile); try { - /** + /* * hudson.model.Project Project proj = (Project) Fails with - * java.lang.ClassCastException: org.jenkinsci.plugins.workflow.job.WorkflowJob + * java.lang.ClassCastException: + * org.jenkinsci.plugins.workflow.job.WorkflowJob * cannot be cast to Project */ - getInstance().createProjectFromXML(this.projectName, xmlInput); + getInstance().createProjectFromXML(getProjectName(), xmlInput); } catch (IOException e) { e.printStackTrace(); } finally { @@ -291,117 +306,202 @@ public void doCreate(boolean update) throws IOException, ServletException, Descr e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); - } catch (java.lang.IllegalArgumentException e) { + } catch (IllegalArgumentException e) { e.printStackTrace(); } - + if (!configFile.delete()) { - throw new IOException("Unable to delete file: " + configFile.getAbsolutePath()); + throw new IOException("Unable to delete file: " + + configFile.getAbsolutePath()); } } /** - * Create the Pipeline Jenkinsfile script + * Create the Pipeline Jenkinsfile script. * @throws IOException exception * @throws ServletException exception * @throws hudson.model.Descriptor.FormException exception * @throws JobAlreadyExistsException exception * @throws InvalidProjectFileException exception - */ - public void create(boolean update) throws IOException, ServletException, Descriptor.FormException, - JobAlreadyExistsException, InvalidProjectFileException { - - // Create the top-level project - topProject = createProject(); - doCreate(update); + */ + @Override + public void create() + throws IOException, ServletException, Descriptor.FormException, + JobAlreadyExistsException, InvalidProjectFileException { + + // Create the top-level project + createProject(); + doCreate(); + } + + private static Path createTempFile(final Path tempDirChild) + throws UncheckedIOException { + try { + if (tempDirChild.getFileSystem().supportedFileAttributeViews(). + contains("posix")) { + // Explicit permissions setting is only required + // on unix-like systems because + // the temporary directory is shared between all users. + // This is not necessary on Windows, + // each user has their own temp directory + final EnumSet posixFilePermissions = + EnumSet.of( + PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE + ); + if (!Files.exists(tempDirChild)) { + Files.createFile( + tempDirChild, + PosixFilePermissions + .asFileAttribute(posixFilePermissions) + ); + } else { + Files.setPosixFilePermissions( + tempDirChild, + posixFilePermissions + ); // GOOD: Good has permissions `-rw-------`, + //or will throw an exception if this fails + } + } else if (!Files.exists(tempDirChild)) { + // On Windows, we still need to create the directory, + // when it doesn't already exist. + Files.createDirectory(tempDirChild); + } + + return tempDirChild.toAbsolutePath(); + } catch (IOException exception) { + throw new UncheckedIOException("Failed to create temp file", + exception); } - + } + /** - * Retrieves config.xml from the jar and writes it to the systems temp + * Retrieves config.xml from the jar and writes it to the systems temp. * directory. - * - * @return - * @throws IOException + * + * @return File - temporary file + * @throws UncheckedIOException */ - private File writeConfigFile() throws IOException { + private File writeConfigFileWithFiles() throws IOException { - InputStream in; + Path configFile; if (useParameters) { - in = getClass().getResourceAsStream("/scripts/config_parameters.xml"); + in = getPipelineConfigParametersXML().openStream(); } else { - in = getClass().getResourceAsStream("/scripts/config.xml"); + in = getPipelineConfigXML().openStream(); } - - //InputStream in = getClass().getResourceAsStream("/scripts/config_parameters.xml"); - BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); - File configFile = File.createTempFile("config_temp", ".xml"); - //FileWriter fw = null - FileOutputStream fosw = null; - OutputStreamWriter osrw = null; + configFile = createTempFile(Paths.get("config_temp.xml")); try { - // write out to temp file - //fw = new FileWriter(configFile); - //bw = new BufferedWriter(fw); - fosw = new FileOutputStream(configFile); - osrw = new OutputStreamWriter(fosw, StandardCharsets.UTF_8); - - if (fosw != null && osrw != null) { - String line = null; - while ((line = br.readLine()) != null) { - osrw.write(line + "\n"); - } - } - } finally { - // cleanup - if (osrw != null) osrw.close(); - br.close(); - in.close(); - if (fosw != null) fosw.close(); + Files.copy(in, configFile, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException ex) { + Logger.getLogger(NewPipelineJob.class.getName()) + .log(Level.INFO, null, ex); + } catch (UnsupportedOperationException ex) { + Logger.getLogger(NewPipelineJob.class.getName()) + .log(Level.INFO, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(NewPipelineJob.class.getName()) + .log(Level.INFO, null, ex); } - return configFile.getAbsoluteFile(); + return configFile.toFile(); } /** - * Get getSharedArtifactDirectory + * Get pipelineSCM. + * @return pipelineSCM String + */ + protected String getPipelineSCM() { + return this.pipelineSCM; + } + /** + * Get getPostSCMCheckoutCommands. + * @return postSCMCheckoutCommands String + */ + protected String getPostSCMCheckoutCommands() { + return this.postSCMCheckoutCommands; + } + + /** + * Get getUseParameters. + * @return useParameters boolean + */ + protected boolean getUseParameters() { + return this.useParameters; + } + + /** + * Get getSingleCheckout. + * @return singleCheckout boolean + */ + protected boolean getSingleCheckout() { + return this.singleCheckout; + } + + /** + * Get getEnvironmentSetup. + * @return environmentSetup String + */ + protected String getEnvironmentSetup() { + return this.environmentSetup; + } + + /** + * Get getExecutePreamble. + * @return executePreamble String + */ + protected String getExecutePreamble() { + return this.executePreamble; + } + + /** + * Get getExecutePreamble. + * @return executePreamble String + */ + protected String getEnvironmentTeardown() { + return this.environmentTeardown; + } + + /** + * Get getSharedArtifactDirectory. * @return sharedArtifactDirectory string */ - protected String getSharedArtifactDirectory() { + protected String getSharedArtifactDir() { return this.sharedArtifactDirectory; } /** - * Get BaseJenkinsfile - * @return BaseJenkinsfile string + * Get getUseCBT. + * @return getUseCBT boolean */ - private String getBaseJenkinsfile() throws IOException { - String result = null; - InputStream in = getClass().getResourceAsStream("/scripts/baseJenkinsfile.groovy"); - - try { - result = IOUtils.toString(in); - } catch (IOException ex) { - Logger.getLogger(NewPipelineJob.class.getName()).log(Level.SEVERE, null, ex); - } finally { - in.close(); - } + protected boolean getUseCBT() { + return this.useCBT; + } - return result; + /** + * Corrects the input path to be all / based. + * + * @param in input string + * @return String correct path. + */ + private String correctPath(final String in) { + return in.replace("\\", "/").replace("\"", "\\\""); } + /** - * Generates the