Git Product home page Git Product logo

diff-coverage-gradle's People

Contributors

alexeytokar avatar nicklaswallgren avatar surpsg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

diff-coverage-gradle's Issues

Java compatibility issue with kotlin lambda expressions

I'm getting the following error when trying to execute diffCoverage task:

Caused by: java.lang.NoSuchMethodError: 'void kotlin.jvm.internal.FunctionReferenceImpl.<init>(int, java.lang.Object, java.lang.Class, java.lang.String, java.lang.String, int)'
	at com.form.coverage.report.analyzable.DiffCoverageAnalyzableReport$buildAnalyzer$1.<init>(DiffCoverageAnalyzableReport.kt)
	at com.form.coverage.report.analyzable.DiffCoverageAnalyzableReport.buildAnalyzer(DiffCoverageAnalyzableReport.kt:37)
	at com.form.coverage.report.ReportGenerator$create$bundleCoverage$1.invoke(ReportGenerator.kt:50)
	at com.form.coverage.report.ReportGenerator$create$bundleCoverage$1.invoke(ReportGenerator.kt:16)

It seems to be related to https://youtrack.jetbrains.com/issue/KT-39389#focus=Comments-27-4184517.0-0, but I have not found a workaround for it.

I'm building this for an android project where I'm currently using gradle 6.5 and kotline 4.0. I have tried updating those but I still get this error when executing diffCoverage.

It looks like a change like this solves it for me, but I'm not sure this is the right approach:

diff --git a/jacoco-filtering-extension/src/main/kotlin/com/form/coverage/report/analyzable/DiffCoverageAnalyzableReport.kt b/jacoco-filtering-extension/src/main/kotlin/com/form/coverage/report/analyzable/DiffCoverageAnalyzableReport.kt
index 7b106f2..e913e15 100644
--- a/jacoco-filtering-extension/src/main/kotlin/com/form/coverage/report/analyzable/DiffCoverageAnalyzableReport.kt
+++ b/jacoco-filtering-extension/src/main/kotlin/com/form/coverage/report/analyzable/DiffCoverageAnalyzableReport.kt
@@ -34,7 +34,10 @@ internal class DiffCoverageAnalyzableReport(
         return FilteringAnalyzer(
                 executionDataStore,
                 coverageVisitor,
-                reportMode.codeUpdateInfo::isInfoExists
+            {
+                reportMode.codeUpdateInfo.isInfoExists(it)
+            }
+
         ) {
             ModifiedLinesFilter(reportMode.codeUpdateInfo)
         }

Incorrect git diff file generated by plugin

When I'm using default git.compare, I found the diff file is not completely correct.
For example, we have master and dev branchs.

  1. master have some commit that dev don't have.
  2. dev have some commit that master don't have.
  3. We're on the dev branch.
  4. Diff coverage comparing to master branch.

In this case, the diff file is including the commits on master and treating as delete operation.

Actually, the master should be always latest comparing to our develop branch, and have some commits we don't have if we don't merge master.
I'm not sure it's a issue or you do want this, but I think we should ignore the commits dev don't have, at least provide a config value.

For now, I use this command to generate the diffFile, please check and hope it helps.

1. git diff origin/master... > reports/git.diff
2. git diff --ignore-space-change origin/master... > reports/git.diff

diffSource.git.compareWith ignores uncommitted files

Describe the bug
The diffSource.git.compareWith configuration has no effect if the files have not been committed to git.

If this is by design, it should be clearly documented. However, it does not align with the expectation of executing git diff <ref> and saving the results to a file that the plugin points to. In particular, it makes a diff reference to HEAD completely useless after the commit.

Additionally the comment in the config explicitly specifies uncommitted files:

Compares current HEAD and all uncommited with provided branch

Desktop (please complete the following information):

  • OS: Mac OS X 13.0 x86_64
  • Gradle version: 7.5.1
  • Diff Coverage plugin version 0.9.5

To Reproduce

  1. Make changes to a file that require coverage, save them but do not commit.
  2. gradle diffCoverage with the below configuration
diffCoverageReport {
    diffSource {
        git.compareWith 'refs/remotes/origin/main'
    }

    reports {
        html = true
    }
}
  1. Observe the files in build/reports/jacoco directory:
  • The diff.patch file has 0 bytes
  • The html report under diffCoverage/html/index.html says "No class files specified." (See also report in #65 for which this may have been the cause.)

Expected behavior

Changed files are found and diff.patch is not empty.

Additional context

Workaround is to configure:

    diffSource {
        file = 'build/tmp/git.diff'
    }

and then execute:

git diff refs/remotes/origin/main > build/tmp/git.diff
gradle diffCoverage

Consider adding support for Configuration Cache

Consider adding support for https://docs.gradle.org/current/userguide/configuration_cache.html

Current issue;
https://docs.gradle.org/7.4.2/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution

13 problems were found storing the configuration cache, 1 of which seems unique.
- Task `:diffCoverage` of type `com.form.coverage.gradle.DiffCoverageTask`: invocation of 'Task.project' at execution time is unsupported.
  See https://docs.gradle.org/7.4.2/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
Caused by: org.gradle.api.InvalidUserCodeException: Invocation of 'Task.project' by task ':diffCoverage' at execution time is unsupported.
        at org.gradle.configurationcache.initialization.DefaultConfigurationCacheProblemsListener.onTaskExecutionAccessProblem(ConfigurationCacheProblemsListener.kt:74)
        at org.gradle.configurationcache.initialization.DefaultConfigurationCacheProblemsListener.onProjectAccess(ConfigurationCacheProblemsListener.kt:53)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.event.DefaultListenerManager$ListenerDetails.dispatch(DefaultListenerManager.java:464)
        at org.gradle.internal.event.DefaultListenerManager$ListenerDetails.dispatch(DefaultListenerManager.java:446)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:61)
        at org.gradle.internal.event.DefaultListenerManager$EventBroadcast$ListenerDispatch.dispatch(DefaultListenerManager.java:434)
        at org.gradle.internal.event.DefaultListenerManager$EventBroadcast.dispatch(DefaultListenerManager.java:221)
        at org.gradle.internal.event.DefaultListenerManager$EventBroadcast.dispatch(DefaultListenerManager.java:192)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
        at jdk.proxy1/jdk.proxy1.$Proxy174.onProjectAccess(Unknown Source)
        at org.gradle.api.internal.AbstractTask.notifyProjectAccess(AbstractTask.java:1053)
        at org.gradle.api.internal.AbstractTask.getProject(AbstractTask.java:237)
        at org.gradle.api.DefaultTask.getProject(DefaultTask.java:59)
        at com.form.coverage.gradle.DiffCoverageTask.getOutputDir(DiffCoverageTask.kt:45)
        at com.form.coverage.gradle.DiffCoverageTask.executeAction(DiffCoverageTask.kt:56)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104)

