2 | "Scan non-scanned builds" option scans only non-scanned builds.
3 | "Scan/Rescan all the builds" option scans all the builds including scanned and non-scanned builds.
4 |
5 |
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureReaderTest.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/build-failure-analyzer-plugin/HEAD/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureReaderTest.zip
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/BackwardsCompatibilityTest/testMatrix120.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/build-failure-analyzer-plugin/HEAD/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/BackwardsCompatibilityTest/testMatrix120.zip
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/resource.js:
--------------------------------------------------------------------------------
1 | document.addEventListener("DOMContentLoaded", () => {
2 | document.querySelector(".bfa-cause-management-back-button").addEventListener("click", () => {
3 | history.back(1);
4 | });
5 | });
6 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndication/help-textSource.html:
--------------------------------------------------------------------------------
1 | A value indicating whether the text in the text field below should be matched against the pattern or
2 | be considered a URL to a build whose log should be matched against the pattern.
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/help-causes.html:
--------------------------------------------------------------------------------
1 | The Cause is the description you see when an issue is found.
2 | The cause has one or more indications, if one of those indications are found in the build
3 | then the cause will be shown on the build page.
4 |
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/BackwardsCompatibilityTest/testLoadVersion1ConfigXml.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/build-failure-analyzer-plugin/HEAD/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/BackwardsCompatibilityTest/testLoadVersion1ConfigXml.zip
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/BackwardsCompatibilityTest/testReadResolveFromVersion1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/build-failure-analyzer-plugin/HEAD/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/BackwardsCompatibilityTest/testReadResolveFromVersion1.zip
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/db/MongoDBKnowledgeBase/config.properties:
--------------------------------------------------------------------------------
1 | MongoDBKnowledgeBase_UserNameDesc=User name for the database, leave blank if no authentication used
2 | MongoDBKnowledgeBase_PasswordDesc=Password for the database, leave blank if no authentication used
3 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/indication/MultilineBuildLogIndication/help-textSource.html:
--------------------------------------------------------------------------------
1 | A value indicating whether the text in the text field below should be matched against the pattern or
2 | be considered a URL to a build whose log should be matched against the pattern.
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/BackwardsCompatibilityTest/testLoadOldFailureCauseWithOnlyLineNumbers.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/build-failure-analyzer-plugin/HEAD/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/BackwardsCompatibilityTest/testLoadOldFailureCauseWithOnlyLineNumbers.zip
--------------------------------------------------------------------------------
/src/main/webapp/help/help-doNotAnalyzeAbortedJobs.html:
--------------------------------------------------------------------------------
1 |
2 | "Do not analyze aborted jobs" option forces BFA plugin to ignore all aborted jobs. It doesn't check reason why job was aborted.
3 | So, if you want to scan jobs aborted due timeout, you need to specify "Fail the build" in "Time-out actions" in job config.
4 |
3 | Jenkins Build Failure Analyzer.
4 | This plugin scans build logs and other files in the workspace for recognised patterns
5 | of known causes to build failures, and displays them on the build page for quicker
6 | recognition of why the build failed.
7 |
2 | "Squash failure metrics to unique categories for each build" option can be useful when a single failed build should
3 | count towards each cause category exactly once. This is particularly useful when combined with the "Treat failed
4 | test cases as failure causes." If numerous tests fail, "squash failure metrics" will prevent those categories
5 | from being incremented for every single failed test, which can skew metrics significantly.
6 |
The regular expression should match the entire line, so if you are looking for FATAL first in the line
5 | but don't know what comes after it, your expression should be ^FATAL.*
6 |
Substitutions may be made within the description with placeholders of the form ${I,G}, where
7 | I is the indication number and G is the captured group within the indication
8 | expression. e.g., ${1,1} would be replaced with the first indication's first captured group
9 | and ${1,2} would be replaced with the first indication's second captured group.
Note that you should not specify ".*" within your multi-line pattern unless you actually want to match every
5 | character. ".*FOO.*" will match the entire build log, assuming it contains "FOO" somewhere.
6 |
Substitutions may be made within the description with placeholders of the form ${I,G}, where
7 | I is the indication number and G is the captured group within the indication
8 | expression. e.g., ${1,1} would be replaced with the first indication's first captured group
9 | and ${1,2} would be replaced with the first indication's second captured group.
10 |
11 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/tokens/Token/help.groovy:
--------------------------------------------------------------------------------
1 | dt("\${BUILD_FAILURE_ANALYZER}")
2 | dd() {
3 | span("Displays found causes by the Build Failure Analyzer.")
4 | dl() {
5 | dt("includeIndications")
6 | dd("When true, the indication numbers and links into the console log are included in the token replacement text.")
7 |
8 | dt("useHtmlFormat")
9 | dd("When true, the replacement text will be an HTML snippet.")
10 |
11 | dt("includeTitle")
12 | dd("When true, the title will appear in the token replacement text.")
13 |
14 | dt("wrapWidth")
15 | dd("Wrap long lines at this width. If wrapWidth is 0, the text isn't wrapped. Only applies if useHtmlFormat == false.")
16 |
17 | dt("noFailureText")
18 | dd("Text to return when no failure cause is present.")
19 |
20 | dt("escapeHtml")
21 | dd("If true, any HTML specific code will be escaped. Only applies if useHtmlFormat == false. Defaults to false.")
22 | }
23 | }
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-mongo.yml:
--------------------------------------------------------------------------------
1 | unclassified:
2 | buildFailureAnalyzer:
3 | doNotAnalyzeAbortedJob: true
4 | gerritTriggerEnabled: true
5 | globalEnabled: true
6 | graphsEnabled: false
7 | knowledgeBase:
8 | mongoDB:
9 | dbName: "bfa"
10 | enableStatistics: true
11 | host: "localhost"
12 | userName: bfa
13 | password: changeme
14 | port: 27017
15 | successfulLogging: false
16 | maxLogSize: 10
17 | metricSquashingEnabled: false
18 | noCausesEnabled: true
19 | noCausesMessage: "No problems were identified. Please contribute causes to help others"
20 | nrOfScanThreads: 6
21 | slackNotifEnabled: false
22 | sodVariables:
23 | maximumSodWorkerThreads: 7
24 | minimumSodWorkerThreads: 2
25 | sodCorePoolNumberOfThreads: 6
26 | sodThreadKeepAliveTime: 17
27 | sodWaitForJobShutdownTimeout: 32
28 | testResultCategories: "hgjghhlllllaa"
29 | testResultParsingEnabled: true
30 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/PluginImpl/config.properties:
--------------------------------------------------------------------------------
1 | enableGerritTriggerDescription=This option allows BFA to forward the description of the found causes to the Gerrit-Trigger-plugin, ultimately allowing users to see their build issues directly inside Gerrit.
2 | nrOfScanThreadsDescription=Number of threads per build to use when scanning the failed builds.
3 | testResultParsingEnabledDescription=Treat failed test cases (as indicated by JUnit/xUnit/... publishers) as failure causes.
4 | testResultCategoriesDescription=A space-separated list of categories to use for failure causes representing failed test cases.
5 | maxLogSize=Log file with size that exceeds limit (in MB) would not be scanned, 0 - disables this check
6 | fallbackCategoriesDescription=Space separated list of category names that marks fallback causes. Fallback causes will only be applied if there are no non-fallback causes found.
7 | metricSquashingEnabledDescription=Prevents a single failed build from counting categories multiple times if multiple failures causes are identified with the same categories.
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright 2012 Sony Ericsson Mobile Communications. All rights reserved.
4 | Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/Messages.properties:
--------------------------------------------------------------------------------
1 | #I18n messages.
2 | PermissionGroup_Title=Build Failure Analyzer
3 | PermissionView_Description=View Failure causes.
4 | PermissionUpdate_Description=Add and Update Failure causes.
5 | PermissionRemove_Description=Remove Failure causes.
6 | BuildLogIndication_DisplayName=Build Log Indication
7 | MultilineBuildLogIndication_DisplayName=Multi-Line Build Log Indication
8 | CauseManagement_DisplayName=Failure Cause Management
9 | ScanLogAction_DisplayName=Failure Scan Log
10 | CauseList_DisplayName=Failure Causes
11 | ScannerJobProperty_DisplayName=Do not Scan failed builds
12 | LocalFileKnowledgeBase_DisplayName=Jenkins Local
13 | MongoDBKnowledgeBase_DisplayName=Mongo DB
14 | MongoDBKnowledgeBase_ConnectionError=Could not connect
15 | MongoDBKnowledgeBase_ConnectionOK=Connection OK!
16 | StringMatchesPattern=String matches pattern
17 | StringDoesNotMatchPattern=String does not match pattern
18 | InvalidPattern_Error=Invalid pattern
19 | InvalidURL_Error=Invalid URL
20 | FailedToScanFile_Error=Failed to scan file
21 | FailureScan_DisplayName=Failure Scan Options
22 | SodAccessDeniedException={0} is missing the {1} or {2} permission
23 | ScanOnDemandBaseAction_NonScanned_DisplayName=Only non-scanned builds
24 | ScanOnDemandBaseAction_AllBuilds_DisplayName=All builds
25 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/test/utils/MatrixSupport.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa.test.utils;
2 |
3 | import hudson.matrix.MatrixProject;
4 | import org.jvnet.hudson.test.JenkinsRule;
5 |
6 | import java.io.IOException;
7 |
8 | /**
9 | * Jenkins Rule with extra methods for {@link MatrixProject}s.
10 | */
11 | public final class MatrixSupport {
12 |
13 | private MatrixSupport() {
14 | // hidden
15 | }
16 |
17 | /**
18 | * Create matrix project.
19 | *
20 | * @param jenkins
21 | *
22 | * @return Project
23 | *
24 | * @throws IOException Failed to save the project
25 | */
26 | public static MatrixProject createMatrixProject(JenkinsRule jenkins) throws IOException {
27 | return jenkins.createProject(MatrixProject.class, "test" + jenkins.jenkins.getItems().size());
28 | }
29 |
30 | /**
31 | * Create matrix project.
32 | *
33 | * @param jenkins
34 | * @param name Project name
35 | *
36 | * @return Project
37 | *
38 | * @throws IOException Failed to save the project
39 | */
40 | public static MatrixProject createMatrixProject(JenkinsRule jenkins, String name) throws IOException {
41 | return jenkins.createProject(MatrixProject.class, name);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/sod/ScanOnDemandVariables/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
9 |
10 |
11 |
13 |
14 |
15 |
17 |
18 |
19 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/webapp/help/sod/nonscanned.html:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 | Scan only builds that have not already been scanned.
27 |
26 | Scan all the builds including already scanned and non-scanned builds.
27 |
--------------------------------------------------------------------------------
/docs/metrics.md:
--------------------------------------------------------------------------------
1 | # Metrics Integration
2 |
3 | This is a guide for the integration with the [Metrics plugin](https://plugins.jenkins.io/metrics/).
4 |
5 | ## Metrics
6 |
7 | The integration provides counters for each individual cause and category that you create. These counters will reset to zero when jenkins is restarted. The format for the metrics created is `jenkins_bfa_category_` for each category and `jenkins_bfa_cause_` for each cause. The category and cause names will be escaped by the metrics api to replace any spaces with underscores.
8 |
9 | ## Exporting
10 |
11 | To export the BFA metrics you can use any plugin that integrates with the Metrics plugin.
12 |
13 | ### Prometheus
14 | The [prometheus plugin](https://plugins.jenkins.io/prometheus/)
15 | To restructure the metrics into the form that prometheus expects you can add the following into your scrape config:
16 |
17 | ```yaml
18 | metric_relabel_configs:
19 | - source_labels: [__name__]
20 | regex: 'jenkins_bfa_category_(.*)'
21 | target_label: 'category'
22 | - source_labels: [__name__]
23 | regex: 'jenkins_bfa_cause_(.*)'
24 | target_label: 'cause'
25 | - source_labels: [__name__]
26 | regex: 'jenkins_bfa_(.*)_(.*)'
27 | replacement: 'jenkins_bfa'
28 | target_label: __name__
29 | ```
30 |
31 | This will provide a metric called `jenkins_bfa` with labels for the category and specific cause.
32 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/db/LocalFileKnowledgeBase/config.jelly:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseColumn/columnHeader.jelly:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseColumn/config.jelly:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/sod/ScanOnDemandBaseAction/index.jelly:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseProjectAction/jobMain.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2014 Red Hat, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseProjectAction;
26 |
27 | st = namespace("jelly:stapler");
28 |
29 | action = it.action;
30 | if (action != null) {
31 | table(style: "margin-left: 1em;") {
32 | st.include(it: action, page: "summary")
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseColumnTest/build-failure-analyzer.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | No problems were identified. If you know why this problem occurred, please add a suitable Cause for it.
4 |
5 |
6 |
7 | fa3ad321-4f70-46da-af45-1304dca50146
8 |
9 | fa3ad321-4f70-46da-af45-1304dca50146
10 | Failure Builder
11 | Simulating a failure
12 |
13 |
14 | .*Simulating a specific result code.*FAILURE.*
15 |
16 |
17 |
18 |
19 |
20 |
21 | 3
22 |
23 | 1
24 | 1
25 | 15
26 | 30
27 | 5
28 |
29 |
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/test/utils/DifferentKnowledgeBase/config.jelly:
--------------------------------------------------------------------------------
1 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/ScannerJobProperty/config.jelly:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 | The Build Failure Analyzer will not scan builds of this project.
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseMatrixBuildAction/badge.jelly:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/IndicationAnnotatorTest.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa;
2 |
3 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
4 | import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
5 | import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
6 | import hudson.MarkupText;
7 | import org.junit.jupiter.api.Test;
8 | import org.jvnet.hudson.test.Issue;
9 | import java.util.ArrayList;
10 |
11 | import static org.junit.jupiter.api.Assertions.assertTrue;
12 | import java.util.List;
13 |
14 | /**
15 | * Tests for the IndicationAnnotator.
16 | *
17 | * @author Tomas Westling <tomas.westling@axis.com>
18 | */
19 | class IndicationAnnotatorTest {
20 |
21 | private static final String EXPECTED_ANNOTATED_TEXT = "tilt" onmouseover=alert(1) foo="bar";
22 |
23 | /**
24 | * Tests that html is escaped correctly when annotating text.
25 | */
26 | @Issue("SECURITY-3244")
27 | @Test
28 | void testAnnotate() {
29 | MarkupText text = new MarkupText("matchingString");
30 | FoundIndication fi = new FoundIndication(
31 | "pattern", "matchingFile", "matchingString");
32 | List fis = new ArrayList<>();
33 | fis.add(fi);
34 | FoundFailureCause ffc = new FoundFailureCause(
35 | new FailureCause("tilt\" onmouseover=alert(1) foo=\"bar", "description"), fis);
36 | List foundFailureCauses = new ArrayList<>();
37 | foundFailureCauses.add(ffc);
38 | IndicationAnnotator ia = new IndicationAnnotator(foundFailureCauses);
39 | ia.annotate(null, text);
40 | assertTrue(text.toString(false).contains(EXPECTED_ANNOTATED_TEXT));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseBuildAction/badge.jelly:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseColumn/column.jelly:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
37 |
38 |
--------------------------------------------------------------------------------
/.github/workflows/cd.yaml:
--------------------------------------------------------------------------------
1 | # Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins
2 | #
3 | # Please find additional hints for individual trigger use case
4 | # configuration options inline this script below.
5 | #
6 | ---
7 | name: cd
8 | on:
9 | workflow_dispatch:
10 | inputs:
11 | validate_only:
12 | required: false
13 | type: boolean
14 | description: |
15 | Run validation with release drafter only
16 | → Skip the release job
17 | # Note: Change this default to true,
18 | # if the checkbox should be checked by default.
19 | default: false
20 | # If you don't want any automatic trigger in general, then
21 | # the following check_run trigger lines should all be commented.
22 | # Note: Consider the use case #2 config for 'validate_only' below
23 | # as an alternative option!
24 | check_run:
25 | types:
26 | - completed
27 |
28 | permissions:
29 | checks: read
30 | contents: write
31 |
32 | jobs:
33 | maven-cd:
34 | uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1
35 | with:
36 | # Comment / uncomment the validate_only config appropriate to your preference:
37 | #
38 | # Use case #1 (automatic release):
39 | # - Let any successful Jenkins build trigger another release,
40 | # if there are merged pull requests of interest
41 | # - Perform a validation only run with drafting a release note,
42 | # if manually triggered AND inputs.validate_only has been checked.
43 | #
44 | validate_only: ${{ inputs.validate_only == true }}
45 | #
46 | # Alternative use case #2 (no automatic release):
47 | # - Same as use case #1 - but:
48 | # - Let any check_run trigger a validate_only run.
49 | # => enforce the release job to be skipped.
50 | #
51 | #validate_only: ${{ inputs.validate_only == true || github.event_name == 'check_run' }}
52 | secrets:
53 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
54 | MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }}
55 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/tokens/TokenUtilsTest.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa.tokens;
2 | import org.junit.jupiter.api.Test;
3 | import java.util.List;
4 |
5 | import static org.junit.jupiter.api.Assertions.assertEquals;
6 |
7 | /**
8 | * Tests that the plugin can wrap token macro output.
9 | */
10 | class TokenUtilsTest {
11 | private static final String TEST_TEXT = """
12 | Lorem ipsum dolor sit amet,
13 | consectetur adipiscing elit. Nulla euismod sapien ligula,
14 |
15 | ac euismod quam aliquet vel.
16 | Duis quam augue, tristique in mi ac, scelerisque
17 | euismod nibh.
18 |
19 | Nulla accumsan velit nec neque sollicitudin,
20 | eget sagittis purus vestibulum. Nunc cursus ornare sapien
21 | sit amet hendrerit. Proin non nisi sapien.""";
22 |
23 | /**
24 | * Test that wrap() with no additional wrapping works appropriately.
25 | *
26 | */
27 | @Test
28 | void testNoAdditionalWrap() {
29 | final int noWrapping = 0;
30 | final List unwrappedLines = TokenUtils.wrap(TEST_TEXT, noWrapping);
31 | System.out.println("Unwrapped lines:");
32 | for (final String line : unwrappedLines) {
33 | System.out.println(line);
34 | }
35 | final int expectedNoWrappingLineCount = 10;
36 | assertEquals(expectedNoWrappingLineCount, unwrappedLines.size());
37 | }
38 |
39 | /**
40 | * Test that wrap() works appropriately.
41 | *
42 | */
43 | @Test
44 | void testWrap() {
45 | final int wrapAt35 = 35;
46 | final List wrappedAt35 = TokenUtils.wrap(TEST_TEXT, wrapAt35);
47 | System.out.println("Wrapped at 35:");
48 | for (final String line : wrappedAt35) {
49 | System.out.println(line);
50 | }
51 | final int expectedWrapAt35LineCount = 15;
52 | assertEquals(expectedWrapAt35LineCount, wrappedAt35.size());
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/test/utils/PrintToLogBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Ericsson Mobile Communications. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.test.utils;
26 |
27 | import hudson.Launcher;
28 | import hudson.model.AbstractBuild;
29 | import hudson.model.BuildListener;
30 | import hudson.tasks.Builder;
31 |
32 | /**
33 | * A builder that writes something in the build log.
34 | *
35 | * @author Robert Sandell, Tomas Westling
36 | */
37 | public class PrintToLogBuilder extends Builder {
38 | private final String toPrint;
39 |
40 | /**
41 | * Standard Constructor.
42 | *
43 | * @param toPrint the thing to print.
44 | */
45 | public PrintToLogBuilder(String toPrint) {
46 | this.toPrint = toPrint;
47 | }
48 |
49 | @Override
50 | public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {
51 | listener.getLogger().println(toPrint);
52 | return true;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/TransientActionProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Ericsson Mobile Communications. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa;
26 |
27 | import hudson.Extension;
28 | import hudson.model.Action;
29 | import hudson.model.Job;
30 | import jenkins.model.TransientActionFactory;
31 |
32 | import java.util.Collection;
33 | import java.util.Collections;
34 |
35 | /**
36 | * @author Robert Sandell <robert.sandell@sonyericsson.com>
37 | */
38 | @Extension
39 | public class TransientActionProvider extends TransientActionFactory {
40 |
41 |
42 | @Override
43 | public Class type() {
44 | return Job.class;
45 | }
46 |
47 | @Override
48 | public Collection extends Action> createFor(Job target) {
49 | if (PluginImpl.shouldScan(target)) {
50 | return Collections.singleton(new TransientCauseManagement(target));
51 | } else {
52 | return Collections.emptyList();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/TransientCauseManagement.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Ericsson Mobile Communications. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa;
26 |
27 | import hudson.model.Item;
28 | import hudson.model.ModelObject;
29 |
30 | /**
31 | * A {@link CauseManagement} page that appears on all Project pages via {@link TransientActionProvider}.
32 | *
33 | * @author Robert Sandell <robert.sandell@sonyericsson.com>
34 | */
35 | public class TransientCauseManagement extends CauseManagement {
36 |
37 | private Item owner;
38 |
39 | /**
40 | * Standard constructor.
41 | *
42 | * @param owner the "owner" of this action. Used to render the side panel.
43 | */
44 | public TransientCauseManagement(Item owner) {
45 | this.owner = owner;
46 | }
47 |
48 | @Override
49 | public ModelObject getOwner() {
50 | return owner;
51 | }
52 |
53 | @Override
54 | protected String getOwnerUrl() {
55 | return "/" + owner.getUrl();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/sod/ScanOnDemandTransientActionProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.sod;
25 |
26 | import com.sonyericsson.jenkins.plugins.bfa.PluginImpl;
27 | import hudson.Extension;
28 | import hudson.model.Action;
29 | import hudson.model.Job;
30 |
31 | import java.util.Arrays;
32 | import java.util.Collection;
33 | import java.util.Collections;
34 |
35 | import jenkins.model.TransientActionFactory;
36 |
37 | /**
38 | * Extension point for inserting SOD Transient Actions
39 | * into the Abstract project.
40 | *
41 | * @author Shemeer Sulaiman <shemeer.x.sulaiman@sonymobile.com>
42 | */
43 | @Extension
44 | public class ScanOnDemandTransientActionProvider extends TransientActionFactory {
45 |
46 | @Override
47 | public Class type() {
48 | return Job.class;
49 | }
50 |
51 | @Override
52 | public Collection extends Action> createFor(Job target) {
53 | if (PluginImpl.shouldScan(target)) {
54 | final ScanOnDemandBaseAction sodBaseAction = new ScanOnDemandBaseAction(target);
55 | if (sodBaseAction.hasPermission()) {
56 | return Arrays.asList(sodBaseAction);
57 | }
58 | }
59 | return Collections.emptyList();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseProjectAction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2014 Red Hat, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.model;
25 |
26 | import edu.umd.cs.findbugs.annotations.NonNull;
27 | import hudson.model.InvisibleAction;
28 |
29 | import hudson.model.Job;
30 | import hudson.model.Run;
31 | import org.kohsuke.accmod.Restricted;
32 | import org.kohsuke.accmod.restrictions.NoExternalUse;
33 |
34 | /**
35 | * Project action showing failure cause of last build, if any.
36 | *
37 | * @author ogondza
38 | */
39 | @Restricted(NoExternalUse.class)
40 | public class FailureCauseProjectAction extends InvisibleAction {
41 |
42 | private final Job, ?> job;
43 |
44 | /**
45 | * @param job A project to report.
46 | */
47 | public FailureCauseProjectAction(@NonNull Job, ?> job) {
48 | this.job = job;
49 | }
50 |
51 | /**
52 | * @return Build action to report.
53 | */
54 | public FailureCauseBuildAction getAction() {
55 | Run, ?> build = job.getLastCompletedBuild();
56 | if (build == null) {
57 | return null;
58 | }
59 |
60 | FailureCauseBuildAction action = build.getAction(FailureCauseBuildAction.class);
61 | if (action == null) {
62 | return null;
63 | }
64 |
65 | return action;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/utils/BfaUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2013 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.utils;
26 |
27 | import java.io.IOException;
28 | import java.net.URL;
29 | import java.util.logging.Level;
30 | import java.util.logging.Logger;
31 |
32 | import jenkins.model.Jenkins;
33 |
34 | /**
35 | * Utility class.
36 | *
37 | * @author Fredrik Persson <fredrik6.persson@sonymobile.com>
38 | *
39 | */
40 | public final class BfaUtils {
41 |
42 | private static final Logger logger = Logger.getLogger(BfaUtils.class.getName());
43 |
44 | /**
45 | * Utility classes should not have a public or default constructor.
46 | */
47 | private BfaUtils() {
48 | }
49 |
50 | /**
51 | * Gets the Jenkins master name.
52 | * @return the master name
53 | */
54 | public static String getMasterName() {
55 | String masterString = Jenkins.getInstance().getRootUrl();
56 | String name = null;
57 |
58 | if (masterString == null) {
59 | logger.log(Level.WARNING, "Couldn't get name of master: Jenkins root url is null");
60 | } else {
61 | try {
62 | name = new URL(masterString).getHost();
63 | } catch (IOException e) {
64 | logger.log(Level.WARNING, "Couldn't get name of master: ", e);
65 | }
66 | }
67 | return name;
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/db/Semaphore.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.db;
25 |
26 | /**
27 | * "Real" binary semaphore, where subsequent calls to release do not
28 | * make the semaphore be able to acquire more than the maximum permits.
29 | * @author Tomas Westling <tomas.westling@sonyericsson.com>
30 | */
31 | public class Semaphore {
32 |
33 | private java.util.concurrent.Semaphore semaphoreLock;
34 |
35 | /**
36 | * Standard constructor.
37 | */
38 | public Semaphore() {
39 | semaphoreLock = new java.util.concurrent.Semaphore(0);
40 | }
41 |
42 | /**
43 | * @see java.util.concurrent.Semaphore#acquire()
44 | * The difference is that this tries to acquire all available permits if there are any and 1 if there are none.
45 | * @throws InterruptedException if the java.util.concurrent.Semaphore is interrupted.
46 | */
47 | public void acquire() throws InterruptedException {
48 | int take;
49 | if (semaphoreLock.availablePermits() < 1) {
50 | take = 1;
51 | } else {
52 | take = semaphoreLock.availablePermits();
53 | }
54 | semaphoreLock.acquire(take);
55 | }
56 |
57 | /**
58 | * @see java.util.concurrent.Semaphore#release()
59 | * Releases a permit, returning it to the semaphore.
60 | */
61 | public void release() {
62 | semaphoreLock.release();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndication/config.jelly:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
45 |
46 |
47 |
48 |
49 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/indication/MultilineBuildLogIndication/config.jelly:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
45 |
46 |
47 |
48 |
49 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/db/MongoDBKnowledgeBase/config.jelly:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/db/SemaphoreTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.db;
25 |
26 | import com.sonyericsson.jenkins.plugins.bfa.test.utils.Whitebox;
27 |
28 | import java.util.concurrent.TimeUnit;
29 | import org.junit.jupiter.api.Test;
30 | import org.junit.jupiter.api.Timeout;
31 |
32 | import static org.junit.jupiter.api.Assertions.assertEquals;
33 |
34 | //CS IGNORE MagicNumber FOR NEXT 100 LINES. REASON: TestData.
35 |
36 | /**
37 | * Tests for the Semaphore.
38 | * @author Tomas Westling <tomas.westling@sonyericsson.com>
39 | */
40 | class SemaphoreTest {
41 |
42 | /**
43 | * Tests that acquire and release works in the the correct way for the Semaphore.
44 | * @throws Exception if so.
45 | */
46 | @Test
47 | @Timeout(value = 20000, unit = TimeUnit.MILLISECONDS)
48 | void testAcquireAndRelease() throws Exception {
49 | Semaphore semaphore = new Semaphore();
50 | java.util.concurrent.Semaphore innerSemaphore = Whitebox.getInternalState(semaphore, "semaphoreLock");
51 | assertEquals(0,
52 | innerSemaphore.availablePermits(),
53 | "The semaphore should have no available permits to start with");
54 | semaphore.release();
55 | semaphore.release();
56 | assertEquals(2, innerSemaphore.availablePermits(), "The semaphore should have 2 available permits");
57 | semaphore.acquire();
58 | assertEquals(0, innerSemaphore.availablePermits(), "All of the semaphore's permits should be taken");
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/ScannerOffJobProperty.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.model;
26 |
27 | import hudson.model.AbstractProject;
28 | import hudson.model.JobProperty;
29 |
30 | import java.io.Serializable;
31 |
32 | /**
33 | * A JobProperty that flags a job that should not be scanned.
34 | *
35 | * @author Robert Sandell <robert.sandell@sonyericsson.com>
36 | * @deprecated {@link ScannerJobProperty} is used instead, but this is kept to be able to de-serialize old jobs.
37 | */
38 | @Deprecated
39 | public class ScannerOffJobProperty extends JobProperty> implements Serializable {
40 | private boolean doNotScan;
41 |
42 | /**
43 | * Standard Constructor.
44 | *
45 | * @param doNotScan signal that builds of this job should not be scanned.
46 | */
47 | public ScannerOffJobProperty(boolean doNotScan) {
48 | this.doNotScan = doNotScan;
49 | }
50 |
51 | /**
52 | * Default Constructor. Do not use unless you are a serializer!
53 | */
54 | public ScannerOffJobProperty() {
55 | }
56 |
57 | /**
58 | * The value. True turns the scanner off.
59 | *
60 | * @return if no scan should be done.
61 | */
62 | public boolean isDoNotScan() {
63 | return doNotScan;
64 | }
65 |
66 | /**
67 | * De-serialize this object to a {@link ScannerJobProperty}.
68 | *
69 | * @return an instance of {@link ScannerJobProperty} with the same data.
70 | */
71 | public Object readResolve() {
72 | return new ScannerJobProperty(doNotScan);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/docs/azure.md:
--------------------------------------------------------------------------------
1 | # Azure Cosmos DB
2 |
3 | This is a guide for setting up the MongoDB storage with the Azure cloud provider,
4 |
5 | ## Prerequisites
6 |
7 | * a mongodb client, e.g. the mongo shell from the [mongo installation guide](https://docs.mongodb.com/manual/installation/)
8 |
9 | ## Getting started
10 |
11 | 1. create the Azure Cosmos DB instance, [follow the Microsoft quickstart](https://docs.microsoft.com/en-us/azure/cosmos-db/create-mongodb-java) for this.
12 | * you can skip the 'create a collection' step and just create a database for now,
13 | the plugin will automatically create the collections for you
14 |
15 | 2. go to the 'Connection string' page on your Cosmos DB resource
16 |
17 |
18 | ## Configuring the plugin via UI
19 |
20 | In a separate tab you can now configure the plugin in Jenkins,
21 |
22 | * go to https://.mongo.cosmos.azure.com"
51 | password: "your password" # see docs for handling secrets https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/docs/features/secrets.adoc
52 | port: 10255
53 | successfulLogging: false
54 | tls: true
55 | userName: ""
56 | ```
57 |
58 | ## Adding required index
59 |
60 | Azure Cosmos DB requires an index when an order by query is performed, in order for this plugin to work you need to run the following commands:
61 |
62 | the example uses the mongo shell, but you can use any mongo client (except the one in the Azure portal which doesn't work for this)
63 |
64 | ```bash
65 | mongo ' # this should be the db name you chose earlier, e.g. bfa
68 | db.failureCauses.createIndex({ "name": 1 })
69 | ```
70 |
71 | ## Configure a failure cause
72 |
73 | * go to your jenkins home page
74 | * click 'Failure Cause Management'
75 | * fill out the fields
76 | * click save
77 |
78 | Go to the 'Data explorer' Azure, and click '' and then 'failureCauses'.
79 |
80 | You should now see the failure cause you just created.
81 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseModification.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2014 Sony Mobile Communications Inc. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.model;
25 |
26 | import com.fasterxml.jackson.annotation.JsonCreator;
27 | import com.fasterxml.jackson.annotation.JsonProperty;
28 |
29 | import java.io.Serializable;
30 | import java.util.Date;
31 |
32 | /**
33 | * A historical record of a modification occurrence by a user.
34 | *
35 | * @author Felix Hall <felix.hall@sonymobile.com>
36 | */
37 | public class FailureCauseModification implements Serializable {
38 | private String user;
39 | private Date time;
40 |
41 | /**
42 | * Constructor for FailureCauseModification.
43 | *
44 | * @param user The user who made the modification.
45 | * @param time The time at which the modification was done.
46 | */
47 | @JsonCreator
48 | public FailureCauseModification(@JsonProperty("user") String user, @JsonProperty("time") Date time) {
49 | this.user = user;
50 | if (time == null) {
51 | this.time = null;
52 | } else {
53 | this.time = (Date)time.clone();
54 | }
55 | }
56 |
57 | /**
58 | * Getter for the time.
59 | *
60 | * @return The time at which the modification was done.
61 | */
62 | public Date getTime() {
63 | if (time == null) {
64 | return null;
65 | } else {
66 | return (Date)time.clone();
67 | }
68 | }
69 |
70 | /**
71 | * Getter for the user.
72 | *
73 | * @return The user who made the modification.
74 | */
75 | public String getUser() {
76 | return user;
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/dbf/CoreDBF.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2013 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.model.dbf;
26 |
27 | import hudson.Extension;
28 | import hudson.model.AbstractBuild;
29 | import hudson.model.Fingerprint;
30 | import hudson.model.Job;
31 | import hudson.model.Run;
32 |
33 | import java.util.LinkedList;
34 | import java.util.List;
35 | import java.util.Map;
36 |
37 | /**
38 | * Basic implementation to get downstream builds from Jenkins using core
39 | * functionality.
40 | *
41 | * @author Jan-Olof Sivtoft
42 | */
43 | @Extension
44 | public class CoreDBF extends DownstreamBuildFinder {
45 |
46 | /**
47 | * Return a list of all downstream builds originating from provided build.
48 | * Using core functionality to retrieve build(s).
49 | *
50 | * @param build get the downstream build(s) relative this build
51 | * @return alist with downstream builds
52 | */
53 | @Override
54 | public List> getDownstreamBuilds(
55 | final Run build) {
56 |
57 | Map buildMap = null;
58 | if (build instanceof AbstractBuild) {
59 | buildMap = ((AbstractBuild)build).getDownstreamBuilds();
60 | }
61 | LinkedList> foundBuilds =
62 | new LinkedList>();
63 |
64 |
65 | if (buildMap != null && !buildMap.isEmpty()) {
66 | for (Map.Entry entry
67 | : buildMap.entrySet()) {
68 | for (Integer buildId : entry.getValue().listNumbers()) {
69 | foundBuilds.add((Run, ?>)
70 | entry.getKey().getBuildByNumber(buildId));
71 | }
72 | }
73 | }
74 |
75 | return foundBuilds;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/MetricsManager.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa;
2 |
3 | import com.codahale.metrics.MetricRegistry;
4 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
5 | import com.sonyericsson.jenkins.plugins.bfa.model.IFailureCauseMetricData;
6 | import jenkins.metrics.api.Metrics;
7 |
8 | import java.util.HashSet;
9 | import java.util.List;
10 | import java.util.Set;
11 | import java.util.SortedSet;
12 |
13 | public final class MetricsManager {
14 | static final String CAUSEPREFIX = "jenkins_bfa.cause.";
15 | static final String CATEGORYPREFIX = "jenkins_bfa.category.";
16 |
17 | /**A magic cause to represent builds that match no causes in the database. */
18 | public static final FailureCause UNKNOWNCAUSE = new FailureCause("no matching cause", "");
19 |
20 | private MetricsManager() {
21 | }
22 |
23 | private static Set getMetricNames(IFailureCauseMetricData cause) {
24 | Set metrics = new HashSet();
25 | metrics.add(CAUSEPREFIX + cause.getName());
26 | List categoriesForCause = cause.getCategories();
27 | if (categoriesForCause != null) {
28 | for (String string : categoriesForCause) {
29 | metrics.add(CATEGORYPREFIX + string);
30 | }
31 | }
32 | return metrics;
33 | }
34 |
35 | /**
36 | * Add metrics into the MetricRegistry from the Metrics plugin.
37 | *
38 | * @param cause The Cause to add metrics for
39 | */
40 | public static void addMetric(IFailureCauseMetricData cause) {
41 | MetricRegistry metricRegistry = Metrics.metricRegistry();
42 | SortedSet existingMetrics = metricRegistry.getNames();
43 | Set metrics = getMetricNames(cause);
44 | for (String metric : metrics) {
45 | if (!existingMetrics.contains(metric)) {
46 | metricRegistry.counter(metric);
47 | }
48 | }
49 | }
50 |
51 | /**
52 | * Increment counters for the metric and its categories.
53 | * @param causes The cause to increment counters for
54 | * @param squashCauses Whether or not to squash cause metrics
55 | */
56 | public static void incCounters(List extends IFailureCauseMetricData> causes, boolean squashCauses) {
57 | MetricRegistry metricRegistry = Metrics.metricRegistry();
58 | if (squashCauses) {
59 | Set metrics = new HashSet<>();
60 | for (IFailureCauseMetricData cause : causes) {
61 | metrics.addAll(getMetricNames(cause));
62 | }
63 | for (String metric : metrics) {
64 | metricRegistry.counter(metric).inc();
65 | }
66 | } else {
67 | for (IFailureCauseMetricData cause : causes) {
68 | Set metrics = getMetricNames(cause);
69 | for (String metric : metrics) {
70 | metricRegistry.counter(metric).inc();
71 | }
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/IndicationAnnotatorFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa;
25 |
26 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
27 | import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
28 | import hudson.Extension;
29 | import hudson.console.ConsoleAnnotator;
30 | import hudson.console.ConsoleAnnotatorFactory;
31 | import hudson.model.Run;
32 | import org.kohsuke.stapler.Ancestor;
33 | import org.kohsuke.stapler.Stapler;
34 | import org.kohsuke.stapler.StaplerRequest2;
35 |
36 | import java.util.List;
37 |
38 | /**
39 | * Factory for creating a new {@link IndicationAnnotator} when the log should be annotated.
40 | *
41 | * @author Tomas Westling <tomas.westling@sonymobile.com>
42 | */
43 | @Extension
44 | public class IndicationAnnotatorFactory extends ConsoleAnnotatorFactory {
45 |
46 | @Override
47 | public ConsoleAnnotator newInstance(Object context) {
48 | StaplerRequest2 currentRequest = Stapler.getCurrentRequest2();
49 | if (currentRequest == null) {
50 | //Accessed through some other means than http, so lets assume it is not a human.
51 | return null;
52 | }
53 | Ancestor ancestor = currentRequest.findAncestor(Run.class);
54 | if (ancestor == null) {
55 | return null;
56 | }
57 | Object object = ancestor.getObject();
58 | Run build = (Run)object;
59 | FailureCauseBuildAction action = build.getAction(FailureCauseBuildAction.class);
60 | if (action == null) {
61 | return null;
62 | }
63 | List foundFailureCauses = action.getFoundFailureCauses();
64 | if (foundFailureCauses.isEmpty()) {
65 | return null;
66 | }
67 | return new IndicationAnnotator(foundFailureCauses);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/remove.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.CauseManagement;
25 |
26 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
27 | import com.sonyericsson.jenkins.plugins.bfa.CauseManagement;
28 | import com.sonyericsson.jenkins.plugins.bfa.PluginImpl;
29 | import hudson.Functions
30 |
31 | def f = namespace(lib.FormTagLib)
32 | def l = namespace(lib.LayoutTagLib)
33 | def j = namespace(lib.JenkinsTagLib)
34 | def st = namespace("jelly:stapler")
35 |
36 | l.layout(permission: PluginImpl.REMOVE_PERMISSION) {
37 | l.header(title: _("Failure Cause Management - Confirm Remove"))
38 |
39 | def management = CauseManagement.getInstance();
40 | def causeId = request2.getParameter("id");
41 | def cause = null;
42 | if (causeId != null && !causeId.isEmpty()) {
43 | cause = PluginImpl.getInstance().getKnowledgeBase().getCause(causeId);
44 | }
45 |
46 | l.side_panel() {
47 | if (!management.isUnderTest()) {
48 | include(management.getOwner(), "sidepanel.jelly")
49 | }
50 | }
51 |
52 | l.main_panel() {
53 | h1(_("Failure Cause - Confirm Remove"))
54 | div(style: "width: 70%") {
55 | st.adjunct(includes: "com.sonyericsson.jenkins.plugins.bfa.CauseManagement.resource")
56 | if (cause != null) {
57 | form(method: "POST", action: "removeConfirm") {
58 | p(_("removeQuestion", cause.getName()))
59 | input(type: "hidden", value: cause.getId(), name: "id")
60 | raw(" ");
61 | f.submit(value: _("Yes"))
62 | raw(" ");
63 | button(type: "button", class: "jenkins-button bfa-cause-management-back-button", _("Back"))
64 | }
65 | } else {
66 | p(_("Not a valid cause id"))
67 | button(class: "jenkins-button bfa-cause-management-back-button", _("Back"))
68 | }
69 |
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/utils/ObjectCountPair.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2013 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.utils;
25 |
26 | import java.util.Comparator;
27 |
28 | /**
29 | * Class for keeping track of the number of copies of the same object.
30 | * Can for example be used for keeping track of how many times
31 | * a specific FailureCause has been triggered.
32 | *
33 | * @author Fredrik Persson <fredrik6.persson@sonyericsson.com>
34 | *
35 | * @param the object type that we count
36 | */
37 | public class ObjectCountPair {
38 |
39 | private T object;
40 | private int count;
41 |
42 | /**
43 | * Standard constructor.
44 | * @param object the object we are counting
45 | * @param count the number of copies we have of the object
46 | */
47 | public ObjectCountPair(T object, int count) {
48 | this.object = object;
49 | this.count = count;
50 | }
51 |
52 | /**
53 | * Getter for the object we are counting.
54 | * @return the object we are counting
55 | */
56 | public T getObject() {
57 | return object;
58 | }
59 |
60 | /**
61 | * Getter for the counter.
62 | * @return the number of copies of the object
63 | */
64 | public int getCount() {
65 | return count;
66 | }
67 |
68 | /**
69 | * Adds argument number to the counter.
70 | * @param add integer value to add
71 | */
72 | public void addCount(int add) {
73 | count += add;
74 | }
75 |
76 | /**
77 | * Gets a comparator that compares the count.
78 | * @return comparator
79 | */
80 | public static Comparator countComparator() {
81 | return new Comparator() {
82 | @Override
83 | public int compare(ObjectCountPair o1, ObjectCountPair o2) {
84 | return o2.getCount() - o1.getCount();
85 | }
86 | };
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/tokens/TokenUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2014 Stellar Science Ltd Co
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.tokens;
25 |
26 | import com.google.common.base.Splitter;
27 | import org.apache.commons.lang.WordUtils;
28 |
29 | import java.util.ArrayList;
30 | import java.util.List;
31 | import java.util.regex.Matcher;
32 | import java.util.regex.Pattern;
33 |
34 | /**
35 | * Static helper methods for Token generation.
36 | */
37 | public final class TokenUtils {
38 |
39 | /** Utility class */
40 | private TokenUtils() { }
41 |
42 | /**
43 | * Wrap some text
44 | * @param text some text to wrap
45 | * @param width the text will be wrapped to this many characters
46 | * @return the text lines
47 | */
48 | /* package private */ static List wrap(final String text, final int width) {
49 | final List lines = new ArrayList< String>();
50 | final Splitter lineSplitter = Splitter.on(Pattern.compile("\\r?\\n"));
51 | //Split the text into lines
52 | for (final String line : lineSplitter.split(text)) {
53 | if (width > 0) {
54 | final Pattern firstNonwhitespacePattern = Pattern.compile("[^\\s]");
55 | final Matcher firstNonwhiteSpaceMatcher = firstNonwhitespacePattern.matcher(line);
56 | String indent = "";
57 | if (firstNonwhiteSpaceMatcher.find()) {
58 | indent = line.substring(0, firstNonwhiteSpaceMatcher.start());
59 | }
60 | //Wrap each line
61 | final String wrappedLines = WordUtils.wrap(line, width - indent.length());
62 | //Split the wrapped line into lines and add those lines to the result
63 | for (final String wrappedLine : lineSplitter.split(wrappedLines)) {
64 | lines.add(indent + wrappedLine.trim());
65 | }
66 | } else {
67 | lines.add(line);
68 | }
69 | }
70 | return lines;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseProjectActionHudsonTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2014 Red Hat, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.model;
25 |
26 | import hudson.Functions;
27 | import hudson.model.FreeStyleBuild;
28 | import hudson.model.FreeStyleProject;
29 | import hudson.model.Result;
30 | import hudson.tasks.BatchFile;
31 | import hudson.tasks.CommandInterpreter;
32 | import hudson.tasks.Shell;
33 |
34 | import org.junit.jupiter.api.Test;
35 | import org.jvnet.hudson.test.JenkinsRule;
36 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
37 |
38 | import static org.junit.jupiter.api.Assertions.assertEquals;
39 | import static org.junit.jupiter.api.Assertions.assertNotNull;
40 | import static org.junit.jupiter.api.Assertions.assertNull;
41 |
42 | /**
43 | * Test Failure Cause project action.
44 | */
45 | @WithJenkins
46 | class FailureCauseProjectActionHudsonTest {
47 |
48 | /**
49 | * Should show failures of last completed build.
50 | *
51 | * @param j
52 | *
53 | * @throws Exception in some cases.
54 | */
55 | @Test
56 | void testShowLastFailureOnProjectPage(JenkinsRule j) throws Exception {
57 | FreeStyleProject project = j.createFreeStyleProject();
58 | CommandInterpreter commandInterpreter;
59 | if (Functions.isWindows()) {
60 | commandInterpreter = new BatchFile("@if %BUILD_NUMBER% == 1 exit /b 1");
61 | } else {
62 | commandInterpreter = new Shell("test $BUILD_NUMBER -ne 1");
63 | }
64 | project.getBuildersList().add(commandInterpreter);
65 | FreeStyleBuild build = project.scheduleBuild2(0).get();
66 | j.assertBuildStatus(Result.FAILURE, build);
67 |
68 | FailureCauseProjectAction action = project.getAction(FailureCauseProjectAction.class);
69 | assertNotNull(action.getAction());
70 | assertEquals(build.getAction(FailureCauseBuildAction.class), action.getAction());
71 |
72 | j.buildAndAssertSuccess(project);
73 | assertNull(project.getAction(FailureCauseProjectAction.class).getAction());
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/docs/documentDB.md:
--------------------------------------------------------------------------------
1 | # AWS DocumentDB
2 |
3 | This is a guide for setting up the MongoDB storage with the AWS Document DB,
4 |
5 | ## Prerequisites
6 |
7 | * a mongodb client, e.g. the mongo shell from the [mongo installation guide](https://docs.mongodb.com/manual/installation/)
8 |
9 | ## Getting started
10 |
11 | 1. Create the DocumentDB cluster in AWS, [follow the AWS DocumentDb quickstart](https://docs.aws.amazon.com/documentdb/latest/developerguide/db-cluster-create.html) for this.
12 | * the plugin will automatically create the collections for you so no need to create a collection
13 |
14 | 2. Disable TLS on the cluster by following this step
15 | * Go to DocumentDB services and click on Parameter Groups
16 | * Click on create and create a new Parameter Groups. Provide relevant name and description
17 | * Once created, click on newly created Parameter Groups and select tls. Click on edit button on top
18 | * Choose value as disable and then click on modify cluster parameter. New cluster parameter group is saved with tls disabled
19 | * Click on Clusters and select modify in Action dropdown
20 | * Select your newly created cluster group in Cluster parameter group option and save the cluster. Reboot cluster and associated instance
21 |
22 | 3. Add inbound rule to security group of your cluster to access cluster
23 | * Create a new inbound rule with following values
24 | * Type : Custom TCP
25 | * Protocol : TCP
26 | * Port Range : 27017
27 | * Source : IP range of your network
28 |
29 | 4. Go to Amazon DocumentDB and then go to Clusters. Select the cluster which you have created. Then go to Connectivity & Security tab
30 |
31 |
32 |
33 | ## Configuring the plugin via UI
34 |
35 | In a separate tab you can now configure the plugin in Jenkins,
36 |
37 | * go to https://.us-west-2.docdb.amazonaws.com"
67 | password: "your documentdb masterpasswrd" # see docs for handling secrets https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/docs/features/secrets.adoc
68 | port: 27017
69 | successfulLogging: false
70 | tls: false
71 | userName: ""
72 | ```
73 |
74 |
75 | ## Configure a failure cause
76 |
77 | * go to your jenkins home page
78 | * click 'Failure Cause Management'
79 | * fill out the fields
80 | * click save
81 |
82 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/FailureCauseMatrixAggregator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Ericsson Mobile Communications. All rights reserved.
5 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 | package com.sonyericsson.jenkins.plugins.bfa;
26 |
27 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseMatrixBuildAction;
28 | import hudson.Launcher;
29 | import hudson.matrix.MatrixAggregator;
30 | import hudson.matrix.MatrixBuild;
31 | import hudson.matrix.MatrixRun;
32 | import hudson.model.BuildListener;
33 |
34 | import java.util.LinkedList;
35 | import java.util.List;
36 |
37 | /**
38 | * Aggregates the failure causes from downstream builds to the parent build.
39 | *
40 | * @author Tomas Westling <thomas.westling@sonyericsson.com>
41 | */
42 | public class FailureCauseMatrixAggregator extends MatrixAggregator {
43 |
44 | /**
45 | * Standard constructor.
46 | *
47 | * @param build the MatrixBuild to aggregate FailureCauses for.
48 | * @param launcher the launcher.
49 | * @param listener the listener.
50 | */
51 | public FailureCauseMatrixAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
52 | super(build, launcher, listener);
53 | }
54 |
55 | @Override
56 | public boolean endBuild() {
57 | if (PluginImpl.shouldScan(build) && PluginImpl.needToAnalyze(build.getResult())) {
58 | List runsWithCorrectNumber = getRuns(build);
59 | build.addAction(new FailureCauseMatrixBuildAction(build, runsWithCorrectNumber));
60 | }
61 | return true;
62 | }
63 |
64 | /**
65 | * Gets the runs that has the same number as the build.
66 | *
67 | * @param matrixBuild the build.
68 | * @return the list of runs.
69 | */
70 | public static List getRuns(MatrixBuild matrixBuild) {
71 | List runs = matrixBuild.getRuns();
72 | List runsWithCorrectNumber = new LinkedList();
73 | for (MatrixRun run : runs) {
74 | if (run.getNumber() == matrixBuild.getNumber()) {
75 | runsWithCorrectNumber.add(run);
76 | }
77 | }
78 | return runsWithCorrectNumber;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseColumnTest/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.0
5 | 2
6 | NORMAL
7 | true
8 |
9 |
10 |
11 | ${JENKINS_HOME}/workspace/${ITEM_FULLNAME}
12 | ${ITEM_ROOTDIR}/builds
13 |
14 |
15 |
16 |
17 |
18 | 0
19 |
20 |
21 |
22 | All
23 | false
24 | false
25 |
26 |
27 |
28 |
29 | columnwithouttext
30 | false
31 | false
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | false
43 |
44 |
45 |
46 |
47 |
48 |
49 | .*
50 |
51 |
52 |
53 | columnwithtext
54 | false
55 | false
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | true
67 |
68 |
69 |
70 |
71 |
72 |
73 | .*
74 |
75 |
76 | All
77 | 0
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/tokens/PipelineTokenTest.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa.tokens;
2 |
3 | import hudson.FilePath;
4 | import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
5 | import org.jenkinsci.plugins.workflow.job.WorkflowJob;
6 | import org.jenkinsci.plugins.workflow.job.WorkflowRun;
7 | import org.junit.jupiter.api.Test;
8 | import org.jvnet.hudson.test.JenkinsRule;
9 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
10 |
11 | import static org.junit.jupiter.api.Assertions.assertEquals;
12 |
13 | /**
14 | * Tests that the plugin is compatible with the token macro pipeline step.
15 | */
16 | @WithJenkins
17 | class PipelineTokenTest {
18 |
19 | private static final String DECLARATIVE_PIPELINE =
20 | """
21 | pipeline {
22 | agent any
23 | stages {
24 | stage("Run declarative bfa") {
25 | steps {
26 | writeFile file: 'bfa.log', text: tm('''${BUILD_FAILURE_ANALYZER, \
27 | noFailureText="No errors found - Declarative"}''')
28 | }
29 | }
30 | }
31 | }
32 | """;
33 |
34 | private static final String SCRIPTED_PIPELINE =
35 | """
36 | node {
37 | stage("Run scripted bfa") {
38 | writeFile file: 'bfa.log', text: tm('''${BUILD_FAILURE_ANALYZER, \
39 | noFailureText="No errors found - Scripted"}''')
40 | }
41 | }
42 | """;
43 |
44 | /**
45 | * Tests that the plugin is run by the tm pipeline step in a declarative pipeline by writing the result to a file.
46 | *
47 | * @param jenkinsRule
48 | *
49 | * @throws Exception If necessary
50 | */
51 | @Test
52 | void declarativePipelineTokenMacro(JenkinsRule jenkinsRule) throws Exception {
53 | WorkflowJob project = jenkinsRule.createProject(WorkflowJob.class);
54 | project.setDefinition(new CpsFlowDefinition(DECLARATIVE_PIPELINE, true));
55 |
56 | final WorkflowRun build = jenkinsRule.buildAndAssertSuccess(project);
57 | final FilePath workspace = jenkinsRule.jenkins.getWorkspaceFor(project);
58 | final FilePath bfaLog = workspace.child("bfa.log");
59 |
60 | final String bfaLogText = bfaLog.readToString();
61 |
62 | assertEquals("No errors found - Declarative", bfaLogText);
63 | }
64 |
65 | /**
66 | * Tests that the plugin is run by the tm pipeline step in a scripted pipeline by writing the result to a file.
67 | *
68 | * @param jenkinsRule
69 | *
70 | * @throws Exception If necessary
71 | */
72 | @Test
73 | void scriptedPipelineTokenMacro(JenkinsRule jenkinsRule) throws Exception {
74 | WorkflowJob project = jenkinsRule.createProject(WorkflowJob.class);
75 | project.setDefinition(new CpsFlowDefinition(SCRIPTED_PIPELINE, true));
76 |
77 | final WorkflowRun build = jenkinsRule.buildAndAssertSuccess(project);
78 | final FilePath workspace = jenkinsRule.jenkins.getWorkspaceFor(project);
79 | final FilePath bfaLog = workspace.child("bfa.log");
80 |
81 | final String bfaLogText = bfaLog.readToString();
82 |
83 | assertEquals("No errors found - Scripted", bfaLogText);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/statistics/FailureCauseStatistics.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.statistics;
26 |
27 | import com.fasterxml.jackson.annotation.JsonCreator;
28 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
29 | import com.fasterxml.jackson.annotation.JsonProperty;
30 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
31 | import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
32 | import org.mongojack.DBRef;
33 |
34 | import java.util.List;
35 |
36 | /**
37 | * The FailureCause statistics object.
38 | * Contains the id of a FailureCause and its found indications.
39 | * @author Tomas Westling <tomas.westling@sonymobile.com>
40 | */
41 | @JsonIgnoreProperties(ignoreUnknown = true)
42 | public class FailureCauseStatistics {
43 | private String id;
44 | private List foundIndications;
45 |
46 | /**
47 | * Getter for the id.
48 | * @return the id.
49 | */
50 | public String getId() {
51 | return id;
52 | }
53 |
54 | /**
55 | * Getter for the FoundIndications.
56 | * @return the FoundIndications.
57 | */
58 | public List getIndications() {
59 | return foundIndications;
60 | }
61 |
62 | /**
63 | * Standard constructor.
64 | * @param id the id of the FailureCause.
65 | * @param indications the list of indications.
66 | */
67 | public FailureCauseStatistics(String id, List indications) {
68 | this.id = id;
69 | this.foundIndications = indications;
70 | }
71 |
72 | /**
73 | * JSON constructor.
74 | *
75 | * @param failureCause database reference to the FailureCause.
76 | * @param indications the list of indications.
77 | * @throws Exception if the database reference is invalid
78 | */
79 | @JsonCreator
80 | public FailureCauseStatistics(
81 | @JsonProperty("failureCause") DBRef failureCause,
82 | @JsonProperty("indications") List indications)
83 | throws Exception {
84 | if (failureCause == null) {
85 | throw new Exception("Unable to resolve DBRef; failureCause mapping is null");
86 | }
87 | this.id = failureCause.getId().toString();
88 | this.foundIndications = indications;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/PluginImplTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Ericsson Mobile Communications. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa;
26 |
27 | import jenkins.model.Jenkins;
28 | import org.junit.jupiter.api.AfterEach;
29 | import org.junit.jupiter.api.BeforeEach;
30 | import org.junit.jupiter.api.Test;
31 | import org.mockito.MockedStatic;
32 |
33 | import static org.junit.jupiter.api.Assertions.assertEquals;
34 | import static org.junit.jupiter.api.Assertions.assertThrows;
35 | import static org.mockito.Mockito.mock;
36 | import static org.mockito.Mockito.mockStatic;
37 |
38 | /**
39 | * JUnit Tests for {@link PluginImpl}.
40 | *
41 | * @author Robert Sandell <robert.sandell@sonyericsson.com>
42 | */
43 | class PluginImplTest {
44 |
45 | private MockedStatic jenkinsMockedStatic;
46 |
47 | /**
48 | * Initial mocking.
49 | */
50 | @BeforeEach
51 | void setUp() {
52 | Jenkins jenkins = mock(Jenkins.class);
53 | jenkinsMockedStatic = mockStatic(Jenkins.class);
54 | jenkinsMockedStatic.when(Jenkins::get).thenReturn(jenkins);
55 | jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins);
56 | }
57 |
58 | /**
59 | * Release all the static mocks.
60 | */
61 | @AfterEach
62 | void tearDown() {
63 | jenkinsMockedStatic.close();
64 | }
65 |
66 | /**
67 | * Tests {@link PluginImpl#getStaticResourcesBase()}. Just a simple one.
68 | *
69 | * TODO Make a similar test in a full Jenkins context.
70 | *
71 | */
72 | @Test
73 | void testGetStaticResourcesBase() {
74 | assertEquals("/plugin/build-failure-analyzer", PluginImpl.getStaticResourcesBase());
75 | }
76 |
77 |
78 | /**
79 | * Tests {@link PluginImpl#getStaticImagesBase()}}. Just a simple one.
80 | *
81 | * TODO Make a similar test in a full Jenkins context.
82 | *
83 | */
84 | @Test
85 | void testGetStaticImagesBase() {
86 | assertEquals("/plugin/build-failure-analyzer/images", PluginImpl.getStaticImagesBase());
87 | }
88 |
89 | /**
90 | * Tests that you can't set {@link PluginImpl#setNrOfScanThreads(int)} to 0.
91 | */
92 | @Test
93 | void testSetNrOfScanThreadsZero() {
94 | PluginImpl plugin = new PluginImpl();
95 | assertThrows(IllegalArgumentException.class, () ->
96 | plugin.setNrOfScanThreads(0));
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/FailureCauseWorkFlowTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2016 Sony Mobile Communications Inc. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa;
25 |
26 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
27 | import hudson.model.Result;
28 | import hudson.model.queue.QueueTaskFuture;
29 | import org.hamcrest.Matchers;
30 | import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
31 | import org.jenkinsci.plugins.workflow.job.WorkflowJob;
32 | import org.jenkinsci.plugins.workflow.job.WorkflowRun;
33 | import org.junit.jupiter.api.Test;
34 | import org.jvnet.hudson.test.JenkinsRule;
35 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
36 |
37 | import static org.hamcrest.MatcherAssert.assertThat;
38 | import static org.junit.jupiter.api.Assertions.assertNotNull;
39 | import static org.junit.jupiter.api.Assertions.assertNull;
40 |
41 | /**
42 | * Tests for WorkflowJobs.
43 | * @author Tomas Westling <tomas.westling@sonymobile.com>
44 | */
45 | @WithJenkins
46 | class FailureCauseWorkFlowTest {
47 |
48 | /**
49 | * Tests that an action is added when the builds fail.
50 | *
51 | * @param j
52 | *
53 | * @throws Exception if so.
54 | */
55 | @Test
56 | void testWorkflowFailureCauseBuildAction(JenkinsRule j) throws Exception {
57 | WorkflowJob proj = j.jenkins.createProject(WorkflowJob.class, "proj");
58 | proj.setDefinition(new CpsFlowDefinition("error()", false));
59 | QueueTaskFuture f = proj.scheduleBuild2(0);
60 | assertThat("build was actually scheduled", f, Matchers.notNullValue());
61 | WorkflowRun run = j.assertBuildStatus(Result.FAILURE, f.get());
62 | FailureCauseBuildAction action = run.getAction(FailureCauseBuildAction.class);
63 | assertNotNull(action);
64 | }
65 |
66 | /**
67 | * Tests that no action is added if all builds are successful.
68 | *
69 | * @param j
70 | *
71 | * @throws Exception if so.
72 | */
73 | @Test
74 | void testFailureCausesWhenNotFailed(JenkinsRule j) throws Exception {
75 | WorkflowJob proj = j.jenkins.createProject(WorkflowJob.class, "proj");
76 | proj.setDefinition(new CpsFlowDefinition("//Do nothing!", false));
77 | WorkflowRun run = j.assertBuildStatusSuccess(proj.scheduleBuild2(0));
78 | FailureCauseBuildAction action = run.getAction(FailureCauseBuildAction.class);
79 | assertNull(action);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/AnnotationHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa;
25 |
26 | import hudson.Functions;
27 | import java.io.Serializable;
28 |
29 | /**
30 | * Helper for annotating the lines, creates the strings to annotate with.
31 | *
32 | * @author Tomas Westling<tomas.westling@sonymobile.com>
33 | */
34 | public class AnnotationHelper implements Serializable {
35 |
36 | private String before = "";
37 | private String after = "";
38 | private String title = "";
39 |
40 | /**
41 | * Gets the String to annotate with before the console text.
42 | *
43 | * @return the String to put before the console text.
44 | */
45 | public String getBefore() {
46 | if (!title.isEmpty()) {
47 | return before
48 | + "";
50 | } else {
51 | return before;
52 | }
53 | }
54 |
55 | /**
56 | * Gets the String to annotate with after the console text.
57 | *
58 | * @return the String to put after the console text.
59 | */
60 | public String getAfter() {
61 | return after;
62 | }
63 |
64 | /**
65 | * Adds a focus id line before the console text.
66 | *
67 | * @param id the id for the line, to refer to in links.
68 | */
69 | public void addFocus(String id) {
70 | // This style should shift the anchor down below the header so that it's visible.
71 | // " " may be required to make this work for WebKit-based browsers.
72 | this.before += "";
75 | }
76 |
77 | /**
78 | * Adds a title for the line.
79 | *
80 | * @param addedTitle the title of the line.
81 | */
82 | public void addTitle(String addedTitle) {
83 | if (this.title.equals("")) {
84 | this.title = addedTitle;
85 | } else {
86 | this.title += "\n" + addedTitle;
87 | }
88 | }
89 |
90 | /**
91 | * Adds a String to annotate with, after the console text.
92 | *
93 | * @param addedAfter the String to put after the console text.
94 | */
95 | public void addAfter(String addedAfter) {
96 | this.after += addedAfter;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/ScanLogAction.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa;
2 |
3 | import edu.umd.cs.findbugs.annotations.NonNull;
4 | import hudson.model.Run;
5 | import java.io.File;
6 | import java.io.IOException;
7 | import java.nio.charset.StandardCharsets;
8 | import jenkins.model.RunAction2;
9 | import org.apache.commons.io.FileUtils;
10 | import org.kohsuke.accmod.Restricted;
11 | import org.kohsuke.accmod.restrictions.NoExternalUse;
12 | import org.kohsuke.stapler.export.Exported;
13 | import org.kohsuke.stapler.export.ExportedBean;
14 |
15 | /**
16 | * The Action for adding a link to the analysis for each run.
17 | */
18 | @ExportedBean
19 | public class ScanLogAction implements RunAction2 {
20 |
21 | /**
22 | * Log file name.
23 | */
24 | public static final String FILE_NAME = "com.sonyericsson.jenkins.plugins.bfa.ScanLogAction.log";
25 |
26 | private transient Run run;
27 |
28 | private long startTime = System.currentTimeMillis();
29 |
30 | private Long endTime;
31 |
32 | private String exceptionMessage;
33 |
34 | /**
35 | * {@inheritDoc}
36 | */
37 | @NonNull
38 | @Override
39 | public String getIconFileName() {
40 | return PluginImpl.getDefaultIcon();
41 | }
42 |
43 | /**
44 | * {@inheritDoc}
45 | */
46 | @NonNull
47 | @Override
48 | public String getDisplayName() {
49 | return Messages.ScanLogAction_DisplayName();
50 | }
51 |
52 | /**
53 | * The run associated with this action, called by jelly.
54 | * @return the run
55 | */
56 | public Run getRun() {
57 | return run;
58 | }
59 |
60 | /**
61 | * {@inheritDoc}
62 | */
63 | @NonNull
64 | @Override
65 | public String getUrlName() {
66 | return "failure-cause-scan-log";
67 | }
68 |
69 | /**
70 | * Log text for the analysis.
71 | * @return the log text, lines are separated by \n
72 | * @throws IOException if the log can't be found
73 | */
74 | public String getLogText() throws IOException {
75 | return FileUtils.readFileToString(new File(run.getRootDir(), FILE_NAME), StandardCharsets.UTF_8);
76 | }
77 |
78 | /**
79 | * The start time of the current scan.
80 | * @return time in milliseconds {@link System#currentTimeMillis}
81 | */
82 | @Exported
83 | public long getStartTime() {
84 | return startTime;
85 | }
86 |
87 | /**
88 | * The end time of the current scan.
89 | * @return time in milliseconds {@link System#currentTimeMillis}
90 | */
91 | @Exported
92 | public Long getEndTime() {
93 | return endTime;
94 | }
95 |
96 | /**
97 | * To call when the scan is finished.
98 | */
99 | @Restricted(NoExternalUse.class)
100 | protected void finished() {
101 | this.endTime = System.currentTimeMillis();
102 | }
103 |
104 | /**
105 | * Get the exception message if any.
106 | * @return the first exception faced during scan
107 | */
108 | public String getExceptionMessage() {
109 | return exceptionMessage;
110 | }
111 |
112 | /**
113 | * Set an exception.
114 | * @param exceptionMessage the exception message to set
115 | */
116 | public void setExceptionMessage(String exceptionMessage) {
117 | this.exceptionMessage = exceptionMessage;
118 | }
119 |
120 | /**
121 | * {@inheritDoc}
122 | */
123 | @Override
124 | public void onAttached(Run, ?> r) {
125 | this.run = r;
126 | }
127 |
128 | /**
129 | * {@inheritDoc}
130 | */
131 | @Override
132 | public void onLoad(Run, ?> r) {
133 | this.run = r;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/IndicationAnnotator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa;
25 |
26 | import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
27 | import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
28 | import hudson.MarkupText;
29 | import hudson.console.ConsoleAnnotator;
30 |
31 | import java.util.HashMap;
32 | import java.util.List;
33 | import java.util.Map;
34 |
35 | /**
36 | * Annotates the build log so that we can create links to it and mark found indications.
37 | *
38 | * @author Tomas Westling <tomas.westling@sonymobile.com>
39 | */
40 | public class IndicationAnnotator extends ConsoleAnnotator");
73 | helperMap.put(matchingString, matchingHelper);
74 | }
75 | }
76 | }
77 |
78 | @Override
79 | public ConsoleAnnotator annotate(Object context, MarkupText text) {
80 | AnnotationHelper match = helperMap.get(text.getText().replace("\n", "").replace("\r", ""));
81 | if (match != null) {
82 | text.wrapBy(match.getBefore(), match.getAfter());
83 | }
84 | return this;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/indication/MultilineBuildLogIndication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.model.indication;
25 |
26 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
27 | import com.fasterxml.jackson.annotation.JsonProperty;
28 | import com.fasterxml.jackson.annotation.JsonTypeInfo;
29 | import com.sonyericsson.jenkins.plugins.bfa.Messages;
30 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureReader;
31 | import com.sonyericsson.jenkins.plugins.bfa.model.MultilineBuildLogFailureReader;
32 | import hudson.Extension;
33 | import hudson.model.Hudson;
34 | import org.kohsuke.stapler.DataBoundConstructor;
35 |
36 | import java.util.regex.Pattern;
37 |
38 | /**
39 | * Build log indication that matches over multiple lines.
40 | *
41 | * @author Andrew Bayer
42 | */
43 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class", visible = true)
44 | @JsonIgnoreProperties(ignoreUnknown = true)
45 | public class MultilineBuildLogIndication extends BuildLogIndication {
46 |
47 | private static final long serialVersionUID = 8436383594898812087L;
48 | private transient Pattern compiled = null;
49 |
50 | /**
51 | * Standard constructor.
52 | *
53 | * @param pattern the string value to search for.
54 | */
55 | @DataBoundConstructor
56 | public MultilineBuildLogIndication(@JsonProperty("pattern") String pattern) {
57 | super(pattern);
58 | }
59 |
60 | @Override
61 | public FailureReader getReader() {
62 | return new MultilineBuildLogFailureReader(this);
63 | }
64 |
65 | @Override
66 | public Pattern getPattern() {
67 | if (compiled == null) {
68 | compiled = Pattern.compile("(?m)(?s)^[^\\r\\n]*?" + getUserProvidedExpression() + "[^\\r\\n]*?$",
69 | Pattern.MULTILINE | Pattern.DOTALL);
70 | }
71 | return compiled;
72 | }
73 |
74 | @Override
75 | public IndicationDescriptor getDescriptor() {
76 | return Hudson.getInstance().getDescriptorByType(MultilineBuildLogIndicationDescriptor.class);
77 | }
78 |
79 | /**
80 | * The descriptor.
81 | */
82 | @Extension
83 | public static class MultilineBuildLogIndicationDescriptor extends BuildLogIndicationDescriptor {
84 | @Override
85 | public String getDisplayName() {
86 | return Messages.MultilineBuildLogIndication_DisplayName();
87 | }
88 |
89 | @Override
90 | protected FailureReader getFailureReader(final String testPattern) {
91 | return new MultilineBuildLogFailureReader(new MultilineBuildLogIndication(testPattern));
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/MetricsManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa;
2 |
3 | import com.codahale.metrics.Counter;
4 | import com.codahale.metrics.MetricRegistry;
5 |
6 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
7 | import com.sonyericsson.jenkins.plugins.bfa.model.IFailureCauseMetricData;
8 | import com.sonyericsson.jenkins.plugins.bfa.model.indication.BuildLogIndication;
9 | import com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication;
10 | import jenkins.metrics.api.Metrics;
11 | import org.junit.jupiter.api.AfterEach;
12 | import org.junit.jupiter.api.BeforeEach;
13 | import org.junit.jupiter.api.Test;
14 | import org.mockito.MockedStatic;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Arrays;
18 | import java.util.Date;
19 | import java.util.LinkedList;
20 | import java.util.List;
21 |
22 | import static com.sonyericsson.jenkins.plugins.bfa.MetricsManager.addMetric;
23 | import static com.sonyericsson.jenkins.plugins.bfa.MetricsManager.incCounters;
24 | import static org.mockito.ArgumentMatchers.anyString;
25 | import static org.mockito.Mockito.mock;
26 | import static org.mockito.Mockito.mockStatic;
27 | import static org.mockito.Mockito.times;
28 | import static org.mockito.Mockito.verify;
29 | import static org.mockito.Mockito.when;
30 |
31 |
32 | /**
33 | * Tests for {@link MetricsManager}.
34 | */
35 | class MetricsManagerTest {
36 | private MetricRegistry metricRegistry;
37 | private Counter counter;
38 |
39 | private FailureCause mockedCause;
40 | private List extends IFailureCauseMetricData> mockedCauseList;
41 | private MockedStatic metricsMockedStatic;
42 |
43 | /**
44 | * Common stuff to set up for the tests.
45 | */
46 | @BeforeEach
47 | void setUp() {
48 | metricRegistry = mock(MetricRegistry.class);
49 | counter = mock(Counter.class);
50 | List indications = new LinkedList<>();
51 | Indication indication = new BuildLogIndication("something");
52 | indications.add(indication);
53 | mockedCause = new FailureCause("id", "myFailureCause", "description", "comment", new Date(),
54 | "category", indications, null);
55 | mockedCauseList = new ArrayList<>(Arrays.asList(mockedCause, mockedCause));
56 |
57 | metricsMockedStatic = mockStatic(Metrics.class);
58 | metricsMockedStatic.when(Metrics::metricRegistry).thenReturn(metricRegistry);
59 |
60 | when(metricRegistry.counter(anyString())).thenReturn(counter);
61 | }
62 |
63 | /**
64 | * Release all the static mocks.
65 | */
66 | @AfterEach
67 | void tearDown() {
68 | metricsMockedStatic.close();
69 | }
70 |
71 | /**
72 | * Test that the case and category counters are created from a FailureCause.
73 | */
74 | @Test
75 | void testAddMetric() {
76 | addMetric(mockedCause);
77 |
78 | verify(metricRegistry, times(1)).counter("jenkins_bfa.cause.myFailureCause");
79 | verify(metricRegistry, times(1)).counter("jenkins_bfa.category.category");
80 | }
81 |
82 | /**
83 | * Test that the cause and category counters are incremented twice for a FailureCause when not using squashing.
84 | */
85 | @Test
86 | void testIncCountersWithSquashingDisabled() {
87 | incCounters(mockedCauseList, false);
88 |
89 | verify(counter, times(mockedCauseList.size() * 2)).inc();
90 | }
91 |
92 | /**
93 | * Test that the cause and category counters are incremented once for a FailureCause when using squashing.
94 | */
95 | @Test
96 | void testIncCountersWithSquashingEnabled() {
97 | incCounters(mockedCauseList, true);
98 |
99 | verify(counter, times(mockedCauseList.size())).inc();
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/providers/FailureCauseProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2017 Axis Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.providers;
25 |
26 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
27 | import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
28 | import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
29 | import hudson.Extension;
30 | import hudson.model.Run;
31 | import net.sf.json.JSONArray;
32 | import net.sf.json.JSONObject;
33 | import com.sonymobile.jenkins.plugins.mq.mqnotifier.providers.MQDataProvider;
34 |
35 | import java.util.List;
36 |
37 | /**
38 | * Provides information about the failure causes for a build.
39 | *
40 | * @author Tomas Westling <tomas.westling@axis.com>
41 | */
42 | @Extension(optional = true)
43 | public class FailureCauseProvider extends MQDataProvider {
44 |
45 | @Override
46 | public void provideCompletedRunData(Run run, JSONObject json) {
47 | FailureCauseBuildAction action = run.getAction(FailureCauseBuildAction.class);
48 | if (action != null) {
49 | List foundFailureCausesList = action.getFoundFailureCauses();
50 | JSONArray failureCausesJSONArray = new JSONArray();
51 | for (FoundFailureCause foundFailureCause : foundFailureCausesList) {
52 | JSONObject failureCauseJSONObject = new JSONObject();
53 | failureCauseJSONObject.put("id", foundFailureCause.getId());
54 | failureCauseJSONObject.put("name", foundFailureCause.getName());
55 | failureCauseJSONObject.put("description", foundFailureCause.getDescription());
56 | failureCauseJSONObject.put("categories", foundFailureCause.getCategories());
57 | JSONArray foundIndicationsJSONArray = new JSONArray();
58 | for (FoundIndication indication : foundFailureCause.getIndications()) {
59 | JSONObject foundIndicationJSONObject = new JSONObject();
60 | foundIndicationJSONObject.put("pattern", indication.getPattern());
61 | foundIndicationJSONObject.put("matchingString", indication.getMatchingString());
62 | foundIndicationJSONObject.put("matchingLine", indication.getMatchingLine());
63 | foundIndicationsJSONArray.add(foundIndicationJSONObject);
64 | }
65 | failureCauseJSONObject.put("indications", foundIndicationsJSONArray);
66 | failureCausesJSONArray.add(failureCauseJSONObject);
67 | }
68 | json.put("failurecauses", failureCausesJSONArray);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/dbf/DownstreamBuildFinder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2013 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.model.dbf;
26 |
27 | import hudson.ExtensionList;
28 | import hudson.ExtensionPoint;
29 | import hudson.Util;
30 | import hudson.model.AbstractBuild;
31 | import hudson.model.Hudson;
32 | import hudson.model.Run;
33 |
34 | import java.util.Collections;
35 | import java.util.LinkedList;
36 | import java.util.List;
37 |
38 | /**
39 | * There is no general way to find downstream build in Jenkins Core. Different
40 | * plugin have there own way of keeping this information.
41 | * Extend this class and implement
42 | * {@link #getDownstreamBuilds(hudson.model.Run)}
43 | * in a way suitable for the plugin
44 | *
45 | * @author Jan-Olof Sivtoft
46 | */
47 | public abstract class DownstreamBuildFinder implements ExtensionPoint {
48 |
49 | /**
50 | * No need to create a new empty list each time there is nothing to return.
51 | * Make it unmodifiable to make sure it isn't used.
52 | */
53 | protected static final List> EMPTY =
54 | Collections.unmodifiableList(new LinkedList>());
55 |
56 | /**
57 | * Return a list of all downstream builds originating from provided build.
58 | *
59 | * @param build get the downstream build(s) relative this build
60 | * @return a list with downstream builds
61 | * @deprecated use {@link #getDownstreamBuilds(hudson.model.Run)}
62 | */
63 | @Deprecated
64 | public List> getDownstreamBuilds(final AbstractBuild build) {
65 | if (Util.isOverridden(DownstreamBuildFinder.class, getClass(), "getDownstreamBuilds", Run.class)) {
66 | return getDownstreamBuilds((Run)build);
67 | }
68 | return null;
69 | }
70 |
71 | /**
72 | * Return a list of all downstream builds originating from provided build.
73 | *
74 | * @param build get the downstream build(s) relative this build
75 | * @return a list with downstream builds
76 | */
77 | public List> getDownstreamBuilds(final Run build) {
78 | if (Util.isOverridden(DownstreamBuildFinder.class, getClass(), "getDownstreamBuilds", AbstractBuild.class)) {
79 | return getDownstreamBuilds((AbstractBuild)build);
80 | }
81 | return null;
82 | }
83 |
84 | /**
85 | * Return a list of all registered DownstreamBuildFinder of this type.
86 | *
87 | * @return a list of DownstreamBuildFinder
88 | */
89 | public static ExtensionList getAll() {
90 | return Hudson.getInstance().
91 | getExtensionList(DownstreamBuildFinder.class);
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/sod/ScanOnDemandBaseAction/ScanMode/index.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | * Copyright (c) 2016, CloudBees, Inc.
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | import com.sonyericsson.jenkins.plugins.bfa.sod.ScanOnDemandBaseAction
27 |
28 | def l = namespace(lib.LayoutTagLib)
29 | def st = namespace("jelly:stapler")
30 | def f = namespace(lib.FormTagLib)
31 |
32 | ScanOnDemandBaseAction.ScanMode mode = my;
33 | mode.setAsDefault()
34 |
35 | l.layout(title: _("Failure Scan Options"), norefresh: true) {
36 | l.header {
37 | mode.parent.checkPermission()
38 | style(type: "text/css", """
39 | tr.disablehover:hover {
40 | background-color: white;
41 | }
42 | """)
43 |
44 | }
45 | st.include(it: mode.parent.project, page: "sidepanel.jelly")
46 | l.'main-panel' {
47 | st.adjunct(includes: "com.sonyericsson.jenkins.plugins.bfa.sod.ScanOnDemandBaseAction.ScanMode.resource")
48 | f.form {
49 | f.section(title: _("Select the option and scan the builds")) {
50 | ScanOnDemandBaseAction.ScanMode.all().each { ScanOnDemandBaseAction.ScanMode option ->
51 | f.entry(field: option.urlName, class: "bfa-scan-mode-build-type-radio-entry",
52 | help: "/plugin/build-failure-analyzer/help/sod/${option.urlName}.html") {
53 | span(class: "bfa-entry-data-holder", "data-root-url": "${rootURL}", "data-option-full-url": "${option.getFullUrl()}")
54 | f.radio(name: "buildType",
55 | value: option.urlName,
56 | checked: option == mode,
57 | title: option.displayName)
58 | }
59 | }
60 | }
61 | }
62 | if (!mode.hasAnyRun(mode.parent.project)) {
63 | f.section(title: _("No build found")) {
64 | f.block {
65 | table(width: "100%", border: "0", cellpadding: "2", cellspacing: "0",
66 | class: "pane bigtable", style: "margin-top: 0") {
67 | tr {
68 | td()
69 | td {
70 | strong(_("No build found to scan"))
71 | }
72 | }
73 | }
74 | }
75 | }
76 | } else {
77 | f.form(method: "POST", action: "performScan") {
78 | f.section {
79 | f.block {
80 | f.submit(value: _("Scan"))
81 | }
82 | }
83 | }
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/ScannerJobProperty.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.model;
26 |
27 | import com.sonyericsson.jenkins.plugins.bfa.FailureCauseMatrixAggregator;
28 | import com.sonyericsson.jenkins.plugins.bfa.Messages;
29 | import hudson.Extension;
30 | import hudson.Launcher;
31 | import hudson.matrix.MatrixAggregatable;
32 | import hudson.matrix.MatrixAggregator;
33 | import hudson.matrix.MatrixBuild;
34 | import hudson.model.Action;
35 | import hudson.model.BuildListener;
36 | import hudson.model.Job;
37 | import hudson.model.JobProperty;
38 | import hudson.model.JobPropertyDescriptor;
39 | import org.kohsuke.stapler.DataBoundConstructor;
40 |
41 | import java.io.Serializable;
42 |
43 | import org.kohsuke.accmod.Restricted;
44 | import org.kohsuke.accmod.restrictions.NoExternalUse;
45 |
46 | /**
47 | * A JobProperty that flags a job that should not be scanned. Also works as the {@link MatrixAggregatable}
48 | *
49 | * @author Robert Sandell <robert.sandell@sonymobile.com>
50 | */
51 | public class ScannerJobProperty extends JobProperty> implements MatrixAggregatable, Serializable {
52 |
53 | private boolean doNotScan;
54 |
55 | /**
56 | * Standard DataBound Constructor.
57 | *
58 | * @param doNotScan signal that builds of this job should not be scanned.
59 | */
60 | @DataBoundConstructor
61 | public ScannerJobProperty(boolean doNotScan) {
62 | this.doNotScan = doNotScan;
63 | }
64 |
65 | /**
66 | * Default Constructor. Do not use unless you are a serializer!
67 | */
68 | public ScannerJobProperty() {
69 | }
70 |
71 | /**
72 | * The value. True turns the scanner off.
73 | *
74 | * @return if no scan should be done.
75 | */
76 | public boolean isDoNotScan() {
77 | return doNotScan;
78 | }
79 |
80 | @Override
81 | @Restricted(NoExternalUse.class)
82 | public Action getJobAction(Job, ?> job) {
83 | return new FailureCauseProjectAction(job);
84 | }
85 |
86 | @Override
87 | public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
88 | return new FailureCauseMatrixAggregator(build, launcher, listener);
89 | }
90 |
91 | /**
92 | * Descriptor for {@link ScannerJobProperty}.
93 | */
94 | @Extension
95 | public static class ScannerJobPropertyDescriptor extends JobPropertyDescriptor {
96 |
97 | @Override
98 | public String getDisplayName() {
99 | return Messages.ScannerJobProperty_DisplayName();
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/BuildLogFailureReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.model;
26 |
27 | import com.sonyericsson.jenkins.plugins.bfa.model.indication.BuildLogIndication;
28 | import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
29 | import hudson.model.Run;
30 |
31 | import java.io.BufferedReader;
32 | import java.io.IOException;
33 | import java.util.ArrayList;
34 | import java.util.List;
35 | import java.util.logging.Level;
36 | import java.util.logging.Logger;
37 |
38 |
39 | /**
40 | * Reader used to find indications of a failure cause.
41 | *
42 | * @author Tomas Westling <tomas.westling@sonymobile.com>
43 | */
44 | public class BuildLogFailureReader extends FailureReader {
45 |
46 | private static final Logger logger = Logger.getLogger(BuildLogFailureReader.class.getName());
47 |
48 | /**
49 | * Standard constructor.
50 | * @param indication the indication to look for.
51 | */
52 | public BuildLogFailureReader(BuildLogIndication indication) {
53 | super(indication);
54 | }
55 |
56 | /**
57 | * Scans a build log.
58 | *
59 | * @param build - the build whose log should be scanned.
60 | * @return a FoundIndication if the pattern given by this BuildLogFailureReader
61 | * is found in the log of the given build; return null otherwise.
62 | * @throws IOException if so.
63 | */
64 | @Override
65 | public FoundIndication scan(Run build) throws IOException {
66 | BufferedReader reader = null;
67 | try {
68 | reader = new BufferedReader(build.getLogReader());
69 | List causes = new ArrayList(1);
70 | FailureCause fc = new FailureCause("somename", "somedescription");
71 | causes.add(fc);
72 | fc.addIndication(indication);
73 | List foundFailureCauses = FailureReader.scanSingleLinePatterns(causes,
74 | build,
75 | reader,
76 | "log");
77 | if (foundFailureCauses.isEmpty()) {
78 | return null;
79 | } else {
80 | return foundFailureCauses.get(0).getIndications().get(0);
81 | }
82 | } finally {
83 | if (reader != null) {
84 | try {
85 | reader.close();
86 | } catch (IOException e) {
87 | logger.log(Level.WARNING, "Failed to close the reader. ", e);
88 | }
89 | }
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/jcasc/ConfigurationAsCodeLocalTest.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa.jcasc;
2 |
3 | import com.sonyericsson.jenkins.plugins.bfa.PluginImpl;
4 | import com.sonyericsson.jenkins.plugins.bfa.db.LocalFileKnowledgeBase;
5 | import com.sonyericsson.jenkins.plugins.bfa.sod.ScanOnDemandVariables;
6 | import io.jenkins.plugins.casc.ConfigurationContext;
7 | import io.jenkins.plugins.casc.ConfiguratorRegistry;
8 | import io.jenkins.plugins.casc.misc.ConfiguredWithCode;
9 | import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule;
10 | import io.jenkins.plugins.casc.misc.junit.jupiter.WithJenkinsConfiguredWithCode;
11 | import io.jenkins.plugins.casc.model.CNode;
12 | import org.junit.jupiter.api.Test;
13 |
14 | import static io.jenkins.plugins.casc.misc.Util.getUnclassifiedRoot;
15 | import static io.jenkins.plugins.casc.misc.Util.toStringFromYamlFile;
16 | import static io.jenkins.plugins.casc.misc.Util.toYamlString;
17 | import static org.hamcrest.MatcherAssert.assertThat;
18 | import static org.hamcrest.core.Is.is;
19 | import static org.hamcrest.core.IsInstanceOf.instanceOf;
20 |
21 | /**
22 | * Checks configuration as code integration for local DB.
23 | */
24 | @WithJenkinsConfiguredWithCode
25 | class ConfigurationAsCodeLocalTest {
26 |
27 | static final String NO_CAUSES_MESSAGE = "No problems were identified. Please contribute causes to help others";
28 | static final int EXPECTED_SCAN_THREADS = 6;
29 | static final int EXPECTED_MAXIMUM_SOD_WORKER_THREADS = 7;
30 | static final int EXPECTED_MINIMUM_SOD_WORKER_THREADS = 2;
31 | static final int EXPECTED_SOD_CORE_POOL_NUMBER_OF_THREADS = 6;
32 | static final int EXPECTED_SOD_THREAD_KEEP_ALIVE_TIME = 17;
33 | static final int EXPECTED_SOD_JOB_SHUTDOWN_TIMEOUT = 32;
34 |
35 | /**
36 | * Support config as code import.
37 | *
38 | * @param j
39 | *
40 | */
41 | @Test
42 | @ConfiguredWithCode("jcasc-local.yml")
43 | void shouldSupportConfigurationAsCode(JenkinsConfiguredWithCodeRule j) {
44 | PluginImpl plugin = PluginImpl.getInstance();
45 |
46 | assertThat(plugin.isDoNotAnalyzeAbortedJob(), is(true));
47 | assertThat(plugin.isGerritTriggerEnabled(), is(true));
48 | assertThat(plugin.isGlobalEnabled(), is(true));
49 | assertThat(plugin.isGraphsEnabled(), is(false));
50 | assertThat(plugin.getKnowledgeBase(), instanceOf(LocalFileKnowledgeBase.class));
51 | assertThat(plugin.getNoCausesMessage(), is(NO_CAUSES_MESSAGE));
52 |
53 | assertThat(plugin.getNrOfScanThreads(), is(EXPECTED_SCAN_THREADS));
54 |
55 | ScanOnDemandVariables sodVariables = plugin.getSodVariables();
56 |
57 | assertThat(sodVariables.getMaximumSodWorkerThreads(), is(EXPECTED_MAXIMUM_SOD_WORKER_THREADS));
58 | assertThat(sodVariables.getMinimumSodWorkerThreads(), is(EXPECTED_MINIMUM_SOD_WORKER_THREADS));
59 | assertThat(sodVariables.getSodCorePoolNumberOfThreads(), is(EXPECTED_SOD_CORE_POOL_NUMBER_OF_THREADS));
60 | assertThat(sodVariables.getSodThreadKeepAliveTime(), is(EXPECTED_SOD_THREAD_KEEP_ALIVE_TIME));
61 | assertThat(sodVariables.getSodWaitForJobShutdownTimeout(), is(EXPECTED_SOD_JOB_SHUTDOWN_TIMEOUT));
62 |
63 | assertThat(plugin.getTestResultCategories(), is("hgjghhlllllaa"));
64 | assertThat(plugin.isTestResultParsingEnabled(), is(true));
65 |
66 | assertThat(plugin.isMetricSquashingEnabled(), is(false));
67 | }
68 |
69 | /**
70 | * Support config as code export.
71 | *
72 | * @param j
73 | *
74 | * @throws Exception if so.
75 | */
76 | @Test
77 | @ConfiguredWithCode("jcasc-local.yml")
78 | void shouldSupportConfigurationExport(JenkinsConfiguredWithCodeRule j) throws Exception {
79 | ConfiguratorRegistry registry = ConfiguratorRegistry.get();
80 | ConfigurationContext context = new ConfigurationContext(registry);
81 | CNode yourAttribute = getUnclassifiedRoot(context).get("buildFailureAnalyzer");
82 |
83 | String exported = toYamlString(yourAttribute);
84 |
85 | String expected = toStringFromYamlFile(this, "jcasc-local-expected.yml");
86 |
87 | assertThat(exported, is(expected));
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseColumnTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2014 Vincent Latombe
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.model;
25 |
26 | import static org.junit.jupiter.api.Assertions.assertNotNull;
27 | import static org.junit.jupiter.api.Assertions.assertNull;
28 |
29 | import hudson.model.FreeStyleBuild;
30 | import hudson.model.Result;
31 | import hudson.model.FreeStyleProject;
32 |
33 | import org.junit.jupiter.api.Test;
34 | import org.jvnet.hudson.test.JenkinsRule;
35 | import org.jvnet.hudson.test.JenkinsRule.WebClient;
36 | import org.jvnet.hudson.test.FailureBuilder;
37 | import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
38 | import org.jvnet.hudson.test.recipes.LocalData;
39 |
40 | import org.htmlunit.html.HtmlPage;
41 |
42 | /**
43 | * Tests for {@link FailureCauseColumn}.
44 | *
45 | * @author Vincent Latombe <vincent@latombe.net>
46 | */
47 | @WithJenkins
48 | class FailureCauseColumnTest {
49 |
50 | /**
51 | * Happy test case with a view containing a {@link FailureCauseColumn}, text option being disabled.
52 | *
53 | * @param j
54 | *
55 | * @throws Exception
56 | * if so
57 | */
58 | @LocalData
59 | @Test
60 | void givenAViewWithTheFailureCauseColumnDisplayTheFirstFailureCauseAsTitle(JenkinsRule j) throws Exception {
61 | FreeStyleProject fs = j.createFreeStyleProject("total_failure");
62 | fs.getBuildersList().add(new FailureBuilder());
63 | fs.save();
64 |
65 | FreeStyleBuild r = fs.scheduleBuild2(0).get();
66 | j.assertBuildStatus(Result.FAILURE, r);
67 |
68 | WebClient webClient = j.createWebClient();
69 | HtmlPage page = webClient.goTo("view/columnwithouttext");
70 | assertNotNull(page.getFirstByXPath("//*[local-name()='svg'][@tooltip='Failure Builder']"),
71 | "Couldn't find the failure cause svg in columnwithouttext view");
72 | assertNull(page.getDocumentElement().getFirstByXPath("//*[.='Failure Builder']"));
73 | }
74 |
75 | /**
76 | * Happy test case with a view containing a {@link FailureCauseColumn}, text option being enabled.
77 | *
78 | * @param j
79 | *
80 | * @throws Exception
81 | * if so
82 | */
83 | @LocalData
84 | @Test
85 | void givenAViewWithTheFailureCauseColumnWithTextDisplayTheFirstFailureCauseAsTitleAndText(JenkinsRule j)
86 | throws Exception {
87 | FreeStyleProject fs = j.createFreeStyleProject("total_failure");
88 | fs.getBuildersList().add(new FailureBuilder());
89 | fs.save();
90 |
91 | FreeStyleBuild r = fs.scheduleBuild2(0).get();
92 | j.assertBuildStatus(Result.FAILURE, r);
93 |
94 | WebClient webClient = j.createWebClient();
95 | HtmlPage page = webClient.goTo("view/columnwithtext");
96 | System.out.println(page.getTextContent());
97 | assertNotNull(page.getFirstByXPath("//*[local-name()='svg'][@tooltip='Failure Builder']"),
98 | "Couldn't find the failure cause svg in columnwithtext view");
99 | assertNotNull(page.getFirstByXPath("//*[contains(text(), 'Failure Builder')]"));
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/dbf/ParameterizedTriggerDBF.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2013 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.model.dbf;
26 |
27 | import hudson.Extension;
28 | import hudson.model.Action;
29 | import hudson.model.Run;
30 |
31 | import java.lang.reflect.InvocationTargetException;
32 | import java.lang.reflect.Method;
33 | import java.util.List;
34 | import java.util.logging.Level;
35 | import java.util.logging.Logger;
36 |
37 | /**
38 | * Get downstream builds for the Parameterized Trigger Plugin.
39 | * We want to avoid having dependencies to other plugins thus using reflection.
40 | *
41 | * @author Jan-Olof Sivtoft
42 | */
43 | @Extension
44 | public class ParameterizedTriggerDBF extends DownstreamBuildFinder {
45 |
46 | private static final Logger logger = Logger.
47 | getLogger(ParameterizedTriggerDBF.class.getName());
48 |
49 | /**
50 | * Return a list of all downstream builds originating from provided build.
51 | * Getting build originating from the usage of the parameterized trigger
52 | * plugin.
53 | *
54 | * @param build get the downstream build(s) relative this build
55 | * @return a list with downstream builds
56 | */
57 | @Override
58 | public List> getDownstreamBuilds(
59 | final Run build) {
60 |
61 | if (build == null) {
62 | return EMPTY;
63 | }
64 |
65 | // The action class to examine for downstream builds
66 | String className =
67 | "hudson.plugins.parameterizedtrigger.BuildInfoExporterAction";
68 | // The method returning triggered builds
69 | String methodName = "getTriggeredBuilds";
70 |
71 | try {
72 | // The BuildInfoExporterAction class
73 | Class clazz = Class.forName(className);
74 | // The BuildInfoExporterAction instance
75 | Action action = build.getAction(clazz);
76 |
77 | // Check triggered builds
78 | if (action != null) {
79 | Method method = clazz.getMethod(methodName);
80 | return (List)method.invoke(action);
81 | } else {
82 | return EMPTY;
83 | }
84 | // All exceptions below are due to using reflection, thus silently
85 | // return an empty list as it doesn't exists.
86 | } catch (ClassNotFoundException e) {
87 | // Either the plugin doesn't exist, silently exit.
88 | // Or className is wrong - treated as it doesn't exist
89 | logger.log(Level.FINER, "Class " + className + " not installed. "
90 | + "Can't get downstream builds");
91 | return EMPTY;
92 | } catch (NoSuchMethodException e) {
93 | logger.log(Level.FINER, "Method " + methodName
94 | + " doesn't exists in " + "class " + className + ".");
95 | return EMPTY;
96 | } catch (InvocationTargetException e) {
97 | return EMPTY;
98 | } catch (IllegalAccessException e) {
99 | return EMPTY;
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/jcasc/ConfigurationAsCodeMongoTest.java:
--------------------------------------------------------------------------------
1 | package com.sonyericsson.jenkins.plugins.bfa.jcasc;
2 |
3 | import com.sonyericsson.jenkins.plugins.bfa.PluginImpl;
4 | import com.sonyericsson.jenkins.plugins.bfa.db.MongoDBKnowledgeBase;
5 | import com.sonyericsson.jenkins.plugins.bfa.sod.ScanOnDemandVariables;
6 | import io.jenkins.plugins.casc.ConfigurationContext;
7 | import io.jenkins.plugins.casc.ConfiguratorRegistry;
8 | import io.jenkins.plugins.casc.misc.ConfiguredWithCode;
9 | import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule;
10 | import io.jenkins.plugins.casc.misc.junit.jupiter.WithJenkinsConfiguredWithCode;
11 | import io.jenkins.plugins.casc.model.CNode;
12 | import org.junit.jupiter.api.Test;
13 |
14 | import static io.jenkins.plugins.casc.misc.Util.getUnclassifiedRoot;
15 | import static io.jenkins.plugins.casc.misc.Util.toStringFromYamlFile;
16 | import static io.jenkins.plugins.casc.misc.Util.toYamlString;
17 | import static org.hamcrest.MatcherAssert.assertThat;
18 | import static org.hamcrest.core.Is.is;
19 |
20 | /**
21 | * Checks configuration as code integration for mongo DB.
22 | */
23 | @WithJenkinsConfiguredWithCode
24 | class ConfigurationAsCodeMongoTest {
25 |
26 | /**
27 | * Support config as code import.
28 | *
29 | * @param j
30 | *
31 | */
32 | @Test
33 | @ConfiguredWithCode("jcasc-mongo.yml")
34 | void shouldSupportConfigurationAsCode(JenkinsConfiguredWithCodeRule j) {
35 | PluginImpl plugin = PluginImpl.getInstance();
36 |
37 | assertThat(plugin.isDoNotAnalyzeAbortedJob(), is(true));
38 | assertThat(plugin.isGerritTriggerEnabled(), is(true));
39 | assertThat(plugin.isGlobalEnabled(), is(true));
40 | assertThat(plugin.isGraphsEnabled(), is(false));
41 |
42 | MongoDBKnowledgeBase knowledgeBase = (MongoDBKnowledgeBase)plugin.getKnowledgeBase();
43 | assertThat(knowledgeBase.getHost(), is("localhost"));
44 | assertThat(knowledgeBase.getDbName(), is("bfa"));
45 | assertThat(knowledgeBase.isEnableStatistics(), is(true));
46 | assertThat(knowledgeBase.getUserName(), is("bfa"));
47 | assertThat(knowledgeBase.getPassword().getPlainText(), is("changeme"));
48 | assertThat(knowledgeBase.isSuccessfulLogging(), is(false));
49 |
50 | assertThat(plugin.getNoCausesMessage(), is(ConfigurationAsCodeLocalTest.NO_CAUSES_MESSAGE));
51 |
52 | assertThat(plugin.getNrOfScanThreads(), is(ConfigurationAsCodeLocalTest.EXPECTED_SCAN_THREADS));
53 |
54 | ScanOnDemandVariables sodVariables = plugin.getSodVariables();
55 |
56 | assertThat(sodVariables.getMaximumSodWorkerThreads(),
57 | is(ConfigurationAsCodeLocalTest.EXPECTED_MAXIMUM_SOD_WORKER_THREADS));
58 | assertThat(sodVariables.getMinimumSodWorkerThreads(),
59 | is(ConfigurationAsCodeLocalTest.EXPECTED_MINIMUM_SOD_WORKER_THREADS));
60 | assertThat(sodVariables.getSodCorePoolNumberOfThreads(),
61 | is(ConfigurationAsCodeLocalTest.EXPECTED_SOD_CORE_POOL_NUMBER_OF_THREADS));
62 | assertThat(sodVariables.getSodThreadKeepAliveTime(),
63 | is(ConfigurationAsCodeLocalTest.EXPECTED_SOD_THREAD_KEEP_ALIVE_TIME));
64 | assertThat(sodVariables.getSodWaitForJobShutdownTimeout(),
65 | is(ConfigurationAsCodeLocalTest.EXPECTED_SOD_JOB_SHUTDOWN_TIMEOUT));
66 |
67 | assertThat(plugin.getTestResultCategories(), is("hgjghhlllllaa"));
68 | assertThat(plugin.isTestResultParsingEnabled(), is(true));
69 |
70 | assertThat(plugin.isMetricSquashingEnabled(), is(false));
71 | }
72 |
73 | /**
74 | * Support config as code export.
75 | *
76 | * @param j
77 | *
78 | * @throws Exception if so.
79 | */
80 | @Test
81 | @ConfiguredWithCode("jcasc-mongo.yml")
82 | void shouldSupportConfigurationExport(JenkinsConfiguredWithCodeRule j) throws Exception {
83 | ConfiguratorRegistry registry = ConfiguratorRegistry.get();
84 | ConfigurationContext context = new ConfigurationContext(registry);
85 | CNode yourAttribute = getUnclassifiedRoot(context).get("buildFailureAnalyzer");
86 |
87 | String exported = toYamlString(yourAttribute)
88 | .replaceAll(".+password: .+", ""); // ignore dynamic password secret
89 |
90 | String expected = toStringFromYamlFile(this, "jcasc-mongo-expected.yml");
91 |
92 | assertThat(exported, is(expected));
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCause/index.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications Inc. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.model.FailureCause
25 | import com.sonyericsson.jenkins.plugins.bfa.PluginImpl
26 | import hudson.Util
27 |
28 | import java.text.DateFormat
29 |
30 | def f = namespace(lib.FormTagLib)
31 | def l = namespace(lib.LayoutTagLib)
32 | def j = namespace(lib.JenkinsTagLib)
33 |
34 | l.layout(permission: PluginImpl.UPDATE_PERMISSION) {
35 | l.header(title: _("Failure Cause Management") + " " + my.getName())
36 |
37 | def management = my.getAncestorCauseManagement();
38 |
39 | context.setVariable("descriptor", my.getDescriptor());
40 | descriptor.setLastFailedBuildUrl();
41 |
42 | l.side_panel() {
43 | if (!management.isUnderTest()) {
44 | include(management.getOwner(), "sidepanel.jelly")
45 | }
46 | }
47 |
48 | l.main_panel() {
49 | l.app_bar(title:"Failure Cause") {
50 | if (Util.fixEmpty(my.getId()) != null) {
51 | a(class: "jenkins-button jenkins-!-destructive-color", href: "../remove?id=" + my.getId(), tooltip: _("Remove this cause")) {
52 | l.icon(src:"symbol-trash")
53 | text(_("Remove"))
54 | }
55 | }
56 | }
57 |
58 | f.form(action: "configSubmit", method: "POST", name: "causeForm", class: "jenkins-form") {
59 | f.invisibleEntry() {
60 | f.textbox(field: "id", value: my.getId())
61 | }
62 | f.entry(title: _("Name"), field: "name") {
63 | f.textbox(value: my.getName(), checkMethod: "post")
64 | }
65 | f.entry(title: _("Description"), field: "description") {
66 | f.textarea(value: my.getDescription(), checkMethod: "post")
67 | }
68 | f.entry(title: _("Comment"), field: "comment") {
69 | f.textarea(value: my.getComment())
70 | }
71 | f.entry(title: _("Categories"), field: "categories") {
72 | f.textbox(value: my.getCategoriesAsString(), autoCompleteDelimChar: " ")
73 | }
74 | f.section(title: _("Indications")) {
75 | f.block {
76 | f.hetero_list(
77 | name: "indications",
78 | hasHeader: true,
79 | descriptors: management.getIndicationDescriptors(),
80 | items: my.getIndications(),
81 | addCaption: _("Add Indication"),
82 | deleteCaption: _("Delete Indication"))
83 | }
84 | }
85 | f.section(title: _("Modification history")) {
86 | def history = my.getAndInitiateModifications();
87 | f.block {
88 | if (history != null) {
89 | ul(id: "modifications") {
90 | history.each{ entry ->
91 | def dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,
92 | DateFormat.SHORT).format(entry.getTime());
93 | li {text(_("ModifiedBy", dateFormat,
94 | entry.getUser() == null ? "unknown": entry.getUser()))}
95 | }
96 | }
97 | }
98 | }
99 | }
100 | f.block {
101 | div(style: "margin-top: 10px")
102 | f.submit(value: _("Save"))
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseColumn.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2014 Vincent Latombe
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.model;
25 |
26 | import hudson.Extension;
27 | import hudson.model.Job;
28 | import hudson.model.Run;
29 | import hudson.views.ListViewColumnDescriptor;
30 | import hudson.views.ListViewColumn;
31 |
32 | import java.util.Collections;
33 | import java.util.List;
34 |
35 | import org.kohsuke.stapler.DataBoundConstructor;
36 |
37 | /**
38 | * A column that user can add to a view to display the failure cause of the last build.
39 | *
40 | * @author vlatombe
41 | *
42 | */
43 | public class FailureCauseColumn extends ListViewColumn {
44 |
45 | /**
46 | * The descriptor for {@link FailureCauseColumn}.
47 | * @author vlatombe
48 | *
49 | */
50 | @Extension
51 | public static class DescriptorImpl extends ListViewColumnDescriptor {
52 | @Override
53 | public String getDisplayName() {
54 | return "Failure Cause";
55 | }
56 |
57 | @Override
58 | public boolean shownByDefault() {
59 | return false;
60 | }
61 | }
62 |
63 | private boolean showText;
64 |
65 | /**
66 | * The standard data-bound constructor.
67 | *
68 | * @param showText
69 | * if true, will display the text of the failure cause next to the icon
70 | */
71 | @DataBoundConstructor
72 | public FailureCauseColumn(boolean showText) {
73 | this.showText = showText;
74 | }
75 |
76 | /**
77 | * @see FailureCauseBuildAction#getBadgeImageUrl()
78 | * @param job The given job we want the badge image url for
79 | * @return the image url
80 | * @deprecated plugin now uses icons. Please use {@link #getIconFileName(Job)} instead.
81 | */
82 | @Deprecated
83 | public String getBadgeImageUrl(Job job) {
84 | FailureCauseBuildAction action = findFailureCauseBuildAction(job);
85 | if (action == null) {
86 | return null;
87 | }
88 | return action.getBadgeImageUrl();
89 | }
90 |
91 | /**
92 | * @see FailureCauseBuildAction#getIconFileName()
93 | * @param job The given job we want the badge icon name for
94 | * @return the icon name
95 | */
96 | public String getIconFileName(Job job) {
97 | FailureCauseBuildAction action = findFailureCauseBuildAction(job);
98 | if (action == null) {
99 | return null;
100 | }
101 | return action.getIconFileName();
102 | }
103 |
104 |
105 | /**
106 | * @see FailureCauseBuildAction#getFoundFailureCauses()
107 | * @param job the job we want to retrieve actions for
108 | * @return the list of found failure causes
109 | */
110 | public List getFoundFailureCauses(Job job) {
111 | FailureCauseBuildAction action = findFailureCauseBuildAction(job);
112 | if (action == null) {
113 | return Collections.emptyList();
114 | }
115 | return action.getFoundFailureCauses();
116 | }
117 |
118 | /**
119 | * @return true if text should be displayed next to the failure cause icon
120 | */
121 | public boolean isShowText() {
122 | return showText;
123 | }
124 |
125 | /**
126 | * A helper method to retrieve the {@link FailureCauseBuildAction} from the given {@link Job}
127 | * @param job the given job
128 | * @return The {@link FailureCauseBuildAction} if it exists, otherwise null
129 | */
130 | private FailureCauseBuildAction findFailureCauseBuildAction(Job job) {
131 | if (job == null) {
132 | return null;
133 | }
134 | Run lastBuild = job.getLastBuild();
135 | if (lastBuild == null) {
136 | return null;
137 | }
138 | return lastBuild.getAction(FailureCauseBuildAction.class);
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/db/EmbeddedMongoTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2013 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa.db;
25 |
26 | import de.flapdoodle.embed.mongo.Command;
27 | import de.flapdoodle.embed.mongo.MongodExecutable;
28 | import de.flapdoodle.embed.mongo.MongodProcess;
29 | import de.flapdoodle.embed.mongo.MongodStarter;
30 | import de.flapdoodle.embed.mongo.config.DownloadConfigBuilder;
31 | import de.flapdoodle.embed.mongo.config.ExtractedArtifactStoreBuilder;
32 | import de.flapdoodle.embed.mongo.config.IMongodConfig;
33 | import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
34 | import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
35 | import de.flapdoodle.embed.mongo.distribution.Version;
36 | import de.flapdoodle.embed.process.config.IRuntimeConfig;
37 | import de.flapdoodle.embed.process.config.store.IDownloadConfig;
38 | import org.junit.jupiter.api.AfterEach;
39 | import org.junit.jupiter.api.BeforeEach;
40 | import java.io.IOException;
41 |
42 | /**
43 | * Abstract class to be extended for running tests with Embedded MongoDB.
44 | * A knowledgeBase is created during setUp, which is backed up by a
45 | * real MongoDB instance.
46 | *
47 | * @author Fredrik Persson <fredrik6.persson@sonymobile.com>
48 | *
49 | */
50 | abstract class EmbeddedMongoTest {
51 |
52 | /**
53 | * KnowledgeBase to be used for testing.
54 | */
55 | protected KnowledgeBase knowledgeBase;
56 |
57 | private static final String LOCALHOST = "127.0.0.1";
58 | private static final String DB_NAME = "jenkinsbfa";
59 |
60 | private static final String mongoURL = System.getProperty(EmbeddedMongoTest.class.getName() + ".mongoURL");
61 |
62 | private MongodExecutable mongodExe = null;
63 | private MongodProcess mongodProc = null;
64 |
65 | /**
66 | * Sets up an instance of {@link MongoDBKnowledgeBase} backed up by a real MongoDB, to be used for testing.
67 | * @throws IOException if something goes wrong
68 | */
69 | @BeforeEach
70 | public void setUp() throws IOException {
71 | MongodStarter runtime;
72 | if (mongoURL != null) {
73 | // Use separate URL for fetching mongoDB artifacts.
74 | Command command = Command.MongoD;
75 | IDownloadConfig downloadConf =
76 | new DownloadConfigBuilder().defaultsForCommand(command).downloadPath(mongoURL).build();
77 | de.flapdoodle.embed.process.store.ExtractedArtifactStoreBuilder artifactStoreBuilder =
78 | new ExtractedArtifactStoreBuilder().defaults(command).download(downloadConf);
79 |
80 | IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
81 | .defaults(command)
82 | .artifactStore(artifactStoreBuilder)
83 | .build();
84 |
85 | runtime = MongodStarter.getInstance(runtimeConfig);
86 | } else {
87 | runtime = MongodStarter.getDefaultInstance();
88 | }
89 |
90 | IMongodConfig conf = new MongodConfigBuilder().version(Version.Main.V3_6).build();
91 | mongodExe = runtime.prepare(conf);
92 | mongodProc = mongodExe.start();
93 |
94 | int port = conf.net().getPort();
95 | knowledgeBase = new MongoDBKnowledgeBase(LOCALHOST, port, DB_NAME, null, null, true, false);
96 | }
97 |
98 | /**
99 | * Tears down the test environment.
100 | */
101 | @AfterEach
102 | public void tearDown() {
103 | if (this.mongodProc != null) {
104 | this.mongodProc.stop();
105 | this.mongodExe.stop();
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/test/java/com/sonyericsson/jenkins/plugins/bfa/test/utils/DifferentKnowledgeBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.sonyericsson.jenkins.plugins.bfa.test.utils;
26 |
27 | import com.sonyericsson.jenkins.plugins.bfa.db.KnowledgeBase;
28 | import com.sonyericsson.jenkins.plugins.bfa.db.LocalFileKnowledgeBase;
29 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
30 | import hudson.Extension;
31 | import hudson.model.Descriptor;
32 | import jenkins.model.Jenkins;
33 | import org.kohsuke.stapler.DataBoundConstructor;
34 |
35 | import java.util.List;
36 | import java.util.Objects;
37 | import java.util.UUID;
38 |
39 | import static hudson.Util.fixEmpty;
40 |
41 | /**
42 | * @author Robert Sandell <robert.sandell@sonyericsson.com>
43 | */
44 | public class DifferentKnowledgeBase extends LocalFileKnowledgeBase {
45 |
46 | private String someString;
47 |
48 | /**
49 | * Standard Databound constructor.
50 | *
51 | * @param someString the string.
52 | */
53 | @DataBoundConstructor
54 | public DifferentKnowledgeBase(String someString) {
55 | this.someString = someString;
56 | }
57 |
58 | /**
59 | * Standard constructor.
60 | *
61 | * @param initial the initial db, can be null.
62 | */
63 | public DifferentKnowledgeBase(List initial) {
64 | if (initial != null) {
65 | for (FailureCause c : initial) {
66 | if (fixEmpty(c.getId()) == null) {
67 | c.setId(UUID.randomUUID().toString());
68 | }
69 | put(c);
70 | }
71 | }
72 | }
73 |
74 | @Override
75 | public boolean equals(KnowledgeBase oldKnowledgeBase) {
76 | return super.equals(oldKnowledgeBase)
77 | && ((DifferentKnowledgeBase)oldKnowledgeBase).someString.equals(someString);
78 | }
79 |
80 | //CS IGNORE AvoidInlineConditionals FOR NEXT 29 LINES. REASON: Auto generated code.
81 |
82 | @Override
83 | public boolean equals(Object o) {
84 | if (this == o) {
85 | return true;
86 | }
87 | if (o == null || getClass() != o.getClass()) {
88 | return false;
89 | }
90 | if (!super.equals(o)) {
91 | return false;
92 | }
93 |
94 | DifferentKnowledgeBase that = (DifferentKnowledgeBase)o;
95 |
96 | return Objects.equals(someString, that.someString);
97 | }
98 |
99 | @Override
100 | public int hashCode() {
101 | //CS IGNORE MagicNumber FOR NEXT 3 LINES. REASON: Auto generated code.
102 | int result = super.hashCode();
103 | result = 31 * result + (someString != null ? someString.hashCode() : 0);
104 | return result;
105 | }
106 |
107 | /**
108 | * A configurable string.
109 | *
110 | * @return some string.
111 | */
112 | public String getSomeString() {
113 | return someString;
114 | }
115 |
116 | /**
117 | * A configurable string.
118 | *
119 | * @param someString some string.
120 | */
121 | public void setSomeString(String someString) {
122 | this.someString = someString;
123 | }
124 |
125 | @Override
126 | public Descriptor getDescriptor() {
127 | return Jenkins.get().getDescriptorByType(DifferentKnowledgeBaseDescriptor.class);
128 | }
129 |
130 | /**
131 | * Descriptor for {@link DifferentKnowledgeBase}.
132 | */
133 | @Extension
134 | public static class DifferentKnowledgeBaseDescriptor extends KnowledgeBaseDescriptor {
135 |
136 | @Override
137 | public String getDisplayName() {
138 | return "A Different One";
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/java/com/sonyericsson/jenkins/plugins/bfa/GerritMessageProviderExtension.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.sonyericsson.jenkins.plugins.bfa;
25 |
26 | import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.GerritMessageProvider;
27 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
28 | import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseDisplayData;
29 | import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
30 |
31 | import hudson.Extension;
32 | import hudson.model.Run;
33 | import jenkins.model.Jenkins;
34 |
35 | import java.util.List;
36 |
37 | /**
38 | * ExtensionPoint that allows BFA to send the failure cause description
39 | * directly to Gerrit.
40 | *
41 | * @author Gustaf Lundh <gustaf.lundh@sonymobile.com>
42 | */
43 | @Extension(optional = true)
44 | public class GerritMessageProviderExtension extends GerritMessageProvider {
45 |
46 | @Override
47 | public String getBuildCompletedMessage(Run build) {
48 | if (PluginImpl.getInstance().isGerritTriggerEnabled()) {
49 | StringBuilder customMessage = new StringBuilder();
50 | if (build != null) {
51 | FailureCauseBuildAction action = build.getAction(FailureCauseBuildAction.class);
52 | if (action != null) {
53 | FailureCauseDisplayData displayData = action.getFailureCauseDisplayData();
54 |
55 | addFailureCausesFromData(customMessage, displayData);
56 | printDownstream(customMessage, displayData.getDownstreamFailureCauses());
57 |
58 | if (customMessage.length() > 0) {
59 | return customMessage.toString().replace("'", "\"");
60 | }
61 | }
62 | }
63 | }
64 | return null;
65 | }
66 |
67 | /**
68 | *
69 | * Adds all causes from downstream builds in recursion
70 | *
71 | * @param message the StringBuilder to add to.
72 | * @param downstreamFailureCauses the list of downstream failures.
73 | */
74 | private void printDownstream(StringBuilder message, List downstreamFailureCauses) {
75 | if (!downstreamFailureCauses.isEmpty()) {
76 | for (FailureCauseDisplayData displayData : downstreamFailureCauses) {
77 | addFailureCausesFromData(message, displayData);
78 | printDownstream(message, displayData.getDownstreamFailureCauses());
79 | }
80 | }
81 | }
82 |
83 | /**
84 | * Appends FailureCause information to provided StringBuilder.
85 | *
86 | * @param message the StringBuilder to add to
87 | * @param displayData the data of downstream failures
88 | */
89 | private void addFailureCausesFromData(StringBuilder message, FailureCauseDisplayData displayData) {
90 | for (FoundFailureCause failureCause : displayData.getFoundFailureCauses()) {
91 | if (message.length() > 0) {
92 | message.append("\n\n");
93 | }
94 | message.append(failureCause.getDescription());
95 |
96 | message.append(" ( ")
97 | .append(Jenkins.getInstance().getRootUrl())
98 | .append(displayData.getLinks().getBuildUrl())
99 | .append(" )");
100 | }
101 |
102 | if (displayData.getDownstreamFailureCauses().isEmpty() && displayData.getFoundFailureCauses().isEmpty()) {
103 | if (message.length() > 0) {
104 | message.append("\n\n");
105 | }
106 |
107 | message.append(PluginImpl.getInstance().getNoCausesMessage())
108 | .append(" ( ")
109 | .append(Jenkins.getInstance().getRootUrl())
110 | .append(displayData.getLinks().getBuildUrl())
111 | .append(" )");
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------