-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial implementation for wooga.gradle.unity-sonarqube
- Loading branch information
1 parent
a09b9ae
commit 7d90841
Showing
8 changed files
with
451 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
...egrationTest/groovy/wooga/gradle/unitysonar/UnitySonarqubeExtensionIntegrationSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package wooga.gradle.unitysonar | ||
|
||
import com.wooga.gradle.test.IntegrationSpec | ||
import com.wooga.gradle.test.PropertyLocation | ||
import com.wooga.gradle.test.writers.PropertyGetterTaskWriter | ||
import com.wooga.gradle.test.writers.PropertySetterWriter | ||
import spock.lang.Unroll | ||
|
||
import static com.wooga.gradle.test.writers.PropertySetInvocation.getAssignment | ||
import static com.wooga.gradle.test.writers.PropertySetInvocation.getNone | ||
import static com.wooga.gradle.test.writers.PropertySetInvocation.getProviderSet | ||
import static com.wooga.gradle.test.writers.PropertySetInvocation.getSetter | ||
|
||
class UnitySonarqubeExtensionIntegrationSpec extends IntegrationSpec { | ||
|
||
def setup() { | ||
buildFile << "${applyPlugin(UnitySonarqubePlugin)}\n" | ||
} | ||
|
||
@Unroll("can set property unitySonarqube.#property with #invocation and type #type") | ||
def "can set property on unitySonarqube extension with build.gradle"() { | ||
given: | ||
when: | ||
set.location = invocation == none ? PropertyLocation.none : set.location | ||
def propertyQuery = runPropertyQuery(get, set) | ||
|
||
then: | ||
propertyQuery.matches(rawValue) | ||
|
||
where: | ||
property | invocation | rawValue | type | ||
"buildDotnetVersion" | providerSet | "7.0.200" | "Provider<String>" | ||
"buildDotnetVersion" | assignment | "7.0.200" | "Provider<String>" | ||
"buildDotnetVersion" | assignment | "7.0.200" | "String" | ||
"buildDotnetVersion" | setter | "7.0.200" | "Provider<String>" | ||
"buildDotnetVersion" | setter | "7.0.200" | "String" | ||
"buildDotnetVersion" | none | "7.0.100" | "String" | ||
|
||
"buildDotnetExecutable" | providerSet | "dot_net" | "Provider<String>" | ||
"buildDotnetExecutable" | assignment | "dir/dot_net" | "Provider<String>" | ||
"buildDotnetExecutable" | assignment | "dot_net" | "String" | ||
"buildDotnetExecutable" | setter | "d/sd/dot_net" | "Provider<String>" | ||
"buildDotnetExecutable" | setter | "dot_net" | "String" | ||
"buildDotnetExecutable" | none | null | "String" | ||
|
||
set = new PropertySetterWriter("unitySonarqube", property) | ||
.set(rawValue, type) | ||
.toScript(invocation) | ||
get = new PropertyGetterTaskWriter(set) | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
...integrationTest/groovy/wooga/gradle/unitysonar/UnitySonarqubePluginIntegrationSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package wooga.gradle.unitysonar | ||
|
||
import com.wooga.gradle.test.IntegrationSpec | ||
import com.wooga.gradle.test.run.result.GradleRunResult | ||
import com.wooga.gradle.test.writers.PropertyGetterTaskWriter | ||
import com.wooga.gradle.test.writers.PropertySetterWriter | ||
|
||
class UnitySonarqubePluginIntegrationSpec extends IntegrationSpec { | ||
|
||
def setup() { | ||
buildFile << "${applyPlugin(UnitySonarqubePlugin)}\n" | ||
} | ||
|
||
def "sonarqube task run tests and sonar build"() { | ||
given: "applied unity-sonarqube plugin" | ||
|
||
when: | ||
def result = runTasks("sonarqube", "--dry-run") | ||
|
||
then: | ||
def run = new GradleRunResult(result) | ||
run["test"] | ||
run["sonarBuildUnity"] | ||
run["sonarqube"].wasExecutedAfter("test") | ||
run["sonarqube"].wasExecutedAfter("sonarBuildUnity") | ||
} | ||
|
||
def "sonarBuildUnity task runs in expected order"() { | ||
given: "applied unity-sonarqube plugin" | ||
|
||
when: | ||
def result = runTasks("sonarBuildUnity", "--dry-run") | ||
|
||
then: | ||
def run = new GradleRunResult(result) | ||
run["asdfBinstubsDotnet"].wasExecutedBefore("sonarBuildUnity") | ||
run["generateSolution"].wasExecutedBefore("sonarBuildUnity") | ||
run["sonarScannerBegin"].wasExecutedBefore("sonarBuildUnity") | ||
run["sonarScannerEnd"].wasExecutedAfter("sonarBuildUnity") | ||
} | ||
|
||
def "sonarqube build task runs after unity tests"() { | ||
given: "applied sonarqube plugin" | ||
|
||
when: | ||
def result = runTasks("sonarBuildUnity", "test", "--dry-run") | ||
|
||
then: | ||
def run = new GradleRunResult(result) | ||
run["test"].wasExecutedBefore("sonarBuildUnity") | ||
} | ||
|
||
def "#task uses asdf-installed dotnet as default executable"() { | ||
given: "applied unity-sonarqube plugin" | ||
when: | ||
getter.write(buildFile) | ||
def tasksResult = runTasks("asdfBinstubsDotnet", getter.taskName) | ||
def query = getter.generateQuery(this, tasksResult) | ||
|
||
then: | ||
query.matches(new File(projectDir, "bin/dotnet").absolutePath) | ||
|
||
where: | ||
task << ["sonarBuildUnity", "sonarScannerBegin", "sonarScannerEnd"] | ||
getter = new PropertyGetterTaskWriter("${task}.executable") | ||
} | ||
|
||
def "#task uses extension-set dotnet as executable"() { | ||
given: "applied unity-sonarqube plugin" | ||
when: | ||
def query = runPropertyQuery(getter, setter) | ||
|
||
then: | ||
query.matches(expectedExecutable) | ||
|
||
where: | ||
task = "sonarBuildUnity" | ||
expectedExecutable = "folder/dot_net" | ||
getter = new PropertyGetterTaskWriter("${task}.executable") | ||
setter = new PropertySetterWriter("unitySonarqube", "buildDotnetExecutable") | ||
.set(expectedExecutable, String) | ||
} | ||
|
||
} |
43 changes: 43 additions & 0 deletions
43
src/main/groovy/wooga/gradle/unitysonar/UnitySonarqubeExtension.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package wooga.gradle.unitysonar | ||
|
||
import com.wooga.gradle.BaseSpec | ||
import org.gradle.api.provider.Property | ||
import org.gradle.api.provider.Provider | ||
import org.gradle.api.tasks.Input | ||
import org.gradle.api.tasks.Optional | ||
|
||
class UnitySonarqubeExtension implements BaseSpec { | ||
|
||
private final Property<String> buildDotnetVersion = objects.property(String) | ||
|
||
@Input | ||
@Optional | ||
Property<String> getBuildDotnetVersion() { | ||
return buildDotnetVersion | ||
} | ||
|
||
void setBuildDotnetVersion(String buildDotnetVersion) { | ||
this.buildDotnetVersion.set(buildDotnetVersion) | ||
} | ||
|
||
void setBuildDotnetVersion(Provider<String> buildDotnetVersion) { | ||
this.buildDotnetVersion.set(buildDotnetVersion) | ||
} | ||
|
||
private final Property<String> buildDotnetExecutable = objects.property(String) | ||
|
||
@Input | ||
@Optional | ||
Property<String> getBuildDotnetExecutable() { | ||
return buildDotnetExecutable | ||
} | ||
|
||
void setBuildDotnetExecutable(String buildDotnetExecutable) { | ||
this.buildDotnetExecutable.set(buildDotnetExecutable) | ||
} | ||
|
||
void setBuildDotnetExecutable(Provider<String> buildDotnetExecutable) { | ||
this.buildDotnetExecutable.set(buildDotnetExecutable) | ||
} | ||
|
||
} |
126 changes: 126 additions & 0 deletions
126
src/main/groovy/wooga/gradle/unitysonar/UnitySonarqubePlugin.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package wooga.gradle.unitysonar | ||
|
||
import org.gradle.api.Action | ||
import org.gradle.api.DefaultTask | ||
import org.gradle.api.Plugin | ||
import org.gradle.api.Project | ||
import org.gradle.api.Task | ||
import org.gradle.api.UnknownTaskException | ||
import org.gradle.api.provider.Provider | ||
import org.gradle.api.tasks.TaskProvider | ||
import org.sonarqube.gradle.SonarQubeExtension | ||
import org.sonarqube.gradle.SonarQubeProperties | ||
import wooga.gradle.asdf.AsdfPlugin | ||
import wooga.gradle.asdf.AsdfPluginExtension | ||
import wooga.gradle.asdf.internal.ToolVersionInfo | ||
import wooga.gradle.dotnetsonar.DotNetSonarqubePlugin | ||
import wooga.gradle.dotnetsonar.SonarScannerExtension | ||
import wooga.gradle.dotnetsonar.tasks.BuildSolution | ||
import wooga.gradle.unity.UnityPlugin | ||
import wooga.gradle.unity.UnityPluginExtension | ||
|
||
class UnitySonarqubePlugin implements Plugin<Project> { | ||
|
||
Project project | ||
|
||
@Override | ||
void apply(Project project) { | ||
this.project = project | ||
|
||
project.pluginManager.apply(UnityPlugin.class) | ||
project.pluginManager.apply(DotNetSonarqubePlugin.class) | ||
project.pluginManager.apply(AsdfPlugin.class) | ||
|
||
def unitySonarqube = createExtension("unitySonarqube") | ||
//uses same dotnet version for both sonarScanner and buildTask | ||
def asdf = configureAsdfWithTool("dotnet", unitySonarqube.buildDotnetVersion) | ||
def unity = configureUnityPlugin() | ||
configureSonarScanner(asdf) | ||
configureSonarqubePlugin(unity) | ||
|
||
|
||
def unityTestTask = project.tasks.named(UnityPlugin.Tasks.test.toString()) | ||
def createSolutionTask = project.tasks.named(UnityPlugin.Tasks.generateSolution.toString()) | ||
|
||
def sonarBuild = project.tasks.register("sonarBuildUnity", BuildSolution) { it -> | ||
it.dependsOn(createSolutionTask) | ||
it.mustRunAfter(unityTestTask) | ||
|
||
def buildDotnetDefault = unitySonarqube.buildDotnetExecutable.orElse(asdf.getTool("dotnet").getExecutable("dotnet")) | ||
it.executableName.convention(buildDotnetDefault) | ||
it.solution.convention(unity.projectDirectory.file("${project.name}.sln")) | ||
it.environment.put("FrameworkPathOverride", unity.monoFrameworkDir.map { it.asFile.absolutePath }) | ||
|
||
def propsFix = createSolutionPropertyFixFile("/unity-sonarqube.project-fixes.props") | ||
it.additionalArguments.add("/p:CustomBeforeMicrosoftCommonProps=${propsFix.absolutePath}") | ||
} | ||
|
||
namedOrRegister("sonarqube", DefaultTask) { task -> | ||
task.dependsOn(unityTestTask, sonarBuild) | ||
} | ||
} | ||
|
||
UnitySonarqubeExtension createExtension(String extensionName) { | ||
def unitySonarqube = project.extensions.create(extensionName, UnitySonarqubeExtension) | ||
unitySonarqube.buildDotnetVersion.convention(UnitySonarqubePluginConventions.buildDotnetVersion.getStringValueProvider(project)) | ||
return unitySonarqube | ||
} | ||
|
||
AsdfPluginExtension configureAsdfWithTool(String name, Provider<String> version) { | ||
def asdf = project.extensions.getByType(AsdfPluginExtension) | ||
asdf.tool(new ToolVersionInfo(name, version)) | ||
return asdf | ||
} | ||
|
||
UnityPluginExtension configureUnityPlugin() { | ||
def unityExt = project.extensions.findByType(UnityPluginExtension) | ||
unityExt.enableTestCodeCoverage = true | ||
return unityExt | ||
} | ||
|
||
SonarScannerExtension configureSonarScanner(AsdfPluginExtension asdf) { | ||
def sonarScanner = project.extensions.findByType(SonarScannerExtension) | ||
|
||
def asdfDotnet = asdf.getTool("dotnet") | ||
sonarScanner.dotnetExecutable.convention(asdfDotnet.getExecutable("dotnet")) | ||
return sonarScanner | ||
} | ||
|
||
SonarQubeExtension configureSonarqubePlugin(UnityPluginExtension unity) { | ||
def sonarExt = project.extensions.findByType(SonarQubeExtension) | ||
sonarExt.properties({ | ||
def assetsDir = unity.assetsDir.get().asFile | ||
def reportsDir = unity.reportsDir.get().asFile | ||
def relativeAssetsDir = project.projectDir.relativePath(assetsDir) | ||
addPropertyIfNotExists(it, "sonar.cpd.exclusions", "${relativeAssetsDir}/**/Tests/**") | ||
addPropertyIfNotExists(it, "sonar.coverage.exclusions", "${relativeAssetsDir}/**/Tests/**") | ||
addPropertyIfNotExists(it, "sonar.exclusions", "${relativeAssetsDir}/Paket.Unity3D/**") | ||
addPropertyIfNotExists(it, "sonar.cs.nunit.reportsPaths", "${reportsDir.path}/**/*.xml") | ||
addPropertyIfNotExists(it, "sonar.cs.opencover.reportsPaths", "${reportsDir.path}/**/*.xml") | ||
}) | ||
return sonarExt | ||
} | ||
|
||
protected static void addPropertyIfNotExists(SonarQubeProperties properties, String key, Object value) { | ||
if (!properties.properties.containsKey(key)) { | ||
properties.property(key, value) | ||
} | ||
} | ||
|
||
protected static File createSolutionPropertyFixFile(String resourceFileName) { | ||
def propsFixResource = UnitySonarqubePlugin.class.getResourceAsStream(resourceFileName) | ||
def propsFixTmpFile = File.createTempFile("unity-sonarqube-", ".project-fixes.props") | ||
propsFixTmpFile.text = propsFixResource.text | ||
return propsFixTmpFile | ||
} | ||
|
||
protected <T extends Task> TaskProvider<T> namedOrRegister(String taskName, Class<T> type = DefaultTask.class, Action<T> configuration = { it -> }) { | ||
try { | ||
return project.tasks.named(taskName, type, configuration) | ||
} catch (UnknownTaskException ignore) { | ||
return project.tasks.register(taskName, type, configuration) | ||
} | ||
} | ||
|
||
|
||
} |
19 changes: 19 additions & 0 deletions
19
src/main/groovy/wooga/gradle/unitysonar/UnitySonarqubePluginConventions.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package wooga.gradle.unitysonar | ||
|
||
import com.wooga.gradle.PropertyLookup | ||
|
||
class UnitySonarqubePluginConventions { | ||
|
||
static PropertyLookup buildDotnetVersion = new PropertyLookup( | ||
"UNITY_SONARQUBE_BUILD_DOTNET_VERSION", | ||
"unitySonarqube.buildDotnetVersion", | ||
"7.0.100" | ||
) | ||
|
||
static PropertyLookup buildDotnetExecutable = new PropertyLookup( | ||
"UNITY_SONARQUBE_BUILD_DOTNET_EXECUTABLE", | ||
"unitySonarqube.buildDotnetExecutable", | ||
null | ||
) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<PropertyGroup> | ||
<!-- Our wooga projects get falsely flagged as test projects due to `nunit` reference. --> | ||
<SonarQubeTestProject>false</SonarQubeTestProject> | ||
<!-- Unity default .sln export adds the Unity installed CSC tools which have issues to work with `.editoconfig` --> | ||
<CscToolPath></CscToolPath> | ||
<CscToolExe></CscToolExe> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<!-- Unity 2020 default export disables all it's references. (known bug: https://issuetracker.unity3d.com/issues/referenceoutputassembly-key-is-set-to-false-in-project-references) --> | ||
<ProjectReference Update="*.csproj"> | ||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly> | ||
</ProjectReference> | ||
</ItemGroup> | ||
</Project> |
Oops, something went wrong.