Wrong class file distinguish when two classes having same package and name

Describe the bug
When there are two java files in different module, that have same package and class name, the coverage is wrong
e.g.

  • module A
    • com.example.Application
  • module B
    • com.example.Application

There is no test for both A and B before.

After I changed A class and add related test case

  • Module A pass, because I covered changed lines
  • Module B failed, even I didn't change the file, but it still think the changed line belongs to this file.

I think the root cause is, the plugin didn't add module name for distinguish two different class
I don't read the source code, but I think the uniqueKey is

  • Now: package_name + class_name
  • Should be: module_name/parent_dir_name + package_name + class_name

Version info:

  • Gradle version: 4.10.2
  • Diff Coverage plugin version 0.8.1

To Reproduce

diffCoverageReport {
    violationRules.failIfCoverageLessThan 0.7
}
  • module A
    • com.example.Application
  • module B
    • com.example.Application

Both two files don't have test class

Then change module A file, and run diffCoverage

'diffCoverageReport.classesDirs' file collection is empty.

After upgrading from 0.8.1 to 0.9.0/0.9.1, diffCoverage task keep throwing exception that 'diffCoverageReport.classesDirs' file collection is empty.

My gradle version is 4.10.3.

Here is my configurations

subprojects {
	jacocoTestReport {
		dependsOn test
		group = "Reporting"
		description = "Generate Jacoco coverage reports"

		executionData files("${buildDir}/jacoco/jacoco.exec")
		sourceDirectories = files("${projectDir}/src/main/java")

		def generatedFilter = [
			'**/generated/**'
		]
		classDirectories = files(
			fileTree(dir: "${buildDir}/classes/java/main", excludes: generatedFilter),
			fileTree(dir: "${buildDir}/classes/main", excludes: generatedFilter)
		)

		reports {
			xml.enabled = true
			html.enabled = true
			csv.enabled = true
			xml.destination file("${buildDir}/reports/jacoco.xml")
			csv.destination file("${buildDir}/reports/jacoco.csv")
			html.destination file("${buildDir}/reports/fullCoverage")
		}

		afterEvaluate {
			classDirectories = files(classDirectories.files.collect {
				fileTree(dir: it, exclude: generatedFilter)
			})
		}
	}

	diffCoverageReport {
		def diffFile = System.getProperty('jacoco.diff.file') ?: ''
		def diffRepo = System.getProperty('jacoco.diff.repo') ?: 'origin'
		def diffBranch = System.getProperty('jacoco.diff.branch') ?: 'master'
		diffSource {
			if (diffFile) {
				file = diffFile
			} else {
				git.compareWith "refs/remotes/${diffRepo}/${diffBranch}"
			}
		}

		jacocoExecFiles = files(jacocoTestReport.executionData)
		classesDirs = files(jacocoTestReport.classDirectories)
		srcDirs = files(jacocoTestReport.sourceDirectories)

		reports {
			html = true
			csv = true
			xml = true
			baseReportDir = "${buildDir}/reports"
		}
	}
}

java.lang.ClassCastException

Enviroment:
Android Studio 4.2.2
Gradle plugin 6.7
diffCoveragePlugin: 0.9.1

Caused by: java.lang.ClassCastException: org.gradle.api.DefaultTask_Decorated cannot be cast to org.gradle.testing.jacoco.tasks.JacocoReport
        at com.form.coverage.gradle.DiffTaskAutoConfigurationKt$jacocoTestReportsSettings$3.invoke(DiffTaskAutoConfiguration.kt:58)
        at com.form.coverage.gradle.DiffTaskAutoConfigurationKt$jacocoTestReportsSettings$3.invoke(DiffTaskAutoConfiguration.kt)
        at kotlin.sequences.TransformingSequence$iterator$1.next(Sequences.kt:172)
        at com.form.coverage.gradle.DiffTaskAutoConfigurationKt.jacocoTestReportsSettings(DiffTaskAutoConfiguration.kt:99)
        at com.form.coverage.gradle.DiffTaskAutoConfigurationKt.collectFileCollectionOrAutoconfigure(DiffTaskAutoConfiguration.kt:47)
        at com.form.coverage.gradle.DiffTaskAutoConfigurationKt.collectFileCollectionOrThrow(DiffTaskAutoConfiguration.kt:9)
        at com.form.coverage.gradle.DiffCoverageTask.getSourcesFiles(DiffCoverageTask.kt:30)
        at org.gradle.api.internal.tasks.properties.bean.AbstractNestedRuntimeBeanNode$BeanPropertyValue$1$1.create(AbstractNestedRuntimeBeanNode.java:77)
        at org.gradle.internal.deprecation.DeprecationLogger.whileDisabled(DeprecationLogger.java:236)
        at org.gradle.api.internal.tasks.properties.bean.AbstractNestedRuntimeBeanNode$BeanPropertyValue$1.get(AbstractNestedRuntimeBeanNode.java:73)
        at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:167)
        at org.gradle.api.internal.tasks.properties.bean.AbstractNestedRuntimeBeanNode$BeanPropertyValue.call(AbstractNestedRuntimeBeanNode.java:133)
        at org.gradle.util.GUtil.uncheckedCall(GUtil.java:442)
        at org.gradle.util.DeferredUtil.unpackNestableDeferred(DeferredUtil.java:64)
        at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:84)
        at org.gradle.api.internal.file.DefaultFileCollectionFactory$ResolvingFileCollection.visitChildren(DefaultFileCollectionFactory.java:310)
        at org.gradle.api.internal.file.CompositeFileCollection.visitDependencies(CompositeFileCollection.java:108)
        at org.gradle.api.internal.tasks.CachingTaskDependencyResolveContext$TaskGraphImpl.getNodeValues(CachingTaskDependencyResolveContext.java:112)
        at org.gradle.internal.graph.CachingDirectedGraphWalker$GraphWithEmptyEdges.getNodeValues(CachingDirectedGraphWalker.java:213)
        at org.gradle.internal.graph.CachingDirectedGraphWalker.doSearch(CachingDirectedGraphWalker.java:121)
        at org.gradle.internal.graph.CachingDirectedGraphWalker.findValues(CachingDirectedGraphWalker.java:73)
        at org.gradle.api.internal.tasks.CachingTaskDependencyResolveContext.getDependencies(CachingTaskDependencyResolveContext.java:67)
        ... 114 more

Cannot include the plugin in gradle, cannot find plugin id

What is the plugin id that I should use to include this plugin??
I am using this in my build.gradle file

plugins {
    id "jacoco"
    id "com.form.diff-coverage" version "0.9.0"
}
* Exception is:
org.gradle.api.plugins.UnknownPluginException: Plugin [id: 'com.form.diff-coverage', version: '0.9.0'] was not found in any of the following sources:

- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Plugin Repositories (could not resolve plugin artifact 'com.form.diff-coverage:com.form.diff-coverage.gradle.plugin:0.9.0')
  Searched in the following repositories:
    Gradle Central Plugin Repository
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.resolveToFoundResult(DefaultPluginRequestApplicator.java:222)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.lambda$resolvePluginRequests$4(DefaultPluginRequestApplicator.java:148)
	at org.gradle.util.CollectionUtils.collect(CollectionUtils.java:207)
	at org.gradle.util.CollectionUtils.collect(CollectionUtils.java:201)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.resolvePluginRequests(DefaultPluginRequestApplicator.java:146)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:86)
	at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:117)
	at org.gradle.configuration.BuildOperationScriptPlugin$1.run(BuildOperationScriptPlugin.java:65)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:56)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$run$1(DefaultBuildOperationExecutor.java:71)
	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.runWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:45)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:71)
	at org.gradle.configuration.BuildOperationScriptPlugin.lambda$apply$0(BuildOperationScriptPlugin.java:62)
	at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:43)
	at org.gradle.configuration.BuildOperationScriptPlugin.apply(BuildOperationScriptPlugin.java:62)
	at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$applyToMutableState$0(DefaultProjectStateRegistry.java:250)
	at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.fromMutableState(DefaultProjectStateRegistry.java:277)
	at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.applyToMutableState(DefaultProjectStateRegistry.java:249)
	at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:42)
	at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:26)
	at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:35)
	at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.lambda$run$0(LifecycleProjectEvaluator.java:100)
	at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$applyToMutableState$0(DefaultProjectStateRegistry.java:250)
	at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$withProjectLock$3(DefaultProjectStateRegistry.java:310)
	at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:213)
	at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withProjectLock(DefaultProjectStateRegistry.java:310)
	at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.fromMutableState(DefaultProjectStateRegistry.java:291)
	at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.applyToMutableState(DefaultProjectStateRegistry.java:249)
	at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:91)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:56)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$run$1(DefaultBuildOperationExecutor.java:71)
	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.runWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:45)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:71)
	at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:63)
	at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:723)
	at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:150)
	at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:41)
	at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:67)
	at org.gradle.configuration.DefaultProjectsPreparer.prepareProjects(DefaultProjectsPreparer.java:46)
	at org.gradle.configuration.BuildTreePreparingProjectsPreparer.prepareProjects(BuildTreePreparingProjectsPreparer.java:64)
	at org.gradle.configuration.BuildOperationFiringProjectsPreparer$ConfigureBuild.run(BuildOperationFiringProjectsPreparer.java:52)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:56)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$run$1(DefaultBuildOperationExecutor.java:71)
	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.runWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:45)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:71)
	at org.gradle.configuration.BuildOperationFiringProjectsPreparer.prepareProjects(BuildOperationFiringProjectsPreparer.java:40)
	at org.gradle.initialization.DefaultGradleLauncher.prepareProjects(DefaultGradleLauncher.java:226)
	at org.gradle.initialization.DefaultGradleLauncher.doClassicBuildStages(DefaultGradleLauncher.java:164)
	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
	at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:125)
	at org.gradle.internal.invocation.GradleBuildController$1.create(GradleBuildController.java:71)
	at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:213)
	at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:67)
	at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:56)
	at org.gradle.tooling.internal.provider.runner.AbstractClientProvidedBuildActionRunner.runClientAction(AbstractClientProvidedBuildActionRunner.java:53)
	at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner.run(ClientProvidedPhasedActionRunner.java:47)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:66)
	at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
	at org.gradle.tooling.internal.provider.FileSystemWatchingBuildActionRunner.run(FileSystemWatchingBuildActionRunner.java:90)
	at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:41)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:49)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:44)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:44)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.lambda$execute$0(InProcessBuildActionExecuter.java:59)
	at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:86)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:58)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30)
	at org.gradle.launcher.exec.BuildTreeScopeLifecycleBuildActionExecuter.lambda$execute$0(BuildTreeScopeLifecycleBuildActionExecuter.java:34)
	at org.gradle.internal.buildtree.BuildTreeState.run(BuildTreeState.java:53)
	at org.gradle.launcher.exec.BuildTreeScopeLifecycleBuildActionExecuter.execute(BuildTreeScopeLifecycleBuildActionExecuter.java:33)
	at org.gradle.launcher.exec.BuildTreeScopeLifecycleBuildActionExecuter.execute(BuildTreeScopeLifecycleBuildActionExecuter.java:28)
	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:104)
	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:55)
	at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:64)
	at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:37)
	at org.gradle.tooling.internal.provider.SessionScopeLifecycleBuildActionExecuter.lambda$execute$0(SessionScopeLifecycleBuildActionExecuter.java:54)
	at org.gradle.internal.session.BuildSessionState.run(BuildSessionState.java:67)
	at org.gradle.tooling.internal.provider.SessionScopeLifecycleBuildActionExecuter.execute(SessionScopeLifecycleBuildActionExecuter.java:50)
	at org.gradle.tooling.internal.provider.SessionScopeLifecycleBuildActionExecuter.execute(SessionScopeLifecycleBuildActionExecuter.java:36)
	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:36)
	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:25)
	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:59)
	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:31)
	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:58)
	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:42)
	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:47)
	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:31)
	at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:65)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:29)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:78)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:75)
	at org.gradle.util.Swapper.swap(Swapper.java:38)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:75)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:84)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
	at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)
	at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)

Tasks failed with FileNotFoundException

Hi,
I met a problem about FileNotFoundException while running diffCoverage task.

I'm testing with this configuration, and always get this error

 diffCoverageReport {
        def diffBranch = System.getProperty('jacoco-diff-branch') ?: 'master'
        diffSource {
            git.compareWith "refs/heads/${diffBranch}"
        }

        jacocoExecFiles = files(jacocoTestReport.executionData)
        classesDirs = files(jacocoTestReport.classDirectories)
        srcDirs = files(jacocoTestReport.sourceDirectories)

        reports {
            xml = true
            html = false
            csv = true
        }
    }

When I change reports.html to true, the error disappeared.

I tried to debug the source code, and I found the report is generated at ${buildDir}/reports/jacoco/diffCoverage/xxx.format.
And I found this code, HTML is using FileMultiReportOutput, XML/CSV is using FileOutputStream.
FileMultiReportOutput will auto create the parent directory, but FileOutputStream is not, and it also throws a FileNotFoundException

So it can explain why when reports.html = false, it cannot auto mkdir parent dirs and throws a exception.

And under further analysis, I also don't know why the code goes here, it looks like full report generator, but fullCoverageReport is not setted to true.
image

'diffCoverageReport.jacocoExecFiles' file collection is empty

Describe the bug
FAILURE: Build failed with an exception.

  • What went wrong:
    Could not determine the dependencies of task ':diffCoverage'.

'diffCoverageReport.jacocoExecFiles' file collection is empty.

Desktop (please complete the following information):

  • OS: Linux, Mac
  • Gradle version: 7.5.1
  • Diff Coverage plugin version 0.9.5

To Reproduce
./gradlew clean diffCoverage

Expected behavior
The build fails, it would be great to add an option to fail silently. The use-case is in CI builds the diff might not have any test coverage and can lead to this failure.

Logs
FAILURE: Build failed with an exception.

  • What went wrong:
    Could not determine the dependencies of task ':diffCoverage'.

'diffCoverageReport.jacocoExecFiles' file collection is empty.

  • Try:

Run with --stacktrace option to get the stack trace.
Run with --info or --debug option to get more log output
Additional context
Add any other context about the problem here.

[feature request] support the coverage to 2 decimal

Describe the feature
Since this plugin is an extension of Jacoco, and Jacoco allows us to configure the coverage to multiple decimals (e.g. 0.65), I had the wrong impression that we can do the same for this plugin.

When I set the minBranches to 0.61, the exception still reports the same message

java.lang.Exception: Rule violated for bundle clients: branches covered ratio is 0.2, but expected minimum is 0.6

Desktop (please complete the following information):

  • OS: macOS 12.6.2
  • Gradle version: 6.9.3
  • Diff Coverage plugin version 0.9.5

To Reproduce

diffCoverageReport {
    diffSource.file = 'diff.patch'

    violationRules {
      minBranches = 0.61
      failOnViolation = true
    }
}

Expected behavior
The report can be more precise when the coverage is set to 2 decimals, such as

java.lang.Exception: Rule violated for bundle clients: branches covered ratio is 0.29, but expected minimum is 0.61

Additional context
I checked the config usage and seems we only set a single decimal for the double type, which might be the reason but I could be wrong.
Please let me know if it can be supported. Thanks!

Gradle 7.4 - Execution optimizations have been disabled for task ':diffCoverage'

> Task :diffCoverage
Execution optimizations have been disabled for task ':diffCoverage' to ensure correctness due to the following reasons:
  - Gradle detected a problem with the following location: '<PATH>/build/classes/java/main'. Reason: Task ':diffCoverage' uses this output of task ':compileJava' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. Please refer to https://docs.gradle.org/7.4/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: '<PATH>/build/jacoco/test.exec'. Reason: Task ':diffCoverage' uses this output of task ':test' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. Please refer to https://docs.gradle.org/7.4/userguide/validation_problems.html#implicit_dependency for more details about this problem.
  - Gradle detected a problem with the following location: '<PATH>/build/resources/main'. Reason: Task ':diffCoverage' uses this output of task ':processResources' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. Please refer to https://docs.gradle.org/7.4/userguide/validation_problems.html#implicit_dependency for more details about this problem.
Fail on violations: false. Found violations: 0.

Adding exclusions setting

It would be nice to have a specific setting which specifies the files which should be thrown out of coverage check. This helps in cases when @Data from lombok library is used. One could argue that those methods should still be tested, but it would still be a nice feature.

I suggest adding something like

    diffCoverageReport {
        diffSource.git.compareWith 'refs/remotes/origin/develop'

        violationRules.failIfCoverageLessThan 0.8

        reports {
            html = true
        }
        
        exclusions = "**/MyClass.java", "**/model/*.java" # // <-- This is the setting I'm talking about
    }

@SurpSG could you please provide your opinion on this matter? I think I can implement the necessary code myself, but I want to get your confirmation first.

UPD: It looks like this option is present in maven version of this plugin, it means that this should not be a problem to implement it for gradle as well.

How to setup in a multi-module project?

I applied the plugin (v 0.9.5) in the root's build.gradle. After generating the reports, diff.patch is not correct compared to the result from git diff. Looks like it doesn't include diff in submodules.

Even if I tried configuring the report as below , it still doesn't work as expected.

diffCoverageReport {
    ...
    jacocoExecFiles = files(...)
    srcDirs = files(...)
    classesDirs = files(...)      
}

It'd be great if you could provide an example for multi-module setup.

False Negative on Code Coverage for Blank Lines and Comments added to Source file under test

Describe the bug

If you add just a blank line, or a comment, but no new instructions or functions to a class under test, the coverage violations will fail and say you have not met the threshold. In this case there is no new instructions, just comments and some extra blank lines, so code coverage should be the same as it was before.

We have instruction coverage to be a minimum of 0.7 percent, and branch coverage for 0.5 percent. The branch coverage is passing. The instruction coverage fails

Min Line coverage is 0.0.

   diffCoverageExtension.violationRules{
        minBranches = 0.5 // Optional. Default `0.0`
        minInstructions = 0.7 // Optional. Default `0.0`
        failOnViolation = true // Optional. Default `false`
    }

Desktop (please complete the following information):

  • OS: all
  • Gradle version: 7.4.1
  • Diff Coverage plugin version = 0.9.5

To Reproduce
If possible, provide your configuration of the plugin, for example:

diffCoverageReport {
    diffSource.file = 'diff.patch'

    violationRules.failIfCoverageLessThan 0.9
}

// Some comment in a source file 

Expected behavior

Since no instruction coverage changed this should still pass and meet the original thresholds.

diff.patch not correctly created when running inside CI

I have configured the project to run correctly locally using git configuration to get the diff.

This is my configuration:

diffCoverageReport {
      def targetBranch = project.getProperties().get("targetBranch") ?: "development"
      diffSource {
          git.compareWith targetBranch
      }

      jacocoExecFiles = files(jacocoTestReport.executionData)
      classesDirs = files(jacocoTestReport.classDirectories)
      srcDirs = files(jacocoTestReport.sourceDirectories)

      reports {
          html = true
          xml = true
      }

      violationRules {
          minBranches = 1
          minLines = 1
          minInstructions = 1
          failOnViolation = true
      }
}

However, when I run inside Gitlab CI/CD, the execution fails because it cannot create diff.patch. I believe the issue is becuase the folder where it wants to create it, build/reports/jacoco/, because if I pre-create this folder empty, then the plugin finishes successfully.

This is the exception:

Caused by: java.io.FileNotFoundException: /builds/android/<REPO>/build/reports/jacoco/diff.patch (No such file or directory)
	at kotlin.io.FilesKt__FileReadWriteKt.writeBytes(FileReadWrite.kt:108)
	at kotlin.io.FilesKt__FileReadWriteKt.writeText(FileReadWrite.kt:134)
	at kotlin.io.FilesKt__FileReadWriteKt.writeText$default(FileReadWrite.kt:134)
	at com.form.coverage.tasks.git.GitDiffSource.saveDiffTo(DiffSource.kt:67)
	at com.form.coverage.tasks.DiffCoverageTask.obtainUpdatesInfo(DiffCoverageTask.kt:109)
	at com.form.coverage.tasks.DiffCoverageTask.executeAction(DiffCoverageTask.kt:61)
	at com.form.coverage.tasks.DiffCoverageTask$executeAction.call(Unknown Source)

I verified that /builds/android/<REPO> exists and it is the root of my project. I also verified that simply running mkdir -p ./build/reports/jacoco before running my gradlew command fixes it.

Can you help me identify why the folder would be successfully created when running locally but fails when running inside CI?

There are some issues for collecting stats of Scala code

Describe the bug
I could see two items for each Scala class in the HTMP report. One is correct and another is not.

Desktop (please complete the following information):

  • OS: [e.g. Linux]
  • Gradle version: [e.g. 7.5.1]
  • Diff Coverage plugin version [e.g. 0.9.5]

To Reproduce
If possible, provide your configuration of the plugin, for example:

diffCoverageReport {
    diffSource.file = 'diff.patch'

    violationRules.failIfCoverageLessThan 0.9
}

Expected behavior
A clear and concise description of what you expected to happen.

Logs
If applicable, add stacktrace, Gradle output.

Additional context
Add any other context about the problem here.

Plugin fails when filtering classes before

I hope the project still receives support πŸ‘€

Describe the bug
When filtering the classDirectories used in the jacoco coverage analysis, gradle fails with 'diffCoverageReport.classesDirs' is not configured. When removing the afterEvaluate section, everything works as intended.

Desktop (please complete the following information):

  • OS: Windows 10
  • Gradle version: 8.2
  • Diff Coverage plugin version: 0.9.5

To Reproduce
Since this occurred in a larger project, I created a small reproduction project:
https://github.com/julian-christl/diffCoverageRepro

  1. Clone
  2. Checkout chore/repro
  3. Run gradle clean test jacocoTestReport diffCoverage

Expected behavior
The tests run through, and the reports get created.

Logs

FAILURE: Build failed with an exception.
* What went wrong:
Could not determine the dependencies of task ':diffCoverage'.
> 'diffCoverageReport.classesDirs' is not configured.
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
BUILD FAILED in 63ms

File Path is not support on UTF8 chars

  • What went wrong:
    Execution failed for task ':diffCoverage'.

Couldn't parse file relative path: +++ "......./\043\043\043 Fresh Video.json.withOption"

Task fails when running in CI

Hi,

I have configured the project to correctly run locally with multiple sub-projects.

However, when running inside Gitlab CI, then the task fails with:

Execution failed for task ':common-server:diffCoverage'.
> repo.resolve(name) must not be null

raised inside of:

private fun getTreeIterator(repo: Repository, name: String): AbstractTreeIterator  {
        val id: ObjectId = repo.resolve(name)
        .
        .
        .
}

I wonder if this can be avoided by handling the null-case in any way?

Configuration

subprojects {

	apply plugin: 'jacoco'
	apply plugin: 'com.form.diff-coverage'


	diffCoverageReport {
	    diffSource {
	        git.compareWith 'master'
	    }

	    jacocoExecFiles = files(project.projectDir.path + '/build/jacoco/test.exec')
	    srcDirs = files(project.projectDir.path + '/src/main/java')
	    classesDirs = files(project.projectDir.path + '/build/classes/')


	    reports {
	        html = true
	        xml = true
	        baseReportDir = project.projectDir.path + '/build/reports/'
	        fullCoverageReport = false
	    }

	    violationRules.failIfCoverageLessThan 0.9

	}
}

Versions in use

Gradle: 7.0
Kotlin: 1.4.31
Groovy: 3.0.7
diff-coverage-gradle: 0.8.0

diffCoverage gives html report with "No class files specified."

jacocoTestReport generates the code coverage report. However, diffCoverage generates html file with "No class files specified." I suspect the issue is with classesDirs and srcDirs but unable to get proper report after trying multiple different approaches.

jacocoTestReport {
    reports {
        xml {
            enabled true
            destination file("${buildDir}/coverage-report/jacoco-report.xml")
        }
        html {
            enabled true
            destination file("${buildDir}/coverage-report")
        }
    }
    afterEvaluate {
        classDirectories.from = files(classDirectories.files.collect {
            fileTree(dir: it, exclude: [
                    '**/generated/**'
            ])
        })
    }
}

diffCoverageReport {
    diffSource {
        git.compareWith 'refs/remotes/origin/main'
    }

    jacocoExecFiles = files(jacocoTestReport.executionData)
    classesDirs = files(jacocoTestReport.classDirectories)
    srcDirs = files(jacocoTestReport.sourceDirectories)

    reports {
        html = true
        baseReportDir = "${buildDir}/coverage-report"
    }
}

Diffcoverage fails with Empty File Collection if Clean is used

Describe the bug

When running a task like:

./gradlew clean testDebugUnitTestCoverage diffCoverage --no-build-cache

And configuring where the location of the class files can be found. Diff Coverage will through an error:

  • What went wrong:
    Could not determine the dependencies of task ':lib:diffCoverage'.

'diffCoverageReport.classesDirs' file collection is empty.

This is becuase the clean will have wiped out the location of the files and the configuration happens before the files are loaded.

Currently:

https://github.com/form-com/diff-coverage-gradle/blob/master/diff-coverage/src/main/kotlin/com/form/coverage/gradle/DiffCoverageTask.kt#L38

calls collectFilesOrThrow which eagerly collects the files instead of lazily doing it after the configuration phase has completed.

Ideally these should take Providers instead of FileCollections directly, so that when the task is executing it can get the files at that particular time instead of eagerly doing it whenever the get method is called.

That will always throw an error if clean is used. If clean is not used and the coverage has run before as a seperate step it'll pass.

Ideally a FileCollectionProvider should be used and read from the ReportGenerator.

Desktop (please complete the following information):

  • OS: all
  • Gradle version: 7.4.1
  • Diff Coverage plugin version: 0.9.3

To Reproduce

./gradlew clean jacocoReport diffCoverage

Works if:

./gradlew clean jacocoReport
./gradlew diffCoverage

Expected behavior

./gradlew clean jacocoReport diffCoverage

should work without crashing

A clear and concise description of what you expected to happen.

Logs

Could not determine the dependencies of task ':lib:diffCoverage'.

'diffCoverageReport.classesDirs' file collection is empty.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.