├── .circleci
└── config.yml
├── .github
└── workflows
│ ├── release.yml
│ └── test.yml
├── .gitignore
├── .scalafix.conf
├── .scalafmt.conf
├── LICENSE
├── README.md
├── build.sbt
├── project
├── build.properties
└── plugins.sbt
└── src
├── main
├── scala-sbt-0.13
│ └── sbtsonar
│ │ └── SbtCompat.scala
├── scala-sbt-1.0
│ └── sbtsonar
│ │ └── SbtCompat.scala
└── scala
│ └── sbtsonar
│ ├── SonarPlugin.scala
│ └── SonarSbtLogOutput.scala
├── sbt-test
└── sbt-sonar
│ ├── external-config
│ ├── build.sbt
│ ├── project
│ │ ├── build.properties
│ │ └── plugins.sbt
│ ├── sonar-project.properties
│ ├── src
│ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example.scala
│ │ └── test
│ │ │ └── scala
│ │ │ └── ExampleTest.scala
│ └── test
│ ├── independent-projects
│ ├── build.sbt
│ ├── project
│ │ ├── build.properties
│ │ └── plugins.sbt
│ ├── src
│ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example.scala
│ │ └── test
│ │ │ └── scala
│ │ │ └── ExampleTest.scala
│ ├── test
│ ├── test-1
│ │ └── module1
│ │ │ └── src
│ │ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example1.scala
│ │ │ └── test
│ │ │ └── scala
│ │ │ └── Example1Test.scala
│ └── test-2
│ │ └── module2
│ │ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── Example2.scala
│ │ └── test
│ │ └── scala
│ │ └── Example2Test.scala
│ ├── multi-module-not-on-root-with-correct-config
│ ├── build.sbt
│ ├── project
│ │ ├── build.properties
│ │ └── plugins.sbt
│ ├── src
│ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example.scala
│ │ └── test
│ │ │ └── scala
│ │ │ └── ExampleTest.scala
│ ├── test
│ ├── test-1
│ │ └── module1
│ │ │ └── src
│ │ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example1.scala
│ │ │ └── test
│ │ │ └── scala
│ │ │ └── Example1Test.scala
│ └── test-2
│ │ └── module2
│ │ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── Example2.scala
│ │ └── test
│ │ └── scala
│ │ └── Example2Test.scala
│ ├── multi-module-not-on-root
│ ├── build.sbt
│ ├── project
│ │ ├── build.properties
│ │ └── plugins.sbt
│ ├── src
│ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example.scala
│ │ └── test
│ │ │ └── scala
│ │ │ └── ExampleTest.scala
│ ├── test
│ ├── test-1
│ │ └── module1
│ │ │ └── src
│ │ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example1.scala
│ │ │ └── test
│ │ │ └── scala
│ │ │ └── Example1Test.scala
│ └── test-2
│ │ └── module2
│ │ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── Example2.scala
│ │ └── test
│ │ └── scala
│ │ └── Example2Test.scala
│ ├── multi-module
│ ├── build.sbt
│ ├── module1
│ │ └── src
│ │ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example1.scala
│ │ │ └── test
│ │ │ └── scala
│ │ │ └── Example1Test.scala
│ ├── module2
│ │ └── src
│ │ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example2.scala
│ │ │ └── test
│ │ │ └── scala
│ │ │ └── Example2Test.scala
│ ├── project
│ │ ├── build.properties
│ │ └── plugins.sbt
│ ├── src
│ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example.scala
│ │ └── test
│ │ │ └── scala
│ │ │ └── ExampleTest.scala
│ └── test
│ ├── sbt-0.13
│ ├── build.sbt
│ ├── project
│ │ ├── build.properties
│ │ └── plugins.sbt
│ ├── src
│ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example.scala
│ │ └── test
│ │ │ └── scala
│ │ │ └── ExampleTest.scala
│ └── test
│ ├── sbt-1.0
│ ├── build.sbt
│ ├── project
│ │ ├── build.properties
│ │ └── plugins.sbt
│ ├── src
│ │ ├── main
│ │ │ └── scala
│ │ │ │ └── Example.scala
│ │ └── test
│ │ │ └── scala
│ │ │ └── ExampleTest.scala
│ └── test
│ └── scala-2.11
│ ├── build.sbt
│ ├── project
│ ├── build.properties
│ └── plugins.sbt
│ ├── src
│ ├── main
│ │ └── scala
│ │ │ └── Example.scala
│ └── test
│ │ └── scala
│ │ └── ExampleTest.scala
│ └── test
└── test
└── scala
└── sbtsonar
├── SonarPluginTest.scala
└── WithFile.scala
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | defaults: &defaults
4 | docker:
5 | - image: circleci/openjdk:8-jdk
6 | working_directory: ~/repo
7 | environment:
8 | TERM: xterm
9 | DEBIAN_FRONTEND: noninteractive
10 | DISABLE_SCALAFMT: true
11 | JVM_OPTS: -Xmx3200m
12 |
13 | jobs:
14 | test:
15 | <<: *defaults
16 | steps:
17 | - checkout
18 | - restore_cache:
19 | keys:
20 | - v1-dependencies-{{ checksum "build.sbt" }}
21 | - v1-dependencies-
22 | - run: sbt ^test:compile
23 | - save_cache:
24 | paths:
25 | - ~/.m2
26 | key: v1-dependencies--{{ checksum "build.sbt" }}
27 | - run: sbt ^test
28 | release:
29 | <<: *defaults
30 | steps:
31 | - checkout
32 | - restore_cache:
33 | keys:
34 | - v1-dependencies-{{ checksum "build.sbt" }}
35 | - v1-dependencies-
36 | - add_ssh_keys:
37 | fingerprints:
38 | - "bf:24:38:ce:25:6b:8c:da:e6:3a:b4:e7:23:66:b6:59"
39 | - run:
40 | name: Set up git
41 | command: |
42 | git config --global user.name "CircleCI"
43 | git config --global user.email "mwz@users.noreply.github.com"
44 | ssh-keyscan -T 15 github.com >> ~/.ssh/known_hosts
45 | - run: sbt 'release with-defaults skip-tests' < /dev/null
46 |
47 | workflows:
48 | version: 2
49 | sbt-sonar:
50 | jobs:
51 | - test
52 | - hold:
53 | type: approval
54 | requires:
55 | - test
56 | filters:
57 | branches:
58 | only: master
59 | - release:
60 | requires:
61 | - hold
62 | filters:
63 | branches:
64 | only: master
65 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | push:
4 | branches: [master]
5 | tags: ["*"]
6 | env:
7 | CI_SNAPSHOT_RELEASE: "^publish"
8 | CI_RELEASE: "^publishSigned"
9 | jobs:
10 | release:
11 | runs-on: ubuntu-20.04
12 | steps:
13 | - uses: actions/checkout@v2
14 | - run: git fetch --prune --unshallow
15 | - uses: olafurpg/setup-scala@v10
16 | with:
17 | java-version: adopt@1.8
18 | - uses: actions/cache@v1
19 | with:
20 | path: ~/.ivy2/cache
21 | key: ivy-${{hashFiles('**/*.sbt')}}
22 | restore-keys: ivy-
23 | - uses: actions/cache@v1
24 | with:
25 | path: ~/.sbt
26 | key: sbt-${{hashFiles('**/*.sbt')}}-${{hashFiles('project/build.properties')}}
27 | restore-keys: sbt-
28 | - run: sbt ci-release
29 | env:
30 | PGP_PASSPHRASE: ${{secrets.PGP_PASSPHRASE}}
31 | PGP_SECRET: ${{secrets.PGP_SECRET}}
32 | SONATYPE_PASSWORD: ${{secrets.SONATYPE_PASSWORD}}
33 | SONATYPE_USERNAME: ${{secrets.SONATYPE_USERNAME}}
34 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 | on:
3 | pull_request:
4 | jobs:
5 | test:
6 | name: Test
7 | runs-on: ubuntu-20.04
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: olafurpg/setup-scala@v10
11 | with:
12 | java-version: adopt@1.8
13 | - uses: actions/cache@v1
14 | with:
15 | path: ~/.ivy2/cache
16 | key: ivy-${{hashFiles('**/*.sbt')}}
17 | restore-keys: |
18 | ivy-
19 | - uses: actions/cache@v1
20 | with:
21 | path: ~/.sbt
22 | key: sbt-${{hashFiles('**/*.sbt')}}-${{hashFiles('project/build.properties')}}
23 | restore-keys: |
24 | sbt-
25 | - run: sbt ^test
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # sbt
2 | .cache
3 | dist
4 | target
5 |
6 | # IDE
7 | .idea
8 | .vscode
9 |
10 | # metals
11 | .bloop
12 | .bsp
13 | .metals
14 | metals.sbt
15 |
16 | # Other
17 | *.log
18 | *.orig
19 | .scannerwork
20 |
--------------------------------------------------------------------------------
/.scalafix.conf:
--------------------------------------------------------------------------------
1 | rules = [
2 | DisableSyntax,
3 | LeakingImplicitClassVal,
4 | NoAutoTupling,
5 | NoValInForComprehension,
6 | ProcedureSyntax,
7 | RemoveUnused,
8 | SortImports
9 | ]
10 |
11 | DisableSyntax.noVars = true
12 | DisableSyntax.noThrows = true
13 | DisableSyntax.noNulls = true
14 | DisableSyntax.noReturns = true
15 | DisableSyntax.noWhileLoops = true
16 | DisableSyntax.noFinalize = true
17 | DisableSyntax.noValPatterns = true
18 | SortImports.blocks = [
19 | "java.",
20 | "scala.",
21 | "*"
22 | ]
23 |
--------------------------------------------------------------------------------
/.scalafmt.conf:
--------------------------------------------------------------------------------
1 | version = "2.7.5"
2 | align = some
3 | align {
4 | arrowEnumeratorGenerator = false
5 | ifWhileOpenParen = false
6 | openParenCallSite = false
7 | openParenDefnSite = false
8 | tokens.add = [
9 | "%",
10 | "%%",
11 | "<-",
12 | {code = "=", owner = "Param"},
13 | {code = "=>", owner = "Case"}
14 | ]
15 | }
16 | assumeStandardLibraryStripMargin = true
17 | continuationIndent.defnSite = 2
18 | continuationIndent.callSite = 2
19 | danglingParentheses = true
20 | docstrings = JavaDoc
21 | indentOperator = spray
22 | maxColumn = 110
23 | project {
24 | git = true
25 | excludeFilters = ["target"]
26 | }
27 | rewrite {
28 | rules = [PreferCurlyFors, RedundantBraces, SortImports]
29 | redundantBraces.maxLines = 1
30 | }
31 | spaces.inImportCurlyBraces = false
32 | unindentTopLevelOperators = true
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
sbt-sonar
2 |
3 | 
4 | [![maven-badge]][maven] [![gitter-badge]][gitter]
5 |
6 | [maven]: https://search.maven.org/artifact/com.sonar-scala/sbt-sonar
7 | [maven-badge]:
8 | https://maven-badges.herokuapp.com/maven-central/com.sonar-scala/sbt-sonar/badge.svg
9 | [bintray]: https://bintray.com/mwz/sbt-plugin-releases/sbt-sonar/_latestVersion
10 | [gitter]: https://gitter.im/sonar-scala/sonar-scala
11 | [gitter-badge]:
12 | https://img.shields.io/gitter/room/sonar-scala/sonar-scala.svg?colorB=46BC99&label=Chat
13 |
14 | sbt-sonar is an sbt plugin, which provides an easy way to integrate Scala
15 | projects with [SonarQube](https://www.sonarqube.org) - a tool for continuous
16 | code inspection and quality management :white_check_mark:.
17 |
18 | Under the hood, it uses the embedded
19 | [sonar-scanner API](https://github.com/SonarSource/sonar-scanner-api) library,
20 | which allows you to run SonarQube scan without the need to have the
21 | sonar-scanner executable installed in your environment.
22 |
23 | This plugin is particularly useful for CI when used together with e.g.
24 | [sbt-release](https://www.github.com/sbt/sbt-release) plugin for an automated
25 | release process in your project, but it can be also used on its own.
26 |
27 | ## Documentation
28 |
29 | See the project website
30 | [sonar-scala.com](https://sonar-scala.com/docs/setup/sbt-sonar) for
31 | documentation.
32 |
33 | ## License
34 |
35 | The project is licensed under the Apache License v2. See the [LICENSE](LICENSE)
36 | file for more details.
37 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | import java.time.Year
2 |
3 | import de.heikoseeberger.sbtheader.License
4 |
5 | enablePlugins(AutomateHeaderPlugin)
6 | enablePlugins(SbtPlugin)
7 |
8 | name := "sbt-sonar"
9 | organization := "com.sonar-scala"
10 | homepage := Some(url("https://github.com/sonar-scala/sbt-sonar"))
11 |
12 | // Licence
13 | organizationName := "All sbt-sonar contributors"
14 | startYear := Some(2016)
15 | licenses := Seq("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0"))
16 | headerLicense := Some(
17 | License.ALv2(
18 | s"${startYear.value.get}-${Year.now}",
19 | organizationName.value
20 | )
21 | )
22 | excludeFilter.in(headerResources) := "*.scala"
23 | scmInfo := Some(
24 | ScmInfo(
25 | url("https://github.com/sonar-scala/sbt-sonar"),
26 | "scm:git:https://github.com/sonar-scala/sbt-sonar.git",
27 | Some("scm:git:git@github.com:sonar-scala/sbt-sonar.git")
28 | )
29 | )
30 | developers := List(
31 | Developer(
32 | "mwz",
33 | "Michael Wizner",
34 | "@mwz",
35 | url("https://github.com/mwz")
36 | )
37 | )
38 |
39 | crossSbtVersions := Seq("0.13.18", "1.5.0")
40 | sbtPlugin := true
41 | scalacOptions ++= Seq(
42 | "-encoding",
43 | "UTF-8",
44 | "-unchecked",
45 | "-deprecation"
46 | )
47 | libraryDependencies ++= List(
48 | "org.sonarsource.scanner.api" % "sonar-scanner-api" % "2.16.1.361" % Compile,
49 | "org.scalatest" %% "scalatest" % "3.2.9" % Test,
50 | "org.scalatestplus" %% "mockito-1-10" % "3.1.0.0" % Test,
51 | "org.mockito" % "mockito-core" % "3.10.0" % Test
52 | )
53 | scalafmtOnCompile in ThisBuild :=
54 | sys.env
55 | .get("CI")
56 | .forall(_.toLowerCase == "false")
57 | cancelable in Global := true
58 |
59 | // Scripted
60 | scriptedLaunchOpts := {
61 | scriptedLaunchOpts.value ++ Seq(
62 | "-Xmx1024M",
63 | "-Dplugin.version=" + version.value,
64 | "-Dsonar.host.url=http://localhost"
65 | )
66 | }
67 | scriptedBufferLog := false
68 |
69 | // Sonatype
70 | sonatypeCredentialHost := "s01.oss.sonatype.org"
71 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.5.2
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.7")
2 | addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.0")
3 | addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2")
4 | addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7")
5 |
--------------------------------------------------------------------------------
/src/main/scala-sbt-0.13/sbtsonar/SbtCompat.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016-2021 All sbt-sonar contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package sbtsonar
18 |
19 | import scala.sys.process.ProcessBuilder
20 |
21 | object SbtCompat {
22 | val Logger = sbt.Logger
23 | val Using = sbt.Using
24 |
25 | def process(process: ProcessBuilder): Stream[String] =
26 | process.lines
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/scala-sbt-1.0/sbtsonar/SbtCompat.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016-2021 All sbt-sonar contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package sbtsonar
18 |
19 | import scala.sys.process.ProcessBuilder
20 |
21 | object SbtCompat {
22 | val Logger = sbt.util.Logger
23 | val Using = sbt.io.Using
24 |
25 | def process(process: ProcessBuilder): Stream[String] =
26 | process.lineStream
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/scala/sbtsonar/SonarPlugin.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016-2021 All sbt-sonar contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package sbtsonar
18 |
19 | import java.nio.file.Paths
20 | import java.util.{Properties => JavaProperties}
21 |
22 | import scala.collection.JavaConverters._
23 | import scala.sys.process.Process
24 | import scala.util.Properties
25 |
26 | import org.sonarsource.scanner.api.{EmbeddedScanner, LogOutput}
27 | import sbt.Keys._
28 | import sbt._
29 |
30 | object SonarPlugin extends AutoPlugin {
31 | private val SonarProjectVersionKey = "sonar.projectVersion"
32 | private val SonarExternalConfigFileName = "sonar-project.properties"
33 | private val ScoverageReport = "scoverage-report/scoverage.xml"
34 | private val ScapegoatReport = "scapegoat-report/scapegoat.xml"
35 |
36 | object autoImport {
37 | val sonarUseExternalConfig: SettingKey[Boolean] = settingKey(
38 | "Whether to use an external sonar-project.properties file instead of the properties defined in the sonarProperties Map."
39 | )
40 | val sonarUseSonarScannerCli: SettingKey[Boolean] = settingKey(
41 | "Whether to use a standalone sonar-scanner CLI instead of the embedded sonar-scanner API."
42 | )
43 | val sonarExpectSonarQubeCommunityPlugin: SettingKey[Boolean] = settingKey(
44 | "Whether to expect the target SonarQube server to run SonarScala (vendor plugin) or sonar-scala (community plugin)"
45 | )
46 | val sonarProperties: SettingKey[Map[String, String]] = settingKey(
47 | "SonarScanner configuration properties."
48 | )
49 | val sonarScan: TaskKey[Unit] = taskKey(
50 | "Update project version in sonar-project.properties and run sonar scanner process."
51 | )
52 | }
53 |
54 | import autoImport._
55 |
56 | override def trigger: PluginTrigger = allRequirements
57 |
58 | override def projectSettings =
59 | Seq(
60 | sonarUseExternalConfig := false,
61 | sonarUseSonarScannerCli := false,
62 | // true for backwards compatibility
63 | sonarExpectSonarQubeCommunityPlugin := true,
64 | sonarProperties := (
65 | Seq(
66 | "sonar.projectName" -> name.value,
67 | "sonar.projectKey" -> normalizedName.value,
68 | "sonar.sourceEncoding" -> "UTF-8",
69 | "sonar.scala.version" -> scalaVersion.value,
70 | "sonar.projectBaseDir" -> baseDirectory.value.toString
71 | ) ++
72 | // Base sources directory.
73 | sourcesDir(baseDirectory.value, (scalaSource in Compile).value) ++
74 |
75 | // Base tests directory.
76 | testsDir(baseDirectory.value, (scalaSource in Test).value) ++
77 |
78 | // Scoverage & Scapegoat report directories.
79 | reports(
80 | baseDirectory.value,
81 | (crossTarget in Compile).value,
82 | sonarExpectSonarQubeCommunityPlugin.value
83 | )
84 | ).toMap,
85 | sonarScan := {
86 | implicit val log: Logger = streams.value.log
87 |
88 | // Allow to set sonar properties via system properties
89 | // [https://docs.sonarqube.org/display/SONAR/Analysis+Parameters]
90 | val systemProperties: Map[String, String] =
91 | sys.props.filterKeys(_.startsWith("sonar.")).toMap
92 |
93 | if (sonarUseSonarScannerCli.value)
94 | useStandaloneScanner(
95 | sonarUseExternalConfig.value,
96 | baseDirectory.value,
97 | version.value,
98 | sonarProperties.value,
99 | systemProperties
100 | )
101 | else {
102 | val logOutput: LogOutput = SonarSbtLogOutput(systemProperties)
103 | val embeddedScanner: EmbeddedScanner =
104 | EmbeddedScanner
105 | .create(
106 | "sbt-sonar",
107 | getClass.getPackage.getImplementationVersion,
108 | logOutput
109 | )
110 |
111 | useEmbeddedScanner(
112 | sonarUseExternalConfig.value,
113 | new File(baseDirectory.value, SonarExternalConfigFileName),
114 | version.value,
115 | sonarProperties.value,
116 | systemProperties,
117 | embeddedScanner
118 | )
119 | }
120 | }
121 | )
122 |
123 | private[sbtsonar] def sourcesDir(baseDir: File, scalaSources: File): Option[(String, String)] =
124 | IO.relativizeFile(baseDir, scalaSources).map("sonar.sources" -> _.toString)
125 |
126 | private[sbtsonar] def testsDir(baseDir: File, scalaTests: File): Option[(String, String)] =
127 | IO.relativizeFile(baseDir, scalaTests).map("sonar.tests" -> _.toString)
128 |
129 | private[sbtsonar] def reports(
130 | baseDir: File,
131 | crossTarget: File,
132 | expectSonarQubeCommunityPlugin: Boolean
133 | ): Seq[(String, String)] = {
134 | val (scoverageReportKey, scapegoatReportKey) = {
135 | if (expectSonarQubeCommunityPlugin)
136 | ("sonar.scala.scoverage.reportPath", "sonar.scala.scapegoat.reportPath")
137 | else
138 | ("sonar.scala.coverage.reportPaths", "sonar.scala.scapegoat.reportPaths")
139 | }
140 | IO.relativizeFile(baseDir, crossTarget)
141 | .map { dir =>
142 | Seq(
143 | scoverageReportKey -> new File(dir, ScoverageReport).toString,
144 | scapegoatReportKey -> new File(dir, ScapegoatReport).toString
145 | )
146 | }
147 | .toSeq
148 | .flatten
149 | }
150 |
151 | private[sbtsonar] def updatePropertiesFile(baseDir: File, fileName: String, version: String): Unit = {
152 | val sonarPropsFile = new File(baseDir, fileName)
153 | val sonarProps: List[String] = IO.readLines(sonarPropsFile)
154 |
155 | def loop(lines: List[String]): List[String] = {
156 | lines match {
157 | case h :: tail if h.contains(SonarProjectVersionKey) =>
158 | s"$SonarProjectVersionKey=$version" :: tail
159 | case h :: tail =>
160 | h :: loop(tail)
161 | case _ =>
162 | Nil
163 | }
164 | }
165 |
166 | // Update sonar project version.
167 | val updatedSonarProps: List[String] = loop(sonarProps)
168 | IO.writeLines(sonarPropsFile, updatedSonarProps)
169 | }
170 |
171 | private[sbtsonar] def sonarScannerArgs(
172 | sonarUseExternalConfig: Boolean,
173 | sonarProperties: Map[String, String],
174 | systemProperties: Map[String, String],
175 | version: String
176 | ): List[String] = {
177 | val properties: Map[String, String] =
178 | if (sonarUseExternalConfig) systemProperties
179 | else (sonarProperties + (SonarProjectVersionKey -> version)) ++ systemProperties
180 |
181 | properties.map { case (key, value) =>
182 | s"-D$key=$value"
183 | }.toList
184 | }
185 |
186 | private[sbtsonar] def useStandaloneScanner(
187 | sonarUseExternalConfig: Boolean,
188 | baseDirectory: File,
189 | version: String,
190 | sonarProperties: Map[String, String],
191 | systemProperties: Map[String, String]
192 | )(implicit log: Logger): Unit = {
193 | val sonarHome: String =
194 | sys.env
195 | .get("SONAR_SCANNER_HOME")
196 | .orElse(sys.props.get("sonarScanner.home"))
197 | .getOrElse(
198 | sys.error(
199 | "SONAR_SCANNER_HOME environment variable or sonarScanner.home system property not defined."
200 | )
201 | )
202 |
203 | // Update the external properties file if the sonarUseExternalConfig is set to true.
204 | if (sonarUseExternalConfig)
205 | updatePropertiesFile(baseDirectory, SonarExternalConfigFileName, version)
206 |
207 | val args: Seq[String] =
208 | sonarScannerArgs(sonarUseExternalConfig, sonarProperties, systemProperties, version)
209 |
210 | val executablePath: String =
211 | if (Properties.isWin) "bin/sonar-scanner.bat"
212 | else "bin/sonar-scanner"
213 |
214 | val sonarScanner: String =
215 | Paths
216 | .get(sonarHome)
217 | .resolve(executablePath)
218 | .toAbsolutePath
219 | .toString
220 |
221 | // Run sonar-scanner executable.
222 | SbtCompat
223 | .process(Process(sonarScanner, args))
224 | .foreach(log.info(_))
225 | }
226 |
227 | private[sbtsonar] def propertiesFromFile(file: File): Map[String, String] = {
228 | SbtCompat.Using.fileInputStream(file) { stream =>
229 | val props = new JavaProperties
230 | props.load(stream)
231 | props.asScala.toMap
232 | }
233 | }
234 |
235 | private[sbtsonar] def useEmbeddedScanner(
236 | useExternalConfig: Boolean,
237 | propertiesFile: File,
238 | version: String,
239 | sonarProperties: Map[String, String],
240 | systemProperties: Map[String, String],
241 | embeddedScanner: EmbeddedScanner
242 | )(implicit log: Logger): Unit = {
243 | val properties: Map[String, String] =
244 | if (useExternalConfig)
245 | // Overwrite project version.
246 | (propertiesFromFile(propertiesFile) + (SonarProjectVersionKey -> version)) ++ systemProperties
247 | else (sonarProperties + (SonarProjectVersionKey -> version)) ++ systemProperties
248 |
249 | val configuredScanner =
250 | embeddedScanner.addGlobalProperties(properties.asJava)
251 |
252 | configuredScanner.start()
253 | log.info("SonarQube server version: " + configuredScanner.serverVersion)
254 | configuredScanner.execute(properties.asJava)
255 | }
256 | }
257 |
--------------------------------------------------------------------------------
/src/main/scala/sbtsonar/SonarSbtLogOutput.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016-2021 All sbt-sonar contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package sbtsonar
18 |
19 | import org.sonarsource.scanner.api.LogOutput
20 | import sbt.{Level, Logger}
21 |
22 | object SonarSbtLogOutput {
23 | def apply(props: Map[String, String])(implicit logger: Logger): LogOutput =
24 | new LogOutput {
25 | def log(formattedMessage: java.lang.String, level: LogOutput.Level): Unit =
26 | level match {
27 | case LogOutput.Level.TRACE | LogOutput.Level.DEBUG =>
28 | val verbose: Boolean =
29 | props
30 | .get("sonar.verbose")
31 | .exists(_.toLowerCase == "true")
32 | val debugTrace: Boolean =
33 | props
34 | .get("sonar.log.level")
35 | .map(_.toLowerCase)
36 | .exists(v => v == "debug" || v == "trace")
37 | // Log only if "sonar.verbose" is "true"
38 | // or "sonar.log.level" is either "DEBUG" or "TRACE".
39 | if (verbose || debugTrace)
40 | logger.log(Level.Info, formattedMessage)
41 | case LogOutput.Level.ERROR =>
42 | logger.log(Level.Error, formattedMessage)
43 | case LogOutput.Level.WARN =>
44 | logger.log(Level.Warn, formattedMessage)
45 | case LogOutput.Level.INFO =>
46 | logger.log(Level.Info, formattedMessage)
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/external-config/build.sbt:
--------------------------------------------------------------------------------
1 | import sbtsonar.SonarPlugin.autoImport.sonarUseExternalConfig
2 |
3 | name := "external-config"
4 |
5 | version := "0.1"
6 |
7 | scalaVersion := "2.12.4"
8 |
9 | scapegoatVersion in ThisBuild := "1.3.3"
10 |
11 | sonarUseExternalConfig := true
12 |
13 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
14 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/external-config/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.5.0
2 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/external-config/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val pluginVersion = sys.props.getOrElse(
2 | "plugin.version",
3 | throw new RuntimeException(
4 | """|The system property 'plugin.version' is not defined.
5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin))
6 |
7 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.7")
8 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
9 | addSbtPlugin("com.sonar-scala" % "sbt-sonar" % pluginVersion)
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/external-config/sonar-project.properties:
--------------------------------------------------------------------------------
1 | sonar.projectName=external-config
2 | sonar.projectKey=external-config
3 | sonar.projectVersion=0
4 | sonar.sources=src/main/scala
5 | sonar.tests=src/test/scala
6 | sonar.sourceEncoding=UTF-8
7 | sonar.scala.version=2.12
8 | sonar.scala.scoverage.reportPath=target/scala-2.12/scoverage-report/scoverage.xml
9 | sonar.scala.scapegoat.reportPath=target/scala-2.12/scapegoat-report/scapegoat.xml
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/external-config/src/main/scala/Example.scala:
--------------------------------------------------------------------------------
1 | object Example {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/external-config/src/test/scala/ExampleTest.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class ExampleTest extends FlatSpec with Matchers {
4 | "Example" should "sum two numbers" in {
5 | Example.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/external-config/test:
--------------------------------------------------------------------------------
1 | # Test against sbt 1.0 & scala 2.12.
2 | # Runs scoverage, scapegoat & sonarScan.
3 |
4 | > clean
5 | > coverage
6 | > test
7 | > coverageReport
8 | > coverageOff
9 | > scapegoat
10 | > sonarScan
11 | $ exists .scannerwork/report-task.txt
12 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/build.sbt:
--------------------------------------------------------------------------------
1 | import sbtsonar.SonarPlugin.autoImport.sonarProperties
2 | import sbtsonar.SonarPlugin.autoImport.sonarScan
3 |
4 | lazy val baseSettings = Seq(
5 | version := "0.1",
6 | scalaVersion := "2.12.4",
7 | scapegoatVersion in ThisBuild := "1.3.3",
8 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
9 | )
10 | lazy val sonarSettings = Seq(
11 | sonarProperties ++= Map(
12 | "sonar.projectName" -> "Independent projects"
13 | )
14 | )
15 |
16 | lazy val module1 = (project in file("test-1/module1"))
17 | .settings(baseSettings)
18 | .settings(name := "module2indep")
19 |
20 | lazy val module2 = (project in file("test-2/module2"))
21 | .settings(baseSettings)
22 | .settings(name := "module1indep")
23 |
24 | lazy val independantProjects = (project in file("."))
25 | .aggregate(module1, module2)
26 | .settings(name := "independent-projects")
27 | .settings(baseSettings)
28 | .settings(sonarSettings)
29 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.5.0
2 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val pluginVersion = sys.props.getOrElse(
2 | "plugin.version",
3 | throw new RuntimeException(
4 | """|The system property 'plugin.version' is not defined.
5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin))
6 |
7 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.7")
8 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
9 | addSbtPlugin("com.sonar-scala" % "sbt-sonar" % pluginVersion)
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/src/main/scala/Example.scala:
--------------------------------------------------------------------------------
1 | object Example {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/src/test/scala/ExampleTest.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class ExampleTest extends FlatSpec with Matchers {
4 | "Example" should "sum two numbers" in {
5 | Example.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/test:
--------------------------------------------------------------------------------
1 | # Test against sbt 1.0 & scala 2.12.
2 | # Runs scoverage, scapegoat & sonarScan.
3 |
4 | > clean
5 | > coverage
6 | > test
7 | > coverageReport
8 | > coverageOff
9 | > scapegoat
10 | > sonarScan
11 | $ exists .scannerwork/report-task.txt
12 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/test-1/module1/src/main/scala/Example1.scala:
--------------------------------------------------------------------------------
1 | object Example1 {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/test-1/module1/src/test/scala/Example1Test.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class Example1Test extends FlatSpec with Matchers {
4 | "Example1" should "sum two numbers" in {
5 | Example1.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/test-2/module2/src/main/scala/Example2.scala:
--------------------------------------------------------------------------------
1 | object Example2 {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/independent-projects/test-2/module2/src/test/scala/Example2Test.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class Example2Test extends FlatSpec with Matchers {
4 | "Example2" should "sum two numbers" in {
5 | // No coverage!
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/build.sbt:
--------------------------------------------------------------------------------
1 | import sbtsonar.SonarPlugin.autoImport.sonarProperties
2 | import sbtsonar.SonarPlugin.autoImport.sonarScan
3 |
4 | lazy val baseSettings = Seq(
5 | version := "0.1",
6 | scalaVersion := "2.12.4",
7 | scapegoatVersion in ThisBuild := "1.3.3",
8 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
9 | )
10 | lazy val sonarSettings = Seq(
11 | sonarProperties ++= Map(
12 | "sonar.projectName" -> "Multi Module not in root with correct config",
13 | "sonar.modules" -> "module1nirwcc,module2nirwcc",
14 | "module1nirwcc.sonar.projectName" -> "Module 1 not in root with correct config",
15 | "module2nirwcc.sonar.projectName" -> "Module 2 not in root with correct config",
16 | "module2nirwcc.sonar.projectBaseDir" -> "test-2/module2",
17 | "module1nirwcc.sonar.projectBaseDir" -> "test-1/module1"
18 | )
19 | )
20 |
21 | lazy val module1 = (project in file("test-1/module1"))
22 | .settings(baseSettings)
23 | .settings(name := "module2nirwcc")
24 |
25 | lazy val module2 = (project in file("test-2/module2"))
26 | .settings(baseSettings)
27 | .settings(name := "module1nirwcc")
28 |
29 | lazy val multiModule = (project in file("."))
30 | .aggregate(module1, module2)
31 | .settings(name := "multi-module-not-in-root-with-correct-config")
32 | .settings(baseSettings)
33 | .settings(sonarSettings)
34 | .settings(aggregate in sonarScan := false)
35 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.5.0
2 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val pluginVersion = sys.props.getOrElse(
2 | "plugin.version",
3 | throw new RuntimeException(
4 | """|The system property 'plugin.version' is not defined.
5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin))
6 |
7 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.7")
8 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
9 | addSbtPlugin("com.sonar-scala" % "sbt-sonar" % pluginVersion)
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/src/main/scala/Example.scala:
--------------------------------------------------------------------------------
1 | object Example {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/src/test/scala/ExampleTest.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class ExampleTest extends FlatSpec with Matchers {
4 | "Example" should "sum two numbers" in {
5 | Example.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/test:
--------------------------------------------------------------------------------
1 | # Test against sbt 1.0 & scala 2.12.
2 | # Runs scoverage, scapegoat & sonarScan.
3 |
4 | > clean
5 | > coverage
6 | > test
7 | > coverageReport
8 | > coverageOff
9 | > scapegoat
10 | > sonarScan
11 | $ exists .scannerwork/report-task.txt
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/test-1/module1/src/main/scala/Example1.scala:
--------------------------------------------------------------------------------
1 | object Example1 {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/test-1/module1/src/test/scala/Example1Test.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class Example1Test extends FlatSpec with Matchers {
4 | "Example1" should "sum two numbers" in {
5 | Example1.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/test-2/module2/src/main/scala/Example2.scala:
--------------------------------------------------------------------------------
1 | object Example2 {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root-with-correct-config/test-2/module2/src/test/scala/Example2Test.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class Example2Test extends FlatSpec with Matchers {
4 | "Example2" should "sum two numbers" in {
5 | // No coverage!
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/build.sbt:
--------------------------------------------------------------------------------
1 | import sbtsonar.SonarPlugin.autoImport.sonarProperties
2 | import sbtsonar.SonarPlugin.autoImport.sonarScan
3 |
4 | lazy val baseSettings = Seq(
5 | version := "0.1",
6 | scalaVersion := "2.12.4",
7 | scapegoatVersion in ThisBuild := "1.3.3",
8 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
9 | )
10 | lazy val sonarSettings = Seq(
11 | sonarProperties ++= Map(
12 | "sonar.projectName" -> "Multi Module not in root",
13 | "sonar.modules" -> "module1nir,module2nir",
14 | "module1.sonar.projectName" -> "Module 1 not in root",
15 | "module2.sonar.projectName" -> "Module 2 not in root"
16 | )
17 | )
18 |
19 | lazy val module1 = (project in file("test-1/module1"))
20 | .settings(baseSettings)
21 | .settings(name := "module1nir")
22 |
23 | lazy val module2 = (project in file("test-2/module2"))
24 | .settings(baseSettings)
25 | .settings(name := "module2nir")
26 |
27 | lazy val multiModule = (project in file("."))
28 | .aggregate(module1, module2)
29 | .settings(name := "multi-module-not-in-root")
30 | .settings(baseSettings)
31 | .settings(sonarSettings)
32 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.5.0
2 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val pluginVersion = sys.props.getOrElse(
2 | "plugin.version",
3 | throw new RuntimeException(
4 | """|The system property 'plugin.version' is not defined.
5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin))
6 |
7 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.7")
8 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
9 | addSbtPlugin("com.sonar-scala" % "sbt-sonar" % pluginVersion)
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/src/main/scala/Example.scala:
--------------------------------------------------------------------------------
1 | object Example {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/src/test/scala/ExampleTest.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class ExampleTest extends FlatSpec with Matchers {
4 | "Example" should "sum two numbers" in {
5 | Example.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/test:
--------------------------------------------------------------------------------
1 | # Test against sbt 1.0 & scala 2.12.
2 | # Runs scoverage, scapegoat & sonarScan.
3 |
4 | > clean
5 | > coverage
6 | > test
7 | > coverageReport
8 | > coverageOff
9 | > scapegoat
10 | -> sonarScan
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/test-1/module1/src/main/scala/Example1.scala:
--------------------------------------------------------------------------------
1 | object Example1 {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/test-1/module1/src/test/scala/Example1Test.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class Example1Test extends FlatSpec with Matchers {
4 | "Example1" should "sum two numbers" in {
5 | Example1.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/test-2/module2/src/main/scala/Example2.scala:
--------------------------------------------------------------------------------
1 | object Example2 {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module-not-on-root/test-2/module2/src/test/scala/Example2Test.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class Example2Test extends FlatSpec with Matchers {
4 | "Example2" should "sum two numbers" in {
5 | // No coverage!
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/build.sbt:
--------------------------------------------------------------------------------
1 | import sbtsonar.SonarPlugin.autoImport.sonarProperties
2 | import sbtsonar.SonarPlugin.autoImport.sonarScan
3 |
4 | lazy val baseSettings = Seq(
5 | version := "0.1",
6 | scalaVersion := "2.12.4",
7 | scapegoatVersion in ThisBuild := "1.3.3",
8 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
9 | )
10 | lazy val sonarSettings = Seq(
11 | sonarProperties ++= Map(
12 | "sonar.projectName" -> "Multi Module",
13 | "sonar.modules" -> "module1,module2",
14 | "module1.sonar.projectName" -> "Module 1",
15 | "module2.sonar.projectName" -> "Module 2"
16 | )
17 | )
18 |
19 | lazy val module1 = (project in file("module1"))
20 | .settings(baseSettings)
21 | .settings(name := "module2")
22 |
23 | lazy val module2 = (project in file("module2"))
24 | .settings(baseSettings)
25 | .settings(name := "module1")
26 |
27 | lazy val multiModule = (project in file("."))
28 | .aggregate(module1, module2)
29 | .settings(name := "multi-module")
30 | .settings(baseSettings)
31 | .settings(sonarSettings)
32 | .settings(aggregate in sonarScan := false)
33 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/module1/src/main/scala/Example1.scala:
--------------------------------------------------------------------------------
1 | object Example1 {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/module1/src/test/scala/Example1Test.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class Example1Test extends FlatSpec with Matchers {
4 | "Example1" should "sum two numbers" in {
5 | Example1.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/module2/src/main/scala/Example2.scala:
--------------------------------------------------------------------------------
1 | object Example2 {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/module2/src/test/scala/Example2Test.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class Example2Test extends FlatSpec with Matchers {
4 | "Example2" should "sum two numbers" in {
5 | // No coverage!
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.5.0
2 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val pluginVersion = sys.props.getOrElse(
2 | "plugin.version",
3 | throw new RuntimeException(
4 | """|The system property 'plugin.version' is not defined.
5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin))
6 |
7 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.7")
8 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
9 | addSbtPlugin("com.sonar-scala" % "sbt-sonar" % pluginVersion)
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/src/main/scala/Example.scala:
--------------------------------------------------------------------------------
1 | object Example {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/src/test/scala/ExampleTest.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class ExampleTest extends FlatSpec with Matchers {
4 | "Example" should "sum two numbers" in {
5 | Example.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/multi-module/test:
--------------------------------------------------------------------------------
1 | # Test against sbt 1.0 & scala 2.12.
2 | # Runs scoverage, scapegoat & sonarScan.
3 |
4 | > clean
5 | > coverage
6 | > test
7 | > coverageReport
8 | > coverageOff
9 | > scapegoat
10 | > sonarScan
11 | $ exists .scannerwork/report-task.txt
12 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-0.13/build.sbt:
--------------------------------------------------------------------------------
1 | name := "sbt-0.13"
2 |
3 | version := "0.1"
4 |
5 | scalaVersion := "2.12.4"
6 |
7 | scapegoatVersion := "1.3.3"
8 |
9 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-0.13/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.16
2 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-0.13/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val pluginVersion = sys.props.getOrElse(
2 | "plugin.version",
3 | throw new RuntimeException(
4 | """|The system property 'plugin.version' is not defined.
5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin))
6 |
7 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.4")
8 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
9 | addSbtPlugin("com.github.mwz" % "sbt-sonar" % pluginVersion)
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-0.13/src/main/scala/Example.scala:
--------------------------------------------------------------------------------
1 | object Example {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-0.13/src/test/scala/ExampleTest.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class ExampleTest extends FlatSpec with Matchers {
4 | "Example" should "sum two numbers" in {
5 | Example.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-0.13/test:
--------------------------------------------------------------------------------
1 | # Test against sbt 0.13 & scala 2.12.
2 | # Runs scoverage, scapegoat & sonarScan.
3 |
4 | > clean
5 | > coverage
6 | > test
7 | > coverageReport
8 | > coverageOff
9 | > scapegoat
10 | > sonarScan
11 | $ exists .scannerwork/report-task.txt
12 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-1.0/build.sbt:
--------------------------------------------------------------------------------
1 | name := "sbt-1.0"
2 |
3 | version := "0.1"
4 |
5 | scalaVersion := "2.12.4"
6 |
7 | scapegoatVersion in ThisBuild := "1.3.3"
8 |
9 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-1.0/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.5.0
2 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-1.0/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val pluginVersion = sys.props.getOrElse(
2 | "plugin.version",
3 | throw new RuntimeException(
4 | """|The system property 'plugin.version' is not defined.
5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin))
6 |
7 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.7")
8 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
9 | addSbtPlugin("com.sonar-scala" % "sbt-sonar" % pluginVersion)
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-1.0/src/main/scala/Example.scala:
--------------------------------------------------------------------------------
1 | object Example {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-1.0/src/test/scala/ExampleTest.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class ExampleTest extends FlatSpec with Matchers {
4 | "Example" should "sum two numbers" in {
5 | Example.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/sbt-1.0/test:
--------------------------------------------------------------------------------
1 | # Test against sbt 1.0 & scala 2.12.
2 | # Runs scoverage, scapegoat & sonarScan.
3 |
4 | > clean
5 | > coverage
6 | > test
7 | > coverageReport
8 | > coverageOff
9 | > scapegoat
10 | > sonarScan
11 | $ exists .scannerwork/report-task.txt
12 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/scala-2.11/build.sbt:
--------------------------------------------------------------------------------
1 | name := "scala-2.11"
2 |
3 | version := "0.1"
4 |
5 | scalaVersion := "2.11.11"
6 |
7 | scapegoatVersion := "1.3.3"
8 |
9 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/scala-2.11/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.16
2 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/scala-2.11/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val pluginVersion = sys.props.getOrElse(
2 | "plugin.version",
3 | throw new RuntimeException(
4 | """|The system property 'plugin.version' is not defined.
5 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin))
6 |
7 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.4")
8 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
9 | addSbtPlugin("com.github.mwz" % "sbt-sonar" % pluginVersion)
10 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/scala-2.11/src/main/scala/Example.scala:
--------------------------------------------------------------------------------
1 | object Example {
2 | def sum(a: Int, b: Int) = a + b
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/scala-2.11/src/test/scala/ExampleTest.scala:
--------------------------------------------------------------------------------
1 | import org.scalatest._
2 |
3 | class ExampleTest extends FlatSpec with Matchers {
4 | "Example" should "sum two numbers" in {
5 | Example.sum(1, 5) shouldBe 6
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/sbt-sonar/scala-2.11/test:
--------------------------------------------------------------------------------
1 | # Test against sbt 0.13 & scala 2.11.
2 | # Runs scoverage, scapegoat & sonarScan.
3 |
4 | > clean
5 | > coverage
6 | > test
7 | > coverageReport
8 | > coverageOff
9 | > scapegoat
10 | > sonarScan
11 | $ exists .scannerwork/report-task.txt
12 |
--------------------------------------------------------------------------------
/src/test/scala/sbtsonar/SonarPluginTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016-2021 All sbt-sonar contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package sbtsonar
18 |
19 | import java.io.File
20 | import java.nio.file.Paths
21 |
22 | import scala.collection.JavaConverters._
23 | import scala.util.Properties
24 |
25 | import SbtCompat.Logger
26 | import org.mockito.ArgumentMatchers._
27 | import org.mockito.Mockito._
28 | import org.scalatestplus.mockito.MockitoSugar
29 | import org.sonarsource.scanner.api.EmbeddedScanner
30 | import sbt.IO
31 | import org.scalatest.flatspec.AnyFlatSpec
32 | import org.scalatest.matchers.should.Matchers
33 |
34 | class SonarPluginTest extends AnyFlatSpec with Matchers with MockitoSugar with WithFile {
35 |
36 | val sonarPropertiesFileContent =
37 | """# Root project information
38 | |sonar.projectKey=org.mycompany.myproject
39 | |sonar.projectName=My Project
40 | |sonar.projectVersion=1.0
41 | |
42 | |# Some properties that will be inherited by the modules
43 | |sonar.sources=src
44 | |
45 | |# List of the module identifiers
46 | |sonar.modules=module1,module2
47 | |
48 | |# Properties can obviously be overriden for
49 | |# each module - just prefix them with the module ID
50 | |module1.sonar.projectName=Module 1
51 | |module2.sonar.projectName=Module 2""".stripMargin
52 |
53 | "sourcesDir" should "resolve correctly the relative path" in {
54 | SonarPlugin.sourcesDir(new File("."), new File("./a/b")) shouldBe
55 | Some("sonar.sources" -> Paths.get("a/b").toString)
56 | }
57 |
58 | "testsDir" should "resolve correctly the relative path" in {
59 | SonarPlugin.testsDir(new File("."), new File("./a/b")) shouldBe
60 | Some("sonar.tests" -> Paths.get("a/b").toString)
61 | }
62 |
63 | "reports" should "resolve correctly the relative path to the report files" in {
64 | SonarPlugin.reports(new File("."), new File("./a/b"), expectSonarQubeCommunityPlugin = true) shouldBe
65 | Seq(
66 | "sonar.scala.scoverage.reportPath" -> Paths.get("a/b/scoverage-report/scoverage.xml").toString,
67 | "sonar.scala.scapegoat.reportPath" -> Paths.get("a/b/scapegoat-report/scapegoat.xml").toString
68 | )
69 |
70 | SonarPlugin.reports(new File("."), new File("./a/b"), expectSonarQubeCommunityPlugin = false) shouldBe
71 | Seq(
72 | "sonar.scala.coverage.reportPaths" -> Paths.get("a/b/scoverage-report/scoverage.xml").toString,
73 | "sonar.scala.scapegoat.reportPaths" -> Paths.get("a/b/scapegoat-report/scapegoat.xml").toString
74 | )
75 | }
76 |
77 | "updatePropertiesFile" should
78 | "update the sonar properties file with the current project version" in withFile { file =>
79 | val expectedContent =
80 | """# Root project information
81 | |sonar.projectKey=org.mycompany.myproject
82 | |sonar.projectName=My Project
83 | |sonar.projectVersion=123.456.789
84 | |
85 | |# Some properties that will be inherited by the modules
86 | |sonar.sources=src
87 | |
88 | |# List of the module identifiers
89 | |sonar.modules=module1,module2
90 | |
91 | |# Properties can obviously be overriden for
92 | |# each module - just prefix them with the module ID
93 | |module1.sonar.projectName=Module 1
94 | |module2.sonar.projectName=Module 2""".stripMargin
95 |
96 | IO.writeLines(file, sonarPropertiesFileContent.split(Properties.lineSeparator).toSeq)
97 | SonarPlugin.updatePropertiesFile(file.getParentFile, file.getName, "123.456.789")
98 |
99 | IO.readLines(file) shouldBe expectedContent.split("\\r?\\n").toList
100 | }
101 |
102 | "sonarScannerArgs" should
103 | "convert a map with sonar config properties into a sequence of java env properties " in {
104 | val sonarProperties = Map("a" -> "b", "c.d" -> "e.f")
105 | val systemProperties = Map("sonar.host.url" -> "http://localhost", "sonar.verbose" -> "true")
106 |
107 | val noExternalConfig = SonarPlugin.sonarScannerArgs(
108 | sonarUseExternalConfig = false,
109 | sonarProperties = sonarProperties,
110 | systemProperties = systemProperties,
111 | version = "987.654.321"
112 | )
113 | noExternalConfig should contain theSameElementsAs Seq(
114 | "-Da=b",
115 | "-Dc.d=e.f",
116 | "-Dsonar.projectVersion=987.654.321",
117 | "-Dsonar.host.url=http://localhost",
118 | "-Dsonar.verbose=true"
119 | )
120 |
121 | val withExternalConfig = SonarPlugin.sonarScannerArgs(
122 | sonarUseExternalConfig = true,
123 | sonarProperties = sonarProperties,
124 | systemProperties = systemProperties,
125 | version = "987.654.321"
126 | )
127 | withExternalConfig should contain theSameElementsAs Seq(
128 | "-Dsonar.host.url=http://localhost",
129 | "-Dsonar.verbose=true"
130 | )
131 | }
132 |
133 | "propertiesFromFile" should "read sonar properties from a file" in withFile { file =>
134 | IO.writeLines(file, sonarPropertiesFileContent.split(Properties.lineSeparator).toSeq)
135 |
136 | val expected = Map(
137 | "sonar.projectKey" -> "org.mycompany.myproject",
138 | "sonar.projectName" -> "My Project",
139 | "sonar.projectVersion" -> "1.0",
140 | "sonar.sources" -> "src",
141 | "sonar.modules" -> "module1,module2",
142 | "module1.sonar.projectName" -> "Module 1",
143 | "module2.sonar.projectName" -> "Module 2"
144 | )
145 |
146 | SonarPlugin.propertiesFromFile(file) should contain theSameElementsAs expected
147 | }
148 |
149 | "useEmbeddedScanner" should "start the analysis using the embedded scanner" in {
150 | implicit val log = Logger.Null
151 | val embeddedScanner = mock[EmbeddedScanner]
152 | when(embeddedScanner.addGlobalProperties(any())).thenReturn(embeddedScanner)
153 |
154 | SonarPlugin.useEmbeddedScanner(
155 | useExternalConfig = false,
156 | propertiesFile = new File("."),
157 | version = "1.2.3",
158 | sonarProperties = Map("sonar.property1" -> "value1"),
159 | systemProperties = Map("sonar.property2" -> "value2"),
160 | embeddedScanner
161 | )
162 |
163 | val properties = Map(
164 | "sonar.property1" -> "value1",
165 | "sonar.property2" -> "value2",
166 | "sonar.projectVersion" -> "1.2.3"
167 | )
168 | verify(embeddedScanner).addGlobalProperties(properties.asJava)
169 | verify(embeddedScanner).start
170 | verify(embeddedScanner).execute(properties.asJava)
171 | }
172 |
173 | "useEmbeddedScanner" should "respect properties from an external file" in withFile { file =>
174 | IO.writeLines(file, sonarPropertiesFileContent.split(Properties.lineSeparator).toSeq)
175 |
176 | implicit val log = Logger.Null
177 | val embeddedScanner = mock[EmbeddedScanner]
178 | when(embeddedScanner.addGlobalProperties(any())).thenReturn(embeddedScanner)
179 |
180 | SonarPlugin.useEmbeddedScanner(
181 | useExternalConfig = true,
182 | propertiesFile = file,
183 | version = "1.2.3",
184 | sonarProperties = Map("sonar.property1" -> "value1"),
185 | systemProperties = Map("sonar.property2" -> "value2"),
186 | embeddedScanner
187 | )
188 |
189 | val properties = Map(
190 | "sonar.projectKey" -> "org.mycompany.myproject",
191 | "sonar.projectName" -> "My Project",
192 | "sonar.sources" -> "src",
193 | "sonar.modules" -> "module1,module2",
194 | "module1.sonar.projectName" -> "Module 1",
195 | "module2.sonar.projectName" -> "Module 2",
196 | "sonar.projectVersion" -> "1.2.3",
197 | "sonar.property2" -> "value2"
198 | )
199 | verify(embeddedScanner).addGlobalProperties(properties.asJava)
200 | verify(embeddedScanner).start
201 | verify(embeddedScanner).execute(properties.asJava)
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/test/scala/sbtsonar/WithFile.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016-2021 All sbt-sonar contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package sbtsonar
18 |
19 | import java.io.File
20 | import java.nio.file.Files
21 |
22 | import sbt.IO
23 |
24 | trait WithFile {
25 | def withFile(test: File => Any): Unit = {
26 | val file = Files.createTempFile("sonar-project", ".properties").toFile
27 | try test(file)
28 | finally IO.delete(file)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------