├── .gitignore
├── .travis.yml
├── LICENSE
├── changelog.md
├── config
├── checkstyle-suppressions.xml
└── checkstyle.xml
├── docs
├── add-credentials.png
├── advanced.md
├── conduit-token.png
├── configure-credentials.png
├── configure-job-environment.png
├── configure-job-parameters.png
├── configure-job-post-build.png
├── custom-comment.png
├── custom-lint.png
├── example-path-haiku.png
├── harbormaster-plan.png
├── harbormaster-suspend-param.png
├── herald-rule.png
├── inline-haiku.png
├── jenkins-suspend-param.png
└── uberalls-integration.png
├── phabricator-plugin.iml
├── pom.xml
├── readme.md
└── src
├── main
├── java
│ └── com
│ │ └── uber
│ │ └── jenkins
│ │ └── phabricator
│ │ ├── BuildResultProcessor.java
│ │ ├── CommentBuilder.java
│ │ ├── ConduitCredentialsDescriptor.java
│ │ ├── LauncherFactory.java
│ │ ├── PhabricatorBuildWrapper.java
│ │ ├── PhabricatorBuildWrapperDescriptor.java
│ │ ├── PhabricatorCauseOfInterruption.java
│ │ ├── PhabricatorNotifier.java
│ │ ├── PhabricatorNotifierDescriptor.java
│ │ ├── PhabricatorPlugin.java
│ │ ├── PhabricatorPostbuildAction.java
│ │ ├── PhabricatorPostbuildSummaryAction.java
│ │ ├── RemoteFileFetcher.java
│ │ ├── conduit
│ │ ├── ArcanistClient.java
│ │ ├── ArcanistUsageException.java
│ │ ├── ConduitAPIClient.java
│ │ ├── ConduitAPIException.java
│ │ ├── Differential.java
│ │ ├── DifferentialClient.java
│ │ └── HarbormasterClient.java
│ │ ├── coverage
│ │ ├── CoberturaCoverageProvider.java
│ │ ├── CoberturaXMLParser.java
│ │ ├── CodeCoverageMetrics.java
│ │ ├── CoverageConverter.java
│ │ ├── CoverageProvider.java
│ │ └── PathResolver.java
│ │ ├── credentials
│ │ ├── ConduitCredentials.java
│ │ ├── ConduitCredentialsImpl.java
│ │ └── ConduitCredentialsNameProvider.java
│ │ ├── lint
│ │ ├── LintResult.java
│ │ └── LintResults.java
│ │ ├── provider
│ │ ├── BaseProvider.java
│ │ ├── InstanceProvider.java
│ │ └── Provider.java
│ │ ├── tasks
│ │ ├── ApplyPatchTask.java
│ │ ├── NonDifferentialBuildTask.java
│ │ ├── NonDifferentialHarbormasterTask.java
│ │ ├── PostCommentTask.java
│ │ ├── SendHarbormasterResultTask.java
│ │ ├── SendHarbormasterUriTask.java
│ │ └── Task.java
│ │ ├── uberalls
│ │ └── UberallsClient.java
│ │ ├── unit
│ │ ├── JUnitTestProvider.java
│ │ ├── UnitResult.java
│ │ ├── UnitResults.java
│ │ └── UnitTestProvider.java
│ │ └── utils
│ │ ├── CommonUtils.java
│ │ └── Logger.java
├── resources
│ ├── com
│ │ └── uber
│ │ │ └── jenkins
│ │ │ └── phabricator
│ │ │ ├── PhabricatorBuildWrapper
│ │ │ ├── config.jelly
│ │ │ └── global.jelly
│ │ │ ├── PhabricatorNotifier
│ │ │ ├── config.jelly
│ │ │ ├── global.jelly
│ │ │ └── help-conduitURL.html
│ │ │ ├── PhabricatorPostbuildAction
│ │ │ └── badge.jelly
│ │ │ ├── PhabricatorPostbuildSummaryAction
│ │ │ └── summary.jelly
│ │ │ └── credentials
│ │ │ └── ConduitCredentialsImpl
│ │ │ ├── config.jelly
│ │ │ └── help-gateway.html
│ └── index.jelly
└── webapp
│ └── images
│ └── phabricator.png
└── test
├── java
└── com
│ └── uber
│ └── jenkins
│ └── phabricator
│ ├── BuildIntegrationTest.java
│ ├── BuildResultProcessorTest.java
│ ├── CommentBuilderTest.java
│ ├── FakeConduit.java
│ ├── LauncherFactoryTest.java
│ ├── PhabricatorBuildWrapperTest.java
│ ├── PhabricatorNotifierTest.java
│ ├── PhabricatorPostbuildActionTest.java
│ ├── RemoteFileFetcherTest.java
│ ├── conduit
│ ├── ArcanistClientTest.java
│ ├── ConduitAPIClientTest.java
│ ├── DifferentialClientTest.java
│ └── DifferentialTest.java
│ ├── coverage
│ ├── CoberturaCoverageProviderTest.java
│ ├── CoberturaXMLParserTest.java
│ ├── FakeCoverageProvider.java
│ └── PathResolverTest.java
│ ├── credentials
│ └── ConduitCredentialsImplTest.java
│ ├── provider
│ ├── BaseProviderTest.java
│ └── InstanceProviderTest.java
│ ├── tasks
│ ├── ApplyPatchTaskTest.java
│ ├── NonDifferentialBuildTaskTest.java
│ ├── NonDifferentialHarbormasterTaskTest.java
│ ├── PostCommentTaskTest.java
│ ├── SendHarbormasterResultTaskTest.java
│ └── SendHarbormasterUriTaskTest.java
│ ├── uberalls
│ └── UberallsClientTest.java
│ ├── unit
│ ├── JUnitTestProviderTest.java
│ ├── UnitResultTest.java
│ └── UnitResultsTest.java
│ └── utils
│ ├── CommonUtilsTest.java
│ ├── LoggerTest.java
│ └── TestUtils.java
└── resources
└── com
└── uber
└── jenkins
└── phabricator
├── conduit
├── ResponseWithChanges.json
├── fetchDiffResponseMissingDiff.json
├── fetchDiffWithResponseArray.json
├── missingAuthorResponse.json
├── unitResultWithFailureRequest.json
├── validDifferentialQueryResponse.json
└── validFetchDiffResponse.json
├── coverage
├── go-torch-coverage.xml
├── go-torch-coverage1.xml
├── go-torch-coverage2.xml
├── go-torch-coverage3.xml
├── go-torch-coverage_overwrite.xml
└── python-coverage.xml
├── uberalls
└── validCoverage.json
└── unit
├── go-torch-junit-fail.xml
└── go-torch-junit.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | work/
2 | target/
3 | .idea
4 | .DS_Store
5 | *.iml
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: java
3 | sudo: true
4 |
5 | matrix:
6 | fast_finish: true
7 | include:
8 | - jdk: openjdk7
9 | env: MAIN_ARGS="test"
10 | - jdk: oraclejdk7
11 | env: MAIN_ARGS="test"
12 | - jdk: oraclejdk8
13 | env: MAIN_ARGS="cobertura:cobertura coveralls:report"
14 |
15 | script:
16 | - mvn clean $MAIN_ARGS
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Uber
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ### 1.9.8 (2016/08/26)
4 |
5 | * Abort existing builds when a new build referencing same diff is scheduled (Gautam Korlam)
6 | * Add a gateway option - used as an override to url in Conduit credentials
7 |
8 | ### 1.9.7 (2016/08/09)
9 |
10 | * Report lint warnings from file (Anup Talwalkar)
11 | * Add "details" to unit results from "failure" in JUnit files (Haotian Liu)
12 | * Soften error message on URI artifact to prevent confusion about build failures
13 |
14 | ### 1.9.6 (2016/07/17)
15 |
16 | * Fix incorrect line coverage when merging multiple cobertura reports
17 |
18 | ### 1.9.5 (2016/05/02)
19 |
20 | * Use filenames to compute set of files to publish line coverage
21 |
22 | ### 1.9.4 (2016/04/28)
23 |
24 | * Publish inline coverage data only for changed files in the diff
25 | * Cleanup coverage files on jenkins master to save disk space
26 |
27 | ### 1.9.3 (2016/04/1)
28 |
29 | * Remove deprecated "Build started" comments in favor of Harbormaster
30 |
31 | ### 1.9.2 (2016/03/10)
32 |
33 | * Fix Harbormaster coverage filename/path detection for Python's coverage>=4.0.3
34 | * Add differential variables to environment, display differential summary on build
35 | summary view
36 | * Send build URL to Harbormaster when build starts (Chaitanya Pramod)
37 |
38 | ### 1.9.1 (2016/01/25)
39 |
40 | * Remove coverage dependency on cobertura build action. Allows Uberalls coverage
41 | to work when the cobertura plugin is not enabled (for performance
42 | reasons). (Gautam Korlam)
43 | * Improve readme (Brody Klapko)
44 | * Search for coverage files recursively when Cobertura publisher is disabled
45 | (Gautam Korlam)
46 |
47 | ### 1.9.0 (2016/01/19)
48 |
49 | * Add more logging on differential fetch failure
50 | * Allow user to apply patch with force flag (Chaitanya Pramod)
51 | * Fix crash when missing cobertura plugin
52 | * Send Harbormaster status on non-Differential commits
53 |
54 | ### 1.8.3 (2015/12/09)
55 |
56 | * JENKINS-31335: Add checkbox to skip git clean step (Alexander Yerenkow)
57 | * Add option to create branch when applying diff (cellscape)
58 | * Collapse comment checkboxes when disabled (Gautam Korlam)
59 |
60 | ### 1.8.2 (2015/11/01)
61 |
62 | * Fix "comment size" option not being saved
63 | * Support merging multiple Cobertura coverage files, and fix source root
64 | detection (Gautam Korlam)
65 |
66 | ### 1.8.1 (2015/09/22)
67 |
68 | * Don't require Uberalls to be enabled to post coverage data to Harbormaster
69 | * Handle UTF-8 strings properly in comment file
70 |
71 | ### 1.8.0 (2015/09/09)
72 |
73 | * Qualify log statements with "phabricator:"
74 | * Send a Harbormaster URI Artifacts for the Jenkins build (Chris Burroughs)
75 | * Clean up internal Harbormaster API
76 | * Make the Cobertura plugin an optional dependency (only used for Uberalls)
77 | * Consistently set defaults for notifiers (Chris Burroughs)
78 | * Increase unit test coverage to >85%
79 | * Gracefully ignore missing author names/emails from conduit for summary badge
80 | * Report Cobertura coverage data to Harbormaster API
81 | * Add option to preserve formatting in additional comments (Gautam Korlam)
82 | * Report XUnit results to Harbormaster
83 |
84 | ### 1.7.2 (2015/08/13)
85 |
86 | * Fix HTML escaping on build summary view (regression from auto-escape in 1.7.1)
87 |
88 | ### 1.7.1 (2015/08/13)
89 |
90 | * Fix class loading error in Apache HTTP client
91 | * Bump minimum required Jenkins version to 1.609.2 (from 1.609) so that class exclusions work for above fix
92 | * Add escape-by-default to Jelly templates
93 | * Re-enable Javadoc step
94 |
95 | ### 1.7 (2015/08/12)
96 |
97 | * Conduit token and Phabricator URL are now configured via the [Credentials plugin](https://wiki.jenkins-ci.org/display/JENKINS/Credentials+Plugin)
98 | * Harbormaster messages are now sent over conduit (no more `arc` dependency)
99 | * Removed deprecated "uber-dot-arcanist" functionality
100 | * Removed unused JNA and trove4j dependencies
101 | * Various bugfixes
102 | * Major refactoring and testing
103 |
104 | ### 1.6.1 (2015/06/15)
105 |
106 | * Update wiki path for plugin
107 |
108 | ### 1.6 (2015/06/14)
109 |
110 | * Rename plugin from "Phabricator Plugin" to "Phabricator Differential Plugin"
111 | * Add checkbox to control "Build Started" comments being posted to Phabricator
112 |
113 | ### 1.5 (2015/06/09)
114 |
115 | * Handle invalid responses from conduit
116 |
--------------------------------------------------------------------------------
/config/checkstyle-suppressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
10 |
11 |
--------------------------------------------------------------------------------
/config/checkstyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
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 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/docs/add-credentials.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/add-credentials.png
--------------------------------------------------------------------------------
/docs/advanced.md:
--------------------------------------------------------------------------------
1 | Advanced Usage
2 | ==============
3 |
4 | In addition to Unit and Coverage results, this plugin supports two additional features
5 | you may want to take use of. Both options take a maximum number of bytes to copy, since the plugin
6 | is executed on the Jenkins master and syncing multiple megabytes of data can cause
7 | performance problems.
8 |
9 | Custom Comments
10 | ---------------
11 |
12 | If you'd like to post additional text back to Phabricator, you can add text to the `.phabricator-comment` file
13 | (you can change the name of the file in your job configuration page):
14 |
15 | 
16 |
17 | Any text present in this file will be echoed verbatim to the comment that Jenkins posts back to
18 | Phabricator. If you'd like to preserve formatting, check the "Preserve Formatting" block and the
19 | plugin will surround the comment in triple-backticks (```)
20 |
21 | Custom Lint
22 | -----------
23 |
24 | If you'd like to send Lint Violations as well, you can echo Harbormaster-compatible JSON
25 | (where each line is a valid JSON dictionary) into the `.phabricator-lint` file.
26 |
27 | Although each **line** must be valid JSON, note that the file as a whole is **not valid JSON**
28 | (e.g. if you call `JSON.parse('.phabricator-lint')`) it will fail. This is a design decision to
29 | make it easy for build scripts to `tee` (echo line-by-line) violations without having to
30 | produce well-formed JSON, which requires knowing upfront how many violations are present.
31 |
32 | 
33 |
34 | If a job was configured to run the following shell script:
35 |
36 | ```bash
37 | mkdir example
38 | echo "Once upon a time\nThere was a Jenkins plugin" > example/path
39 | # NOTE: tee -a to support appending multiple lints
40 | echo '{"name": "Comment Name", "code": "Haiku", "severity": "error", "path": "example/path", "line": 2, "char": 0, "description": "Line is not a Haiku" }' | tee -a .phabricator-lint
41 | ```
42 |
43 | You would see the following in your differential at the top:
44 |
45 | 
46 |
47 | And the following in the code view:
48 |
49 | 
50 |
51 | See [Harbormaster Lint](https://secure.phabricator.com/conduit/method/harbormaster.sendmessage/)
52 | API for details on the supported JSON keys. `line`, `char`, and `description` are all optional.
53 | The rest are required.
54 |
55 | The severity parameter recognizes these severity levels:
56 |
57 | | Key | Name |
58 | |----------|----------|
59 | | advice | Advice |
60 | | autofix | Auto-Fix |
61 | | warning | Warning |
62 | | error | Error |
63 | | disabled | Disabled |
64 |
65 | Suspend Useless Jobs
66 | ---------------------
67 |
68 | When new builds are triggered from Phabricator due to new changes to the same diff or
69 | rebuilding via harbormaster, it may be desirable to suspend existing jobs that were triggered
70 | for the same diff. This can be done by adding the `ABORT_ON_REVISION_ID` string parameter to your job.
71 |
72 | 
73 |
74 | You need to also add the parameter to your harbormaster request
75 | 
76 |
77 | This makes the latest build triggered for a diff automatically abort the existing running builds
78 | for the same diff on the job. Jobs aborted this way will skip notifying phabricator to
79 | avoid confusion. Please note that builds on the same diff triggered by the same upstream build will not be aborted this way. This can be useful when running multi-configuration jobs and parallel builds that run on the same diff.
80 |
81 | Also note that if you pass additional arguments to your harbormaster request they may need to be included in the `ABORT_ON_REVISION_ID` field as well. A good example is when you use the same CI job to build multiple targets on a single diff. So for example, if the jenkins request params have
82 | `TARGET=some_target`, then to ensure other targets are not cancelled for the same diff, you may want to set `ABORT_ON_REVISION_ID=some_target_${buildable.revision}`.
83 |
--------------------------------------------------------------------------------
/docs/conduit-token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/conduit-token.png
--------------------------------------------------------------------------------
/docs/configure-credentials.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/configure-credentials.png
--------------------------------------------------------------------------------
/docs/configure-job-environment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/configure-job-environment.png
--------------------------------------------------------------------------------
/docs/configure-job-parameters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/configure-job-parameters.png
--------------------------------------------------------------------------------
/docs/configure-job-post-build.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/configure-job-post-build.png
--------------------------------------------------------------------------------
/docs/custom-comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/custom-comment.png
--------------------------------------------------------------------------------
/docs/custom-lint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/custom-lint.png
--------------------------------------------------------------------------------
/docs/example-path-haiku.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/example-path-haiku.png
--------------------------------------------------------------------------------
/docs/harbormaster-plan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/harbormaster-plan.png
--------------------------------------------------------------------------------
/docs/harbormaster-suspend-param.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/harbormaster-suspend-param.png
--------------------------------------------------------------------------------
/docs/herald-rule.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/herald-rule.png
--------------------------------------------------------------------------------
/docs/inline-haiku.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/inline-haiku.png
--------------------------------------------------------------------------------
/docs/jenkins-suspend-param.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/jenkins-suspend-param.png
--------------------------------------------------------------------------------
/docs/uberalls-integration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/phabricator-plugin/00e0e549f9456fef3ea9a737197a62265e8c336f/docs/uberalls-integration.png
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/ConduitCredentialsDescriptor.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator;
22 |
23 | import com.cloudbees.plugins.credentials.CredentialsMatcher;
24 | import com.cloudbees.plugins.credentials.CredentialsMatchers;
25 | import com.cloudbees.plugins.credentials.CredentialsProvider;
26 | import com.cloudbees.plugins.credentials.common.StandardCredentials;
27 | import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
28 | import com.cloudbees.plugins.credentials.domains.DomainRequirement;
29 | import com.uber.jenkins.phabricator.credentials.ConduitCredentials;
30 | import hudson.model.Item;
31 | import hudson.model.Job;
32 | import hudson.security.ACL;
33 | import hudson.util.ListBoxModel;
34 | import jenkins.model.Jenkins;
35 | import org.kohsuke.stapler.AncestorInPath;
36 |
37 | import java.util.ArrayList;
38 | import java.util.List;
39 |
40 | public class ConduitCredentialsDescriptor {
41 | private static List availableCredentials(Job owner) {
42 | return CredentialsProvider.lookupCredentials(
43 | ConduitCredentials.class,
44 | owner,
45 | null,
46 | new ArrayList()
47 | );
48 | }
49 |
50 | public static ConduitCredentials getCredentials(Job owner, String credentialsID) {
51 | List available = availableCredentials(owner);
52 | if (available.size() == 0) {
53 | return null;
54 | }
55 | CredentialsMatcher matcher;
56 | if (credentialsID != null) {
57 | matcher = CredentialsMatchers.allOf(CredentialsMatchers.withId(credentialsID));
58 | } else {
59 | matcher = CredentialsMatchers.always();
60 | }
61 | return CredentialsMatchers.firstOrDefault(
62 | available,
63 | matcher,
64 | available.get(0)
65 | );
66 | }
67 |
68 | public static ListBoxModel doFillCredentialsIDItems(@AncestorInPath Jenkins context) {
69 | if (context == null || !context.hasPermission(Item.CONFIGURE)) {
70 | return new StandardListBoxModel();
71 | }
72 |
73 | List domainRequirements = new ArrayList();
74 | return new StandardListBoxModel()
75 | .withEmptySelection()
76 | .withMatching(
77 | CredentialsMatchers.anyOf(
78 | CredentialsMatchers.instanceOf(ConduitCredentials.class)),
79 | CredentialsProvider.lookupCredentials(
80 | StandardCredentials.class,
81 | context,
82 | ACL.SYSTEM,
83 | domainRequirements));
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/LauncherFactory.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator;
22 |
23 | import hudson.EnvVars;
24 | import hudson.FilePath;
25 | import hudson.Launcher;
26 |
27 | import java.io.PrintStream;
28 |
29 | public class LauncherFactory {
30 | private final Launcher launcher;
31 | private final PrintStream stderr;
32 | private final EnvVars environment;
33 | private final FilePath pwd;
34 |
35 | public LauncherFactory(Launcher launcher, EnvVars environment, PrintStream stderr, FilePath pwd) {
36 | this.launcher = launcher;
37 | this.environment = environment;
38 | this.stderr = stderr;
39 | this.pwd = pwd;
40 | }
41 |
42 | public PrintStream getStderr() {
43 | return this.stderr;
44 | }
45 |
46 | /**
47 | * Create a launcher
48 | * @return a launcher suitable for executing programs within Jenkins
49 | */
50 | public Launcher.ProcStarter launch() {
51 | return launcher.launch().envs(environment).stderr(stderr).pwd(pwd);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/PhabricatorBuildWrapperDescriptor.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator;
22 |
23 | import com.uber.jenkins.phabricator.credentials.ConduitCredentials;
24 | import hudson.Extension;
25 | import hudson.model.AbstractProject;
26 | import hudson.model.Job;
27 | import hudson.tasks.BuildWrapperDescriptor;
28 | import hudson.util.ListBoxModel;
29 | import jenkins.model.Jenkins;
30 | import net.sf.json.JSONObject;
31 | import org.kohsuke.stapler.AncestorInPath;
32 | import org.kohsuke.stapler.QueryParameter;
33 | import org.kohsuke.stapler.StaplerRequest;
34 |
35 | @SuppressWarnings("UnusedDeclaration")
36 | @Extension
37 | public final class PhabricatorBuildWrapperDescriptor extends BuildWrapperDescriptor {
38 | private String credentialsID;
39 | private String arcPath;
40 |
41 | public PhabricatorBuildWrapperDescriptor() {
42 | super(PhabricatorBuildWrapper.class);
43 | load();
44 | }
45 |
46 | @Override
47 | public boolean isApplicable(AbstractProject, ?> abstractProject) {
48 | return true;
49 | }
50 |
51 | /**
52 | * This human readable name is used in the configuration screen.
53 | */
54 | public String getDisplayName() {
55 | return "Apply Phabricator Differential";
56 | }
57 |
58 | @SuppressWarnings("unused")
59 | public ListBoxModel doFillCredentialsIDItems(@AncestorInPath Jenkins context,
60 | @QueryParameter String remoteBase) {
61 | return ConduitCredentialsDescriptor.doFillCredentialsIDItems(
62 | context);
63 | }
64 |
65 | public ConduitCredentials getCredentials(Job owner) {
66 | return ConduitCredentialsDescriptor.getCredentials(owner, credentialsID);
67 | }
68 |
69 | @Override
70 | public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
71 | // To persist global configuration information,
72 | // set that to properties and call save().
73 | req.bindJSON(this, formData.getJSONObject("phabricator"));
74 | save();
75 | return super.configure(req,formData);
76 | }
77 |
78 | public String getCredentialsID() {
79 | return credentialsID;
80 | }
81 |
82 | public void setCredentialsID(String credentialsID) {
83 | this.credentialsID = credentialsID;
84 | }
85 |
86 | public String getArcPath() {
87 | return arcPath;
88 | }
89 |
90 | public void setArcPath(String arcPath) {
91 | this.arcPath = arcPath;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/PhabricatorCauseOfInterruption.java:
--------------------------------------------------------------------------------
1 | package com.uber.jenkins.phabricator;
2 |
3 | import jenkins.model.CauseOfInterruption;
4 |
5 | public final class PhabricatorCauseOfInterruption extends CauseOfInterruption {
6 | private final String buildUrl;
7 |
8 | PhabricatorCauseOfInterruption(String buildUrl) {
9 | this.buildUrl = buildUrl;
10 | }
11 |
12 | @Override
13 | public String getShortDescription() {
14 | return String.format("Aborted by %s", buildUrl);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/PhabricatorNotifierDescriptor.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator;
22 |
23 | import com.uber.jenkins.phabricator.credentials.ConduitCredentials;
24 | import com.uber.jenkins.phabricator.utils.CommonUtils;
25 | import hudson.Extension;
26 | import hudson.model.AbstractProject;
27 | import hudson.model.Job;
28 | import hudson.tasks.BuildStepDescriptor;
29 | import hudson.tasks.Publisher;
30 | import hudson.util.ListBoxModel;
31 | import jenkins.model.Jenkins;
32 | import net.sf.json.JSONObject;
33 | import org.kohsuke.stapler.AncestorInPath;
34 | import org.kohsuke.stapler.QueryParameter;
35 | import org.kohsuke.stapler.StaplerRequest;
36 |
37 | /**
38 | * Descriptor for {@link PhabricatorNotifier}. Used as a singleton.
39 | * The class is marked as public so that it can be accessed from views.
40 | *
41 | *
42 | * See src/main/resources/hudson/plugins/hello_world/PhabricatorNotifier/*.jelly
43 | * for the actual HTML fragment for the configuration screen.
44 | */
45 | @SuppressWarnings("UnusedDeclaration")
46 | @Extension
47 | public final class PhabricatorNotifierDescriptor extends BuildStepDescriptor {
48 | private String credentialsID;
49 | private String uberallsURL;
50 |
51 | public PhabricatorNotifierDescriptor() {
52 | super(PhabricatorNotifier.class);
53 | load();
54 | }
55 |
56 | public boolean isApplicable(Class extends AbstractProject> aClass) {
57 | // Indicates that this builder can be used with all kinds of project types
58 | return true;
59 | }
60 |
61 | /**
62 | * This human readable name is used in the configuration screen.
63 | */
64 | public String getDisplayName() {
65 | return "Post to Phabricator";
66 | }
67 |
68 | @SuppressWarnings("unused")
69 | public ListBoxModel doFillCredentialsIDItems(@AncestorInPath Jenkins context,
70 | @QueryParameter String remoteBase) {
71 | return ConduitCredentialsDescriptor.doFillCredentialsIDItems(
72 | context);
73 | }
74 |
75 | public ConduitCredentials getCredentials(Job owner) {
76 | return ConduitCredentialsDescriptor.getCredentials(owner, credentialsID);
77 | }
78 |
79 | @Override
80 | public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
81 | // To persist global configuration information,
82 | // set that to properties and call save().
83 | req.bindJSON(this, formData.getJSONObject("uberalls"));
84 | save();
85 | return super.configure(req, formData);
86 | }
87 |
88 | public String getCredentialsID() {
89 | return credentialsID;
90 | }
91 |
92 | public void setCredentialsID(String credentialsID) {
93 | this.credentialsID = credentialsID;
94 | }
95 |
96 | public String getUberallsURL() {
97 | if (!CommonUtils.isBlank(uberallsURL)) {
98 | return uberallsURL;
99 | }
100 | return null;
101 | }
102 |
103 | public void setUberallsURL(String value) {
104 | uberallsURL = value;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/PhabricatorPlugin.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator;
22 |
23 | import hudson.Plugin;
24 | import hudson.PluginWrapper;
25 | import jenkins.model.Jenkins;
26 |
27 | import java.io.File;
28 |
29 | public class PhabricatorPlugin extends Plugin {
30 | // Diff ID (not differential ID)
31 | public static final String DIFFERENTIAL_ID_FIELD = "DIFF_ID";
32 | // Phabricator object ID (for Harbormaster)
33 | public static final String PHID_FIELD = "PHID";
34 | // Revision ID (to abort old running jobs)
35 | public static final String ABORT_ON_REVISION_ID_FIELD = "ABORT_ON_REVISION_ID";
36 |
37 | public static String getIconPath(String icon) {
38 | if (icon == null) {
39 | return null;
40 | }
41 | if (icon.startsWith("/")) {
42 | return icon;
43 | }
44 |
45 | // Try plugin images dir, fallback to Hudson images dir
46 | PluginWrapper wrapper = Jenkins.getInstance().getPluginManager().getPlugin(PhabricatorPlugin.class);
47 |
48 | boolean pluginIconExists = (wrapper != null) && new File(wrapper.baseResourceURL.getPath() + "/images/" + icon).exists();
49 | return pluginIconExists ? "/plugin/" + wrapper.getShortName() + "/images/" + icon : Jenkins.RESOURCE_PATH + "/images/16x16/" + icon;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/PhabricatorPostbuildAction.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator;
22 |
23 | import hudson.model.BuildBadgeAction;
24 | import org.kohsuke.stapler.export.Exported;
25 |
26 | /**
27 | * Ripped from https://github.com/jenkinsci/groovy-postbuild-plugin/blob/master/src/main/java/org/jvnet/hudson/plugins/groovypostbuild/GroovyPostbuildAction.java
28 | */
29 | public class PhabricatorPostbuildAction implements BuildBadgeAction {
30 | private final String iconPath;
31 | private final String text;
32 | private final String color = "#1FBAD6";
33 | private final String background = "transparent";
34 | private final String border = "0";
35 | private final String borderColor = "transparent";
36 | private final String link;
37 |
38 | private PhabricatorPostbuildAction(String text, String link) {
39 | this.iconPath = null;
40 | this.text = text;
41 | this.link = link;
42 | }
43 |
44 | public static PhabricatorPostbuildAction createShortText(String text, String link) {
45 | return new PhabricatorPostbuildAction(text, link);
46 | }
47 |
48 | /* Action methods */
49 | public String getUrlName() {
50 | return "";
51 | }
52 |
53 | public String getDisplayName() {
54 | return "";
55 | }
56 |
57 | public String getIconFileName() {
58 | return null;
59 | }
60 |
61 | @Exported public boolean isTextOnly() {
62 | return (iconPath == null);
63 | }
64 |
65 | @Exported public String getIconPath() {
66 | return iconPath;
67 | }
68 |
69 | @Exported public String getText() {
70 | return text;
71 | }
72 |
73 | @Exported public String getColor() {
74 | return color;
75 | }
76 |
77 | @Exported public String getBackground() {
78 | return background;
79 | }
80 |
81 | @Exported public String getBorder() {
82 | return border;
83 | }
84 |
85 | @Exported public String getBorderColor() {
86 | return borderColor;
87 | }
88 |
89 | @Exported public String getLink() {
90 | return link;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/PhabricatorPostbuildSummaryAction.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator;
22 |
23 | import hudson.model.Action;
24 | import org.kohsuke.stapler.export.Exported;
25 | import org.kohsuke.stapler.export.ExportedBean;
26 |
27 | /**
28 | * Ripped from https://github.com/jenkinsci/groovy-postbuild-plugin/blob/master/src/main/java/org/jvnet/hudson/plugins/groovypostbuild/GroovyPostbuildSummaryAction.java
29 | */
30 | @ExportedBean(defaultVisibility = 2)
31 | public class PhabricatorPostbuildSummaryAction implements Action {
32 | private final String iconPath;
33 | private final String url;
34 | private final String revisionID;
35 | private final String authorName;
36 | private final String authorEmail;
37 | private final String commitMessage;
38 |
39 | public PhabricatorPostbuildSummaryAction(String iconPath, String phabricatorLink, String revisionID,
40 | String authorName, String authorEmail, String commitMessage) {
41 | this.iconPath = iconPath;
42 | this.url = phabricatorLink;
43 | this.revisionID = revisionID;
44 | this.authorName = authorName;
45 | this.authorEmail = authorEmail;
46 | this.commitMessage = commitMessage;
47 | }
48 |
49 | /* Action methods */
50 | public String getUrlName() {
51 | return "";
52 | }
53 |
54 | public String getDisplayName() {
55 | return "";
56 | }
57 |
58 | public String getIconFileName() {
59 | return null;
60 | }
61 |
62 | @Exported public String getIconPath() {
63 | return PhabricatorPlugin.getIconPath(iconPath);
64 | }
65 |
66 | @Exported public String getUrl() {
67 | return url;
68 | }
69 |
70 | @Exported public String getRevisionID() {
71 | return revisionID;
72 | }
73 |
74 | @Exported public String getAuthorName() {
75 | return authorName;
76 | }
77 |
78 | @Exported public String getAuthorEmail() {
79 | return authorEmail;
80 | }
81 |
82 | @Exported public String getCommitMessage() {
83 | return commitMessage;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/RemoteFileFetcher.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator;
22 |
23 | import com.uber.jenkins.phabricator.utils.CommonUtils;
24 | import com.uber.jenkins.phabricator.utils.Logger;
25 | import hudson.FilePath;
26 |
27 | import java.io.IOException;
28 |
29 | import static java.lang.Integer.parseInt;
30 |
31 | public class RemoteFileFetcher {
32 | private static final int DEFAULT_MAX_SIZE = 1000;
33 | private static final String LOGGER_TAG = "file-fetcher";
34 |
35 | private final FilePath workspace;
36 | private final Logger logger;
37 | private final String fileName;
38 | private final String maxSize;
39 |
40 | public RemoteFileFetcher(FilePath workspace, Logger logger, String fileName, String maxSize) {
41 | this.workspace = workspace;
42 | this.logger = logger;
43 | this.fileName = fileName;
44 | this.maxSize = maxSize;
45 | }
46 |
47 | /**
48 | * Attempt to read a remote file
49 | * @return the content of the remote comment file, if present
50 | * @throws InterruptedException if there is an error fetching the file
51 | * @throws IOException if any network error occurs
52 | */
53 | public String getRemoteFile() throws InterruptedException, IOException {
54 | if (CommonUtils.isBlank(fileName)) {
55 | logger.info(LOGGER_TAG, "no file configured");
56 | return null;
57 | }
58 |
59 | FilePath[] src = workspace.list(fileName);
60 | if (src.length == 0) {
61 | logger.info(LOGGER_TAG, "no files found by path: '" + fileName + "'");
62 | return null;
63 | }
64 | if (src.length > 1) {
65 | logger.info(LOGGER_TAG, "Found multiple matches. Reading first only.");
66 | }
67 |
68 | FilePath source = src[0];
69 |
70 | int maxLength = DEFAULT_MAX_SIZE;
71 | if (!CommonUtils.isBlank(maxSize)) {
72 | maxLength = parseInt(maxSize, 10);
73 | }
74 | if (source.length() < maxLength) {
75 | maxLength = (int)source.length();
76 | }
77 | byte[] buffer = new byte[maxLength];
78 | source.read().read(buffer, 0, maxLength);
79 |
80 | return new String(buffer);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/conduit/ArcanistClient.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.conduit;
22 |
23 | import com.uber.jenkins.phabricator.utils.CommonUtils;
24 | import hudson.Launcher;
25 | import hudson.util.ArgumentListBuilder;
26 |
27 | import java.io.IOException;
28 | import java.io.PrintStream;
29 |
30 | public class ArcanistClient {
31 | private final String arcPath;
32 | private final String methodName;
33 | private final String conduitToken;
34 | private final String[] arguments;
35 |
36 | public ArcanistClient(String arcPath, String methodName, String conduitToken, String... arguments) {
37 | this.arcPath = arcPath;
38 | this.methodName = methodName;
39 | this.conduitToken = conduitToken;
40 | this.arguments = arguments;
41 | }
42 |
43 | private ArgumentListBuilder getConduitCommand() {
44 | ArgumentListBuilder builder = new ArgumentListBuilder(this.arcPath, this.methodName);
45 | builder.add(arguments);
46 |
47 | if (!CommonUtils.isBlank(this.conduitToken)) {
48 | builder.addMasked("--conduit-token=" + this.conduitToken);
49 | }
50 | return builder;
51 | }
52 |
53 | private Launcher.ProcStarter getCommand(Launcher.ProcStarter starter) throws IOException {
54 | return starter.cmds(this.getConduitCommand());
55 | }
56 |
57 | public int callConduit(Launcher.ProcStarter starter, PrintStream stderr) throws IOException, InterruptedException {
58 | Launcher.ProcStarter command = this.getCommand(starter);
59 | return command.stdout(stderr).stderr(stderr).join();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/conduit/ArcanistUsageException.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.conduit;
22 |
23 | class ArcanistUsageException extends Exception {
24 | public ArcanistUsageException(String message) {
25 | super(message);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/conduit/ConduitAPIClient.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.conduit;
22 |
23 | import net.sf.json.JSONObject;
24 | import net.sf.json.groovy.JsonSlurper;
25 | import org.apache.commons.httpclient.HttpStatus;
26 | import org.apache.http.HttpResponse;
27 | import org.apache.http.NameValuePair;
28 | import org.apache.http.client.ClientProtocolException;
29 | import org.apache.http.client.entity.UrlEncodedFormEntity;
30 | import org.apache.http.client.methods.HttpPost;
31 | import org.apache.http.client.methods.HttpUriRequest;
32 | import org.apache.http.impl.client.CloseableHttpClient;
33 | import org.apache.http.impl.client.HttpClientBuilder;
34 | import org.apache.http.message.BasicNameValuePair;
35 |
36 | import java.io.IOException;
37 | import java.io.InputStream;
38 | import java.io.UnsupportedEncodingException;
39 | import java.net.MalformedURLException;
40 | import java.net.URISyntaxException;
41 | import java.net.URL;
42 | import java.util.ArrayList;
43 | import java.util.List;
44 |
45 | public class ConduitAPIClient {
46 | private static final String API_TOKEN_KEY = "token";
47 | private static final String CONDUIT_METADATA_KEY = "__conduit__";
48 |
49 | private final String conduitURL;
50 | private final String conduitToken;
51 |
52 | public ConduitAPIClient(String conduitURL, String conduitToken) {
53 | this.conduitURL = conduitURL;
54 | this.conduitToken = conduitToken;
55 | }
56 |
57 | /**
58 | * Call the conduit API of Phabricator
59 | * @param action Name of the API call
60 | * @param params The data to send to Harbormaster
61 | * @return The result as a JSONObject
62 | * @throws IOException If there was a problem reading the response
63 | * @throws ConduitAPIException If there was an error calling conduit
64 | */
65 | public JSONObject perform(String action, JSONObject params) throws IOException, ConduitAPIException {
66 | CloseableHttpClient client = HttpClientBuilder.create().build();
67 | HttpUriRequest request = createRequest(action, params);
68 |
69 | HttpResponse response;
70 | try {
71 | response = client.execute(request);
72 | } catch (ClientProtocolException e) {
73 | throw new ConduitAPIException(e.getMessage());
74 | }
75 |
76 | InputStream responseBody = response.getEntity().getContent();
77 |
78 | if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
79 | throw new ConduitAPIException(responseBody.toString(), response.getStatusLine().getStatusCode());
80 | }
81 |
82 | JsonSlurper jsonParser = new JsonSlurper();
83 | return (JSONObject)jsonParser.parse(responseBody);
84 | }
85 |
86 | /**
87 | * Post a URL-encoded "params" key with a JSON-encoded body as per the Conduit API
88 | * @param action The name of the Conduit method
89 | * @param params The data to be sent to the Conduit method
90 | * @return The request to perform
91 | * @throws UnsupportedEncodingException when the POST data can't be encoded
92 | * @throws ConduitAPIException when the conduit URL is misconfigured
93 | */
94 | public HttpUriRequest createRequest(String action, JSONObject params) throws UnsupportedEncodingException, ConduitAPIException {
95 | HttpPost post;
96 | try {
97 | post = new HttpPost(
98 | new URL(new URL(new URL(conduitURL), "/api/"), action).toURI()
99 | );
100 | } catch (MalformedURLException e) {
101 | throw new ConduitAPIException(e.getMessage());
102 | } catch (URISyntaxException e) {
103 | throw new ConduitAPIException(e.getMessage());
104 | }
105 |
106 | JSONObject conduitParams = new JSONObject();
107 | conduitParams.put(API_TOKEN_KEY, conduitToken);
108 | params.put(CONDUIT_METADATA_KEY, conduitParams);
109 |
110 | List formData = new ArrayList();
111 | formData.add(new BasicNameValuePair("params", params.toString()));
112 |
113 | UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formData, "UTF-8");
114 | post.setEntity(entity);
115 |
116 | return post;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/conduit/ConduitAPIException.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.conduit;
22 |
23 | public class ConduitAPIException extends Exception {
24 | public final int code;
25 |
26 | public ConduitAPIException(String message) {
27 | super(message);
28 | this.code = 0;
29 | }
30 |
31 | public ConduitAPIException(String message, int code) {
32 | super(message);
33 | this.code = code;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/conduit/HarbormasterClient.java:
--------------------------------------------------------------------------------
1 | package com.uber.jenkins.phabricator.conduit;
2 |
3 | import com.uber.jenkins.phabricator.lint.LintResults;
4 | import com.uber.jenkins.phabricator.unit.UnitResults;
5 | import net.sf.json.JSONObject;
6 |
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | public class HarbormasterClient {
13 | private final ConduitAPIClient conduit;
14 |
15 | public HarbormasterClient(ConduitAPIClient conduit) {
16 | this.conduit = conduit;
17 | }
18 |
19 | /**
20 | * Sets a sendHarbormasterMessage build status
21 | * @param phid Phabricator object ID
22 | * @param pass whether or not the build passed
23 | * @param unitResults the results from the unit tests
24 | * @param coverage the results from the coverage provider
25 | * @param lintResults
26 | * @return the Conduit API response
27 | * @throws IOException if there is a network error talking to Conduit
28 | * @throws ConduitAPIException if any error is experienced talking to Conduit
29 | */
30 | public JSONObject sendHarbormasterMessage(String phid, boolean pass, UnitResults unitResults, Map coverage, LintResults lintResults) throws ConduitAPIException, IOException {
31 |
32 | List unit = new ArrayList();
33 |
34 | if (unitResults != null) {
35 | unit.addAll(unitResults.toHarbormaster());
36 | }
37 |
38 | List lint = new ArrayList();
39 |
40 | if (lintResults != null) {
41 | lint.addAll(lintResults.toHarbormaster());
42 | }
43 |
44 | if (coverage != null) {
45 | JSONObject coverageUnit = new JSONObject()
46 | .element("result", "pass")
47 | .element("name", "Coverage Data")
48 | .element("coverage", coverage);
49 | unit.add(coverageUnit);
50 | }
51 |
52 | JSONObject params = new JSONObject();
53 | params.element("type", pass ? "pass" : "fail")
54 | .element("buildTargetPHID", phid);
55 |
56 | if (!unit.isEmpty()) {
57 | params.element("unit", unit);
58 | }
59 |
60 | if (!lint.isEmpty()) {
61 | params.element("lint", lint);
62 | }
63 |
64 | return conduit.perform("harbormaster.sendmessage", params);
65 | }
66 |
67 | /**
68 | * Uploads a uri as an 'artifact' for Harbormaster to display
69 | * @param phid Phabricator object ID
70 | * @param buildUri Uri to display, presumably the jenkins builds
71 | * @return the Conduit API response
72 | * @throws IOException if there is a network error talking to Conduit
73 | * @throws ConduitAPIException if any error is experienced talking to Conduit
74 | */
75 | public JSONObject sendHarbormasterUri(String phid, String buildUri) throws ConduitAPIException, IOException {
76 | JSONObject artifactData = new JSONObject();
77 | artifactData = artifactData.element("uri", buildUri)
78 | .element("name", "Jenkins")
79 | .element("ui.external", true);
80 |
81 | JSONObject params = new JSONObject();
82 | params.element("buildTargetPHID", phid)
83 | .element("artifactKey", "jenkins.uri")
84 | .element("artifactType", "uri")
85 | .element("artifactData", artifactData);
86 |
87 | return conduit.perform("harbormaster.createartifact", params);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/coverage/CodeCoverageMetrics.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.coverage;
22 |
23 | public class CodeCoverageMetrics {
24 | private float packagesCoveragePercent = -1;
25 | private float filesCoveragePercent = -1;
26 | private float classesCoveragePercent = -1;
27 | private float methodCoveragePercent = -1;
28 | private float lineCoveragePercent = -1;
29 | private float conditionalCoveragePercent = -1;
30 |
31 | public CodeCoverageMetrics(float packagesCoveragePercent, float filesCoveragePercent,
32 | float classesCoveragePercent, float methodCoveragePercent, float lineCoveragePercent,
33 | float conditionalCoveragePercent) {
34 | this.packagesCoveragePercent = packagesCoveragePercent;
35 | this.filesCoveragePercent = filesCoveragePercent;
36 | this.classesCoveragePercent = classesCoveragePercent;
37 | this.methodCoveragePercent = methodCoveragePercent;
38 | this.lineCoveragePercent = lineCoveragePercent;
39 | this.conditionalCoveragePercent = conditionalCoveragePercent;
40 | }
41 |
42 | public boolean isValid() {
43 | return lineCoveragePercent != -1;
44 | }
45 |
46 | public float getPackageCoveragePercent() {
47 | return packagesCoveragePercent;
48 | }
49 |
50 | public float getFilesCoveragePercent() {
51 | return filesCoveragePercent;
52 | }
53 |
54 | public float getClassesCoveragePercent() {
55 | return classesCoveragePercent;
56 | }
57 |
58 | public float getMethodCoveragePercent() {
59 | return methodCoveragePercent;
60 | }
61 |
62 | public float getLineCoveragePercent() {
63 | return lineCoveragePercent;
64 | }
65 |
66 | public float getConditionalCoveragePercent() {
67 | return conditionalCoveragePercent;
68 | }
69 |
70 | public String toString() {
71 | StringBuilder sb = new StringBuilder();
72 | sb.append("package coverage = ");
73 | sb.append(packagesCoveragePercent);
74 | sb.append(", files coverage = ");
75 | sb.append(filesCoveragePercent);
76 | sb.append(", classes coverage = ");
77 | sb.append(classesCoveragePercent);
78 | sb.append(", method coverage = ");
79 | sb.append(methodCoveragePercent);
80 | sb.append(", line coverage = ");
81 | sb.append(lineCoveragePercent);
82 | sb.append(", conditional coverage = ");
83 | sb.append(conditionalCoveragePercent);
84 | return sb.toString();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/coverage/CoverageConverter.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.coverage;
22 |
23 | import java.util.HashMap;
24 | import java.util.List;
25 | import java.util.Map;
26 |
27 | /**
28 | * Convert {filename: int[] hitCount} data into the Harbormaster format
29 | *
30 | * This is a string, where each character represents a line. The code is as follows:
31 | *
32 | * 'N': not executable
33 | * 'C': covered
34 | * 'U': uncovered
35 | *
36 | * For example a hit count of {null, 2, 0, 1} we would get "NCUC"
37 | */
38 | public class CoverageConverter {
39 | /**
40 | * Convert line coverage to the Harbormaster coverage format
41 | * @return The Harbormaster-formatted coverage
42 | */
43 | public Map convert(Map> lineCoverage) {
44 | Map results = new HashMap();
45 | for (Map.Entry> entry : lineCoverage.entrySet()) {
46 | results.put(entry.getKey(), convertFileCoverage(entry.getValue()));
47 | }
48 |
49 | return results;
50 | }
51 |
52 | private String convertFileCoverage(List lineCoverage) {
53 | StringBuilder sb = new StringBuilder();
54 | for (Integer line : lineCoverage) {
55 | // Can't use a case statement because NULL
56 | if (line == null) {
57 | sb.append('N');
58 | } else if (line == 0) {
59 | sb.append('U');
60 | } else {
61 | sb.append('C');
62 | }
63 | }
64 | return sb.toString();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/coverage/CoverageProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.coverage;
22 |
23 | import hudson.model.AbstractBuild;
24 |
25 | import java.util.List;
26 | import java.util.Map;
27 |
28 | public abstract class CoverageProvider {
29 | private AbstractBuild, ?> build;
30 |
31 | /**
32 | * Set the owning build for this provider
33 | * @param build The build that is associated with the current run
34 | */
35 | public void setBuild(AbstractBuild, ?> build) {
36 | this.build = build;
37 | }
38 |
39 | protected AbstractBuild getBuild() {
40 | return build;
41 | }
42 |
43 | public abstract Map> readLineCoverage();
44 |
45 | public abstract boolean hasCoverage();
46 |
47 | /**
48 | * Get the coverage metrics for the provider
49 | * @return The metrics, if any are available
50 | */
51 | public CodeCoverageMetrics getMetrics() {
52 | if (!hasCoverage()) {
53 | return null;
54 | }
55 | return getCoverageMetrics();
56 | }
57 |
58 | protected abstract CodeCoverageMetrics getCoverageMetrics();
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/coverage/PathResolver.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.coverage;
22 |
23 | import hudson.FilePath;
24 |
25 | import java.io.IOException;
26 | import java.util.List;
27 |
28 | public class PathResolver {
29 | private final FilePath root;
30 | private final List candidates;
31 |
32 | public PathResolver(FilePath root, List candidates) {
33 | this.root = root;
34 | this.candidates = candidates;
35 | }
36 |
37 | /**
38 | * Using the workspace's root FilePath and a file that is presumed to exist on the node running the tests,
39 | * recurse over the `sources` provided by Cobertura and look for a combination where the file exists.
40 | *
41 | * This is a heuristic, and not perfect, to overcome changes to Python's coverage.py module which introduced
42 | * additional `source` directories in version 4.0.3
43 | */
44 | public String choose(String filename) {
45 | for (String sourceDir : candidates) {
46 | FilePath candidate = new FilePath(root, sourceDir);
47 | candidate = new FilePath(candidate, filename);
48 | try {
49 | if (candidate.exists()) {
50 | return sourceDir;
51 | }
52 | } catch (IOException e) {
53 | e.printStackTrace();
54 | } catch (InterruptedException e) {
55 | e.printStackTrace();
56 | }
57 | }
58 | return null;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/credentials/ConduitCredentials.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.credentials;
22 |
23 | import com.cloudbees.plugins.credentials.Credentials;
24 | import hudson.util.Secret;
25 |
26 | public interface ConduitCredentials extends Credentials {
27 |
28 | Secret getToken();
29 |
30 | String getGateway();
31 |
32 | String getUrl();
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/credentials/ConduitCredentialsImpl.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.credentials;
22 |
23 | import com.cloudbees.plugins.credentials.CredentialsDescriptor;
24 | import com.cloudbees.plugins.credentials.NameWith;
25 | import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials;
26 | import com.uber.jenkins.phabricator.utils.CommonUtils;
27 | import edu.umd.cs.findbugs.annotations.CheckForNull;
28 | import edu.umd.cs.findbugs.annotations.NonNull;
29 | import edu.umd.cs.findbugs.annotations.Nullable;
30 | import hudson.Extension;
31 | import hudson.util.Secret;
32 | import org.kohsuke.stapler.DataBoundConstructor;
33 |
34 | @NameWith(value = ConduitCredentialsNameProvider.class, priority = 50)
35 | @SuppressWarnings("unused")
36 | public class ConduitCredentialsImpl extends BaseStandardCredentials implements ConduitCredentials {
37 | @NonNull
38 | private final Secret token;
39 |
40 | @Nullable
41 | private final String gateway;
42 |
43 | @NonNull
44 | private final String url;
45 |
46 | @DataBoundConstructor
47 | public ConduitCredentialsImpl(@CheckForNull String id,
48 | @NonNull @CheckForNull String url,
49 | @Nullable String gateway,
50 | @CheckForNull String description,
51 | @CheckForNull String token) {
52 | super(id, description);
53 | this.url = url;
54 | this.gateway = gateway;
55 | this.token = Secret.fromString(token);
56 | }
57 |
58 | @NonNull
59 | public String getUrl() {
60 | return url;
61 | }
62 |
63 | @Nullable
64 | public String getGateway() {
65 | return !CommonUtils.isBlank(gateway) ? gateway : getUrl();
66 | }
67 |
68 | @NonNull
69 | public Secret getToken() {
70 | return token;
71 | }
72 |
73 | @Extension
74 | @SuppressWarnings("unused")
75 | public static class Descriptor extends CredentialsDescriptor {
76 | /** {@inheritDoc} */
77 | @Override
78 | public String getDisplayName() {
79 | return "Phabricator Conduit Key";
80 | }
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/credentials/ConduitCredentialsNameProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.credentials;
22 |
23 | import com.cloudbees.plugins.credentials.CredentialsNameProvider;
24 | import edu.umd.cs.findbugs.annotations.NonNull;
25 |
26 | public class ConduitCredentialsNameProvider extends CredentialsNameProvider {
27 | @NonNull
28 | @Override
29 | public String getName(@NonNull ConduitCredentialsImpl credentials) {
30 | return credentials.getUrl();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/lint/LintResult.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016 Uber
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | */
22 |
23 | package com.uber.jenkins.phabricator.lint;
24 |
25 | import net.sf.json.JSONObject;
26 |
27 | /**
28 | * This currently mirrors the API format of Harbormaster lint messages
29 | *
30 | * Reference: https://secure.phabricator.com/conduit/method/harbormaster.sendmessage/
31 | *
32 | * name string Short message name, like "Syntax Error".
33 | * code string Lint message code identifying the type of message, like "ERR123".
34 | * severity string Severity of the message.
35 | * path string Path to the file containing the lint message, from the project root.
36 | * line optional int Line number in the file where the text which triggered the message first appears. The first line of the file is line 1, not line 0.
37 | * char optional int Byte position on the line where the text which triggered the message starts. The first byte on the line is byte 1, not byte 0. This position is byte-based (not character-based) because not all lintable files have a valid character encoding.
38 | * description optional string Long explanation of the lint message.
39 | */
40 | public class LintResult {
41 | final String name;
42 | final String code;
43 | final String severity;
44 | final String path;
45 | final int line;
46 | final int charPosition; // NOTE "char" parameter in JSON
47 | final String description;
48 |
49 | public LintResult(String name, String code, String severity, String path, int line, int charPosition, String description) {
50 | this.name = name;
51 | this.code = code;
52 | this.severity = severity;
53 | this.path = path;
54 | this.line = line;
55 | this.charPosition = charPosition;
56 | this.description = description;
57 | }
58 |
59 | /**
60 | * Create a Harbormaster-API-compatible representation of the lint result
61 | * @return A JSON representation of the lint result
62 | */
63 | public JSONObject toHarbormaster() {
64 | return new JSONObject()
65 | .element("name", name)
66 | .element("code", code)
67 | .element("severity", severity)
68 | .element("path", path)
69 | .element("line", line)
70 | .element("char", charPosition)
71 | .element("description", description);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/lint/LintResults.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016 Uber
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | */
22 |
23 | package com.uber.jenkins.phabricator.lint;
24 |
25 | import net.sf.json.JSONObject;
26 |
27 | import java.util.ArrayList;
28 | import java.util.List;
29 |
30 | /**
31 | * Represent a list of lint results
32 | */
33 | public class LintResults {
34 | private final List results;
35 |
36 | public LintResults() {
37 | this.results = new ArrayList();
38 | }
39 |
40 | public void add(LintResult result) {
41 | results.add(result);
42 | }
43 |
44 | public List getResults() {
45 | return results;
46 | }
47 |
48 | /**
49 | * Convert a suite of unit results to Harbormaster JSON format
50 | * @return Harbormaster-formatted unit results
51 | */
52 | public List toHarbormaster() {
53 | List harbormasterData = new ArrayList();
54 |
55 | for (LintResult result : results) {
56 | harbormasterData.add(result.toHarbormaster());
57 | }
58 |
59 | return harbormasterData;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/provider/BaseProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.provider;
22 |
23 | import com.uber.jenkins.phabricator.utils.Logger;
24 | import jenkins.model.Jenkins;
25 |
26 | public class BaseProvider extends Provider {
27 | private final Jenkins jenkins;
28 |
29 | public BaseProvider(Jenkins jenkins, String pluginName, Logger logger) {
30 | super(pluginName, logger);
31 | this.jenkins = jenkins;
32 | }
33 |
34 | /**
35 | * {@inheritDoc}
36 | */
37 | @Override
38 | public boolean isAvailable() {
39 | return jenkins.getPlugin(pluginName) != null;
40 | }
41 |
42 | /**
43 | * {@inheritDoc}
44 | */
45 | @Override
46 | public T getInstance(final String className) {
47 | try {
48 | return (T) getClass().getClassLoader().loadClass(className).newInstance();
49 | } catch (ClassNotFoundException e) {
50 | e.printStackTrace(logger.getStream());
51 | } catch (InstantiationException e) {
52 | e.printStackTrace(logger.getStream());
53 | } catch (IllegalAccessException e) {
54 | e.printStackTrace(logger.getStream());
55 | }
56 | return null;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/provider/InstanceProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.provider;
22 |
23 | import com.uber.jenkins.phabricator.utils.Logger;
24 | import jenkins.model.Jenkins;
25 |
26 | public class InstanceProvider {
27 | private static final String LOGGER_TAG = "plugin-provider";
28 | private final Provider provider;
29 | private final String className;
30 | private final Logger logger;
31 | private final String pluginName;
32 |
33 | /**
34 | * Encapsulate lazilly loading a concrete implementation when a plugin is available
35 | * @param jenkins the instance of Jenkins
36 | * @param pluginName the name of the plugin, e.g. "cobertura" or "junit" (maven name)
37 | * @param className the concrete class name (com.uber.phabricator...)
38 | * @param logger the logger to use
39 | */
40 | public InstanceProvider(Jenkins jenkins, String pluginName, String className, Logger logger) {
41 | this.provider = new BaseProvider(
42 | jenkins,
43 | pluginName,
44 | logger
45 | );
46 | this.pluginName = pluginName;
47 | this.className = className;
48 | this.logger = logger;
49 | }
50 |
51 | /**
52 | * Get an instance of the desired implementation, if available
53 | * @return the class desired
54 | */
55 | public T getInstance() {
56 | if (!provider.isAvailable()) {
57 | logger.info(LOGGER_TAG, String.format("'%s' plugin not installed.", pluginName));
58 | return null;
59 | }
60 | T instance = provider.getInstance(className);
61 | if (instance == null) {
62 | logger.warn(LOGGER_TAG,
63 | String.format("Unable to instantiate plugin provider for '%s'. This should not happen.", pluginName));
64 | }
65 | return instance;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/provider/Provider.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.provider;
22 |
23 | import com.uber.jenkins.phabricator.utils.Logger;
24 |
25 | public abstract class Provider {
26 | protected final Logger logger;
27 | protected final String pluginName;
28 |
29 | public Provider(final String pluginName, final Logger logger) {
30 | this.pluginName = pluginName;
31 | this.logger = logger;
32 | }
33 |
34 | /**
35 | * Determine if the provider is available for the plugin
36 | * @return Whether the plugin is available
37 | */
38 | public abstract boolean isAvailable();
39 |
40 | /**
41 | * Instantiate a new instance of the class given the implementation class name
42 | * @param implementationName The fully-qualified name of the class
43 | * @return An instance of the class
44 | */
45 | public abstract T getInstance(final String implementationName);
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/tasks/ApplyPatchTask.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.tasks;
22 |
23 | import com.uber.jenkins.phabricator.LauncherFactory;
24 | import com.uber.jenkins.phabricator.conduit.ArcanistClient;
25 | import com.uber.jenkins.phabricator.utils.Logger;
26 |
27 | import java.io.IOException;
28 | import java.io.PrintStream;
29 | import java.util.ArrayList;
30 | import java.util.Arrays;
31 | import java.util.List;
32 |
33 | public class ApplyPatchTask extends Task {
34 | private final LauncherFactory starter;
35 | private final String baseCommit;
36 | private final String diffID;
37 | private final PrintStream logStream;
38 | private final String conduitToken;
39 | private final String arcPath;
40 | private final boolean createCommit;
41 | private final String gitPath;
42 | private final boolean skipForcedClean;
43 | private final boolean createBranch;
44 | private final boolean patchWithForceFlag;
45 |
46 | public ApplyPatchTask(Logger logger, LauncherFactory starter, String baseCommit,
47 | String diffID, String conduitToken, String arcPath,
48 | String gitPath, boolean createCommit, boolean skipForcedClean,
49 | boolean createBranch, boolean patchWithForceFlag) {
50 | super(logger);
51 | this.starter = starter;
52 | this.baseCommit = baseCommit;
53 | this.diffID = diffID;
54 | this.conduitToken = conduitToken;
55 | this.arcPath = arcPath;
56 | this.gitPath = gitPath;
57 | this.createCommit = createCommit;
58 | this.skipForcedClean = skipForcedClean;
59 | this.createBranch = createBranch;
60 | this.patchWithForceFlag = patchWithForceFlag;
61 |
62 | this.logStream = logger.getStream();
63 | }
64 |
65 | /**
66 | * {@inheritDoc}
67 | */
68 | @Override
69 | protected String getTag() {
70 | return "arc-patch";
71 | }
72 |
73 | /**
74 | * {@inheritDoc}
75 | */
76 | @Override
77 | protected void setup() {
78 | // Do nothing
79 | }
80 |
81 | /**
82 | * {@inheritDoc}
83 | */
84 | @Override
85 | protected void execute() {
86 | try {
87 | int exitCode = starter.launch()
88 | .cmds(Arrays.asList(gitPath, "reset", "--hard", baseCommit))
89 | .stdout(logStream)
90 | .join();
91 |
92 | if (exitCode != 0) {
93 | info("Got non-zero exit code resetting to base commit " + baseCommit + ": " + exitCode);
94 | }
95 |
96 | if (!skipForcedClean) {
97 | // Clean workspace, otherwise `arc patch` may fail
98 | starter.launch()
99 | .stdout(logStream)
100 | .cmds(Arrays.asList(gitPath, "clean", "-fd", "-f"))
101 | .join();
102 | }
103 |
104 | // Update submodules recursively.
105 | starter.launch()
106 | .stdout(logStream)
107 | .cmds(Arrays.asList(gitPath, "submodule", "update", "--init", "--recursive"))
108 | .join();
109 |
110 | List arcPatchParams = new ArrayList(Arrays.asList("--diff", diffID));
111 | if (!createCommit) {
112 | arcPatchParams.add("--nocommit");
113 | }
114 |
115 | if (!createBranch) {
116 | arcPatchParams.add("--nobranch");
117 | }
118 |
119 | if (patchWithForceFlag) {
120 | arcPatchParams.add("--force");
121 | }
122 |
123 | ArcanistClient arc = new ArcanistClient(
124 | arcPath,
125 | "patch",
126 | conduitToken,
127 | arcPatchParams.toArray(new String[arcPatchParams.size()]));
128 |
129 | exitCode = arc.callConduit(starter.launch(), logStream);
130 | this.result = exitCode == 0 ? Result.SUCCESS : Result.FAILURE;
131 | } catch (IOException e) {
132 | e.printStackTrace(logStream);
133 | this.result = Result.FAILURE;
134 | } catch (InterruptedException e) {
135 | e.printStackTrace(logStream);
136 | this.result = Result.FAILURE;
137 | }
138 | }
139 |
140 | /**
141 | * {@inheritDoc}
142 | */
143 | @Override
144 | protected void tearDown() {
145 | // Do nothing
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/tasks/NonDifferentialBuildTask.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.tasks;
22 |
23 | import com.uber.jenkins.phabricator.coverage.CodeCoverageMetrics;
24 | import com.uber.jenkins.phabricator.uberalls.UberallsClient;
25 | import com.uber.jenkins.phabricator.utils.CommonUtils;
26 | import com.uber.jenkins.phabricator.utils.Logger;
27 |
28 | /**
29 | * Generic build task.
30 | */
31 | public class NonDifferentialBuildTask extends Task {
32 |
33 | protected final UberallsClient uberallsClient;
34 | protected final CodeCoverageMetrics codeCoverageMetrics;
35 | protected final boolean uberallsEnabled;
36 | protected final String commitSha;
37 |
38 | /**
39 | * GenericBuildTask constructor.
40 | * @param logger The logger.
41 | * @param uberallsClient The uberalls client.
42 | * @param codeCoverageMetrics The coverage metrics.
43 | * @param uberallsEnabled Whether uberalls is enabled.
44 | * @param commitSha The commit sha.
45 | */
46 | public NonDifferentialBuildTask(Logger logger, UberallsClient uberallsClient,
47 | CodeCoverageMetrics codeCoverageMetrics, boolean uberallsEnabled,
48 | String commitSha) {
49 | super(logger);
50 | this.uberallsClient = uberallsClient;
51 | this.codeCoverageMetrics = codeCoverageMetrics;
52 | this.uberallsEnabled = uberallsEnabled;
53 | this.commitSha = commitSha;
54 | }
55 |
56 | /**
57 | * {@inheritDoc}
58 | */
59 | @Override
60 | protected String getTag() {
61 | return "non-differential";
62 | }
63 |
64 | /**
65 | * {@inheritDoc}
66 | */
67 | @Override
68 | protected void setup() {
69 | // Handle bad input.
70 | if (codeCoverageMetrics == null || !codeCoverageMetrics.isValid()) {
71 | info("Coverage result not found. Ignoring build.");
72 | result = Result.IGNORED;
73 | } else if (!uberallsEnabled || CommonUtils.isBlank(uberallsClient.getBaseURL())) {
74 | info("Uberalls not configured. Skipping build.");
75 | result = Result.SKIPPED;
76 | }
77 | }
78 |
79 | /**
80 | * {@inheritDoc}
81 | */
82 | @Override
83 | protected void execute() {
84 | if (result == Result.UNKNOWN) {
85 | if (!CommonUtils.isBlank(commitSha)) {
86 | info(String.format("Sending coverage result for %s as %s", commitSha,
87 | codeCoverageMetrics.toString()));
88 | result = uberallsClient.recordCoverage(commitSha, codeCoverageMetrics) ?
89 | Result.SUCCESS : Result.FAILURE;
90 | } else {
91 | info("No line coverage found. Ignoring build.");
92 | result = Result.IGNORED;
93 | }
94 | }
95 | }
96 |
97 | /**
98 | * {@inheritDoc}
99 | */
100 | @Override
101 | protected void tearDown() {
102 | // Do nothing.
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/tasks/NonDifferentialHarbormasterTask.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.tasks;
22 |
23 | import com.uber.jenkins.phabricator.conduit.ConduitAPIClient;
24 | import com.uber.jenkins.phabricator.conduit.ConduitAPIException;
25 | import com.uber.jenkins.phabricator.conduit.HarbormasterClient;
26 | import com.uber.jenkins.phabricator.utils.Logger;
27 |
28 | import java.io.IOException;
29 |
30 | public class NonDifferentialHarbormasterTask extends Task {
31 | private final String phid;
32 | private final ConduitAPIClient conduit;
33 | private final hudson.model.Result buildResult;
34 | private final String buildUrl;
35 | private final HarbormasterClient harbormaster;
36 | private final Logger logger;
37 |
38 | /**
39 | * Task constructor.
40 | * @param logger The logger where logs go to.
41 | * @param conduitClient
42 | * @param result
43 | * @param buildUrl
44 | */
45 | public NonDifferentialHarbormasterTask(Logger logger, String phid, ConduitAPIClient conduitClient, hudson.model.Result result, String buildUrl) {
46 | super(logger);
47 | this.logger = logger;
48 | this.phid = phid;
49 | this.conduit = conduitClient;
50 | this.buildResult = result;
51 | this.buildUrl = buildUrl;
52 |
53 | this.harbormaster = new HarbormasterClient(conduit);
54 | }
55 |
56 | /**
57 | * {@inheritDoc}
58 | */
59 | @Override
60 | protected String getTag() {
61 | return "non-differential-harbormaster";
62 | }
63 |
64 | /**
65 | * {@inheritDoc}
66 | */
67 | @Override
68 | protected void setup() {
69 | // Do nothing
70 | }
71 |
72 | /**
73 | * {@inheritDoc}
74 | */
75 | @Override
76 | protected void execute() {
77 | final boolean pass = buildResult.isBetterOrEqualTo(hudson.model.Result.SUCCESS);
78 | info(String.format("Sending diffusion result as: %s", buildResult.toString()));
79 |
80 | try {
81 | harbormaster.sendHarbormasterUri(phid, buildUrl);
82 | // Only send pass/fail, since coverage and unit aren't viewable outside of differentials
83 | harbormaster.sendHarbormasterMessage(phid, pass, null, null, null);
84 | result = Result.SUCCESS;
85 | return;
86 | } catch (ConduitAPIException e) {
87 | e.printStackTrace(logger.getStream());
88 | } catch (IOException e) {
89 | e.printStackTrace(logger.getStream());
90 | }
91 |
92 | result = Result.FAILURE;
93 | }
94 |
95 | /**
96 | * {@inheritDoc}
97 | */
98 | @Override
99 | protected void tearDown() {
100 | // Do nothing
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/tasks/PostCommentTask.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.tasks;
22 |
23 | import com.uber.jenkins.phabricator.conduit.ConduitAPIException;
24 | import com.uber.jenkins.phabricator.conduit.DifferentialClient;
25 | import com.uber.jenkins.phabricator.utils.Logger;
26 | import net.sf.json.JSONNull;
27 | import net.sf.json.JSONObject;
28 |
29 | import java.io.IOException;
30 |
31 | /**
32 | * Post comment task.
33 | */
34 | public class PostCommentTask extends Task {
35 |
36 | private static final boolean SILENT = false;
37 | private static final String DEFAULT_COMMENT_ACTION = "none";
38 |
39 | private final DifferentialClient differentialClient;
40 | private final String revisionID;
41 | private final String comment;
42 | private final String commentAction;
43 |
44 | /**
45 | * PostCommentTask constructor.
46 | * @param logger the logger
47 | * @param differentialClient the client for the differential
48 | * @param revisionID the revision identifier from harbormaster
49 | * @param comment the body of the comment
50 | * @param commentAction the name of the comment action
51 | */
52 | public PostCommentTask(Logger logger, DifferentialClient differentialClient,
53 | String revisionID, String comment, String commentAction) {
54 | super(logger);
55 |
56 | this.differentialClient = differentialClient;
57 | this.revisionID = revisionID;
58 | this.comment = comment;
59 | this.commentAction = commentAction;
60 | }
61 |
62 | /**
63 | * {@inheritDoc}
64 | */
65 | @Override
66 | protected String getTag() {
67 | return "post-comment";
68 | }
69 |
70 | /**
71 | * {@inheritDoc}
72 | */
73 | @Override
74 | protected void setup() {
75 | // Do nothing.
76 | }
77 |
78 | /**
79 | * {@inheritDoc}
80 | */
81 | @Override
82 | protected void execute() {
83 | JSONObject postDifferentialCommentResult = postDifferentialComment(comment, SILENT,
84 | commentAction);
85 | if (postDifferentialCommentResult == null ||
86 | !(postDifferentialCommentResult.get("error_info") instanceof JSONNull)) {
87 | if (postDifferentialCommentResult != null) {
88 | info(String.format("Got error %s with action %s",
89 | postDifferentialCommentResult.get("error_info"), commentAction));
90 | }
91 |
92 | info("Re-trying with action 'none'");
93 | postDifferentialComment(comment, SILENT, DEFAULT_COMMENT_ACTION);
94 | }
95 | }
96 |
97 | /**
98 | * {@inheritDoc}
99 | */
100 | @Override
101 | protected void tearDown() {
102 | // Do nothing.
103 | }
104 |
105 | private JSONObject postDifferentialComment(String message, boolean silent, String action) {
106 | try {
107 | JSONObject postDifferentialCommentResult = differentialClient.postComment(revisionID,
108 | message, silent, action);
109 | result = Result.SUCCESS;
110 | return postDifferentialCommentResult;
111 | } catch (IOException e) {
112 | throw new RuntimeException(e);
113 | } catch (ConduitAPIException e) {
114 | info("unable to post comment");
115 | }
116 |
117 | result = Result.FAILURE;
118 | return null;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/tasks/SendHarbormasterResultTask.java:
--------------------------------------------------------------------------------
1 | package com.uber.jenkins.phabricator.tasks;
2 |
3 | import com.uber.jenkins.phabricator.conduit.ConduitAPIException;
4 | import com.uber.jenkins.phabricator.conduit.DifferentialClient;
5 | import com.uber.jenkins.phabricator.lint.LintResults;
6 | import com.uber.jenkins.phabricator.unit.UnitResults;
7 | import com.uber.jenkins.phabricator.utils.Logger;
8 | import net.sf.json.JSONNull;
9 | import net.sf.json.JSONObject;
10 |
11 | import java.io.IOException;
12 | import java.util.Map;
13 |
14 | public class SendHarbormasterResultTask extends Task {
15 |
16 | private final DifferentialClient diffClient;
17 | private final String phid;
18 | private final boolean harbormasterSuccess;
19 | private UnitResults unitResults;
20 | private final Map coverage;
21 | private final LintResults lintResults;
22 |
23 | public SendHarbormasterResultTask(Logger logger, DifferentialClient diffClient, String phid,
24 | boolean harbormasterSuccess, UnitResults unitResults,
25 | Map harbormasterCoverage,
26 | LintResults lintResults) {
27 | super(logger);
28 | this.diffClient = diffClient;
29 | this.phid = phid;
30 | this.harbormasterSuccess = harbormasterSuccess;
31 | this.unitResults = unitResults;
32 | this.coverage = harbormasterCoverage;
33 | this.lintResults = lintResults;
34 | }
35 |
36 | /**
37 | * {@inheritDoc}
38 | */
39 | @Override
40 | protected String getTag() {
41 | return "send-harbormaster-result";
42 | }
43 |
44 | /**
45 | * {@inheritDoc}
46 | */
47 | @Override
48 | protected void setup() {
49 | // Do nothing
50 | }
51 |
52 | /**
53 | * {@inheritDoc}
54 | */
55 | @Override
56 | protected void execute() {
57 | try {
58 | if (!sendMessage(unitResults, coverage, lintResults)) {
59 | info("Error sending Harbormaster unit results, trying again without unit data (you may have an old Phabricator?).");
60 | sendMessage(null, null, null);
61 | }
62 | } catch (ConduitAPIException e) {
63 | e.printStackTrace();
64 | failTask();
65 | } catch (IOException e) {
66 | e.printStackTrace();
67 | failTask();
68 | }
69 | }
70 |
71 | /**
72 | * Try to send a message to harbormaster
73 | * @param unitResults the unit testing results to send
74 | * @param coverage the coverage data to send
75 | * @return false if an error was encountered
76 | */
77 | private boolean sendMessage(UnitResults unitResults, Map coverage, LintResults lintResults) throws IOException, ConduitAPIException {
78 | JSONObject result = diffClient.sendHarbormasterMessage(phid, harbormasterSuccess, unitResults, coverage, lintResults);
79 |
80 | if (result.containsKey("error_info") && !(result.get("error_info") instanceof JSONNull)) {
81 | info(String.format("Error from Harbormaster: %s", result.getString("error_info")));
82 | failTask();
83 | return false;
84 | } else {
85 | this.result = Result.SUCCESS;
86 | }
87 | return true;
88 | }
89 |
90 | private void failTask() {
91 | info("Unable to post to Harbormaster");
92 | result = result.FAILURE;
93 | }
94 |
95 | /**
96 | * {@inheritDoc}
97 | */
98 | @Override
99 | protected void tearDown() {
100 | // Do nothing
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/tasks/SendHarbormasterUriTask.java:
--------------------------------------------------------------------------------
1 | // Permission is hereby granted, free of charge, to any person obtaining a copy
2 | // of this software and associated documentation files (the "Software"), to deal
3 | // in the Software without restriction, including without limitation the rights
4 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5 | // copies of the Software, and to permit persons to whom the Software is
6 | // furnished to do so, subject to the following conditions:
7 | //
8 | // The above copyright notice and this permission notice shall be included in
9 | // all copies or substantial portions of the Software.
10 | //
11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
17 | // THE SOFTWARE.
18 |
19 | package com.uber.jenkins.phabricator.tasks;
20 |
21 | import com.uber.jenkins.phabricator.conduit.ConduitAPIException;
22 | import com.uber.jenkins.phabricator.conduit.DifferentialClient;
23 | import com.uber.jenkins.phabricator.utils.Logger;
24 | import net.sf.json.JSONNull;
25 | import net.sf.json.JSONObject;
26 |
27 | import java.io.IOException;
28 |
29 | public class SendHarbormasterUriTask extends Task {
30 |
31 | private final DifferentialClient diffClient;
32 | private final String phid;
33 | private final String buildUri;
34 |
35 | public SendHarbormasterUriTask(Logger logger, DifferentialClient diffClient, String phid, String buildUri) {
36 | super(logger);
37 | this.diffClient = diffClient;
38 | this.phid = phid;
39 | this.buildUri = buildUri;
40 | }
41 |
42 | @Override
43 | protected String getTag() {
44 | return "send-harbormaster-uri";
45 | }
46 |
47 | @Override
48 | protected void setup() {
49 | // Do nothing
50 | }
51 |
52 | @Override
53 | protected void execute() {
54 | try {
55 | JSONObject result = diffClient.sendHarbormasterUri(phid, buildUri);
56 | if (result.containsKey("error_info") && !(result.get("error_info") instanceof JSONNull)) {
57 | info(String.format("Harbormaster declined URI artifact: %s", result.getString("error_info")));
58 | this.result = Result.FAILURE;
59 | } else {
60 | this.result = Result.SUCCESS;
61 | }
62 | } catch (ConduitAPIException e) {
63 | e.printStackTrace();
64 | this.result = Result.FAILURE;
65 | } catch (IOException e) {
66 | e.printStackTrace();
67 | this.result = Result.FAILURE;
68 | }
69 | }
70 |
71 | @Override
72 | protected void tearDown() {
73 | // Do nothing
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/tasks/Task.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.tasks;
22 |
23 | import com.uber.jenkins.phabricator.utils.Logger;
24 |
25 | /**
26 | * Base task for all operations in the phabricator-jenkins plugin.
27 | */
28 | public abstract class Task {
29 |
30 | /**
31 | * Task results.
32 | */
33 | public enum Result {
34 | SUCCESS,
35 | FAILURE,
36 | IGNORED, // For incorrect input.
37 | SKIPPED, // For incorrect configuration.
38 | UNKNOWN
39 | }
40 |
41 | protected Result result = Result.UNKNOWN;
42 | private final Logger logger;
43 |
44 | /**
45 | * Task constructor.
46 | * @param logger The logger where logs go to.
47 | */
48 | public Task(Logger logger) {
49 | this.logger = logger;
50 | }
51 |
52 | /**
53 | * Runs the task workflow.
54 | * @return the result of the task
55 | */
56 | public Result run() {
57 | setup();
58 | execute();
59 | tearDown();
60 |
61 | return result;
62 | }
63 |
64 | /**
65 | * Logs the message.
66 | * @param message The message to log.
67 | */
68 | protected void info(String message) {
69 | logger.info(getTag(), message);
70 | }
71 |
72 | /**
73 | * Gets the task's tag.
74 | * @return A string representation of this task's tag.
75 | */
76 | protected abstract String getTag();
77 |
78 | /**
79 | * Sets up the environment before task execution.
80 | */
81 | protected abstract void setup();
82 |
83 | /**
84 | * Executes the task workflow.
85 | */
86 | protected abstract void execute();
87 |
88 | /**
89 | * Tears down after task execution.
90 | */
91 | protected abstract void tearDown();
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/unit/JUnitTestProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.unit;
22 |
23 | import hudson.model.AbstractBuild;
24 | import hudson.tasks.junit.CaseResult;
25 | import hudson.tasks.junit.SuiteResult;
26 | import hudson.tasks.junit.TestResult;
27 | import hudson.tasks.junit.TestResultAction;
28 |
29 | /**
30 | * Provides jUnit test reports to report results on builds
31 | */
32 | @SuppressWarnings("unused")
33 | public class JUnitTestProvider extends UnitTestProvider {
34 | /**
35 | * {@inheritDoc}
36 | */
37 | @Override
38 | public boolean resultsAvailable() {
39 | return getJUnitResults() != null;
40 | }
41 |
42 | /**
43 | * {@inheritDoc}
44 | */
45 | @Override
46 | public UnitResults getResults() {
47 | return convertJUnit(getJUnitResults());
48 | }
49 |
50 | /**
51 | * Convert JUnit's TestResult representation into a generic UnitResults
52 | * @param jUnitResults The result of the JUnit run
53 | * @return The converted results
54 | */
55 | public UnitResults convertJUnit(TestResult jUnitResults) {
56 | UnitResults results = new UnitResults();
57 | if (jUnitResults == null) {
58 | return results;
59 | }
60 | for (SuiteResult sr : jUnitResults.getSuites()) {
61 | for (CaseResult cr : sr.getCases()) {
62 | UnitResult result = new UnitResult(
63 | cr.getClassName(),
64 | cr.getDisplayName(),
65 | cr.getErrorStackTrace(),
66 | cr.getDuration(),
67 | cr.getFailCount(),
68 | cr.getSkipCount(),
69 | cr.getPassCount()
70 | );
71 | results.add(result);
72 | }
73 | }
74 | return results;
75 | }
76 |
77 | private TestResult getJUnitResults() {
78 | AbstractBuild build = getBuild();
79 |
80 | TestResultAction jUnitAction = build.getAction(TestResultAction.class);
81 | if (jUnitAction == null) {
82 | return null;
83 | }
84 | return jUnitAction.getResult();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/unit/UnitResult.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.unit;
22 |
23 | import net.sf.json.JSONObject;
24 |
25 | public class UnitResult {
26 | private static final String FAILURE = "fail";
27 | private static final String SKIP = "skip";
28 | private static final String PASS = "pass";
29 | private static final String UNSOUND = "unsound";
30 | private static final String ENGINE_NAME = "Jenkins";
31 | private final String className;
32 | private final String name;
33 | private final String stackTrace;
34 | private final float duration;
35 | private final int failCount;
36 | private final int skipCount;
37 | private final int passCount;
38 |
39 | public UnitResult(String className, String displayName, String stackTrace, float duration, int failCount, int skipCount, int passCount) {
40 | this.className = className;
41 | name = displayName;
42 | this.duration = duration;
43 | this.failCount = failCount;
44 | this.skipCount = skipCount;
45 | this.passCount = passCount;
46 | this.stackTrace = stackTrace;
47 | }
48 |
49 | public String getHarbormasterResult() {
50 | if (failCount > 0) {
51 | return FAILURE;
52 | } else if (skipCount > 0) {
53 | return SKIP;
54 | } else if (passCount > 0) {
55 | return PASS;
56 | }
57 | return UNSOUND;
58 | }
59 |
60 | public JSONObject toHarbormaster() {
61 | return new JSONObject()
62 | .element("name", name)
63 | .element("result", getHarbormasterResult())
64 | .element("namespace", className)
65 | .element("details", stackTrace)
66 | .element("engine", ENGINE_NAME)
67 | .element("duration", duration);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/unit/UnitResults.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.unit;
22 |
23 | import net.sf.json.JSONObject;
24 |
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | /**
29 | * Represent a list of unit results
30 | */
31 | public class UnitResults {
32 | private final List results;
33 |
34 | public UnitResults() {
35 | this.results = new ArrayList();
36 | }
37 |
38 | public void add(UnitResult result) {
39 | results.add(result);
40 | }
41 |
42 | public List getResults() {
43 | return results;
44 | }
45 |
46 | /**
47 | * Convert a suite of unit results to Harbormaster JSON format
48 | * @return Harbormaster-formatted unit results
49 | */
50 | public List toHarbormaster() {
51 | List harbormasterData = new ArrayList();
52 |
53 | for (UnitResult result : results) {
54 | harbormasterData.add(result.toHarbormaster());
55 | }
56 |
57 | return harbormasterData;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/unit/UnitTestProvider.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.unit;
22 |
23 | import hudson.model.AbstractBuild;
24 |
25 | /**
26 | * Provides an interface for plugins that have unit test results
27 | */
28 | public abstract class UnitTestProvider {
29 | private AbstractBuild, ?> build;
30 |
31 | /**
32 | * Set the owning build for this provider
33 | * @param build The build that is associated with the current run
34 | */
35 | public void setBuild(AbstractBuild, ?> build) {
36 | this.build = build;
37 | }
38 |
39 | protected AbstractBuild getBuild() {
40 | return build;
41 | }
42 |
43 | /**
44 | * Determine if the current provider has results available for the build
45 | * @return Whether results are available
46 | */
47 | public abstract boolean resultsAvailable();
48 |
49 | /**
50 | * Convert the provider's results to a standard format
51 | * @return The results of the unit tests
52 | */
53 | public abstract UnitResults getResults();
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/utils/CommonUtils.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.utils;
22 |
23 | public class CommonUtils {
24 | public static boolean isBlank(String str) {
25 | return str == null || str.trim().isEmpty();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/uber/jenkins/phabricator/utils/Logger.java:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 Uber Technologies, Inc.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | package com.uber.jenkins.phabricator.utils;
22 |
23 | import java.io.PrintStream;
24 |
25 | /**
26 | * Logger utility.
27 | */
28 | public class Logger {
29 | private static final String LOG_FORMAT = "[phabricator:%s] %s";
30 |
31 | private final PrintStream stream;
32 |
33 | /**
34 | * Logger constructor.
35 | * @param stream The stream.
36 | */
37 | public Logger(PrintStream stream) {
38 | this.stream = stream;
39 | }
40 |
41 | /**
42 | * Gets the stream.
43 | * @return The stream where logs go to.
44 | */
45 | public PrintStream getStream() {
46 | return stream;
47 | }
48 |
49 | /**
50 | * Logs the message to the stream.
51 | * @param tag The tag for the message.
52 | * @param message The message to log.
53 | */
54 | public void info(String tag, String message) {
55 | stream.println(String.format(LOG_FORMAT, tag, message));
56 | }
57 |
58 | /**
59 | * Logs the message to the stream as a warning.
60 | * @param tag The tag for the message.
61 | * @param message The message to log.
62 | */
63 | public void warn(String tag, String message) {
64 | info(tag, message);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/resources/com/uber/jenkins/phabricator/PhabricatorBuildWrapper/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
9 |
10 |
11 |
13 |
14 |
15 |
17 |
18 |
19 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/resources/com/uber/jenkins/phabricator/PhabricatorBuildWrapper/global.jelly:
--------------------------------------------------------------------------------
1 |
2 |
6 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/resources/com/uber/jenkins/phabricator/PhabricatorNotifier/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
15 |
16 |
17 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
28 |
29 |
30 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/main/resources/com/uber/jenkins/phabricator/PhabricatorNotifier/global.jelly:
--------------------------------------------------------------------------------
1 |
2 |
6 |
18 |
19 |
20 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/main/resources/com/uber/jenkins/phabricator/PhabricatorNotifier/help-conduitURL.html:
--------------------------------------------------------------------------------
1 |
2 | This HTML fragment will be injected into the configuration screen
3 | when the user clicks the 'help' icon. See global.jelly for how the
4 | form decides which page to load.
5 | You can have any HTML fragment here.
6 |
Gateway is an optional configuration that can be used to point where your Conduit APIs are routed. If this not not defined, the Conduit client defaults all API calls to the URL defined with the credentials instead.