Code Monkey home page Code Monkey logo

gradle-nexus-staging-plugin's People

Contributors

akomakom avatar alvarosanchez avatar deanhillertwitter avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar driver733 avatar larsgrefer avatar oss-codearte avatar plnech avatar sikevux avatar strelok1 avatar szpak avatar therock24 avatar vampire avatar wtanaka 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  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  avatar  avatar  avatar  avatar

gradle-nexus-staging-plugin's Issues

performance is amazing under org.gradle.parallel=true and org.gradle.configureondemand=true BUT it doesn't work

Great project though I have struggled getting through very cryptic messages and finally found out this plugin doesn't work with org.gradle.parallel either.

It seems to randomly create N repos and I have to turn these features off. It was nice as it slammed uplaoding all my files in a multiproject build up to nexus really fast so my release didn't take long at all. Now it takes forever with these properties off.

Once I disable the org.gradle.parallel feature (and the other one too), I finally get just a single nexus repo with all my jars. Now on to trying to close and promote.

Also, I noticed promote does not depend on close? Shouldn't there be a best effort to close before promotion? just curious on that front.

Support for parallel release of different projects in the same staging profile

In the same packageGroup we handle a lot of artifacts. This means that if we try to closeAndPromote artifact C while we still have artifact A and B in the staging area, C will fail.

Isn't there a way in the nexusStaging closure to provide apart from packageGroup, also artifactId so that this issue is overcome?

is there some local setup for this project(1 test fails, the rest pass)

The web page from gradle is this text

Condition not satisfied:

result.standardOutput.contains("Using username 'testUsername' and password from repository 'Test repo'")
|      |              |
|      |              false
|      The client will now receive all logging from the daemon (pid: 21753). The daemon log file: /Users/dhiller/.gradle/daemon/2.13/daemon-21753.out.log
|      Starting 26th build in daemon [uptime: 44 mins 34.198 secs, performance: 98%, memory: 28% of 954.7 MB]
|      Executing build with daemon context: DefaultDaemonContext[uid=5057097a-aa33-49ba-99d3-b744b9c1332a,javaHome=/opt/twitter_mde/package/TwitterJDK/e2fcfaf92295baf2a4c041a9680f7f4bf11ef591d26a41ffd77a81c6296d4cd7/Contents/Home,daemonRegistryDir=/Users/dhiller/.gradle/daemon,pid=21753,idleTimeout=10800000,daemonOpts=-XX:MaxPermSize=256m,-XX:+HeapDumpOnOutOfMemoryError,-Xmx1024m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]
|      Closing daemon's stdin at end of input.
|      The daemon will no longer process any standard input.
|      Starting Build
|      Settings evaluated using settings file '/Library/Workflow/gradle-nexus-staging-plugin/build/test/io.codearte.gradle.nexus.functional.PasswordFunctionalSpec/should-read-password-from-repository-configured-in-uploadArchives/settings.gradle'.
|      Projects loaded. Root project using build file '/Library/Workflow/gradle-nexus-staging-plugin/build/test/io.codearte.gradle.nexus.functional.PasswordFunctionalSpec/should-read-password-from-repository-configured-in-uploadArchives/build.gradle'.
|      Included projects: [root project 'uploadArchives']
|      Evaluating root project 'uploadArchives' using build file '/Library/Workflow/gradle-nexus-staging-plugin/build/test/io.codearte.gradle.nexus.functional.PasswordFunctionalSpec/should-read-password-from-repository-configured-in-uploadArchives/build.gradle'.
|      Compiling build file '/Library/Workflow/gradle-nexus-staging-plugin/build/test/io.codearte.gradle.nexus.functional.PasswordFunctionalSpec/should-read-password-from-repository-configured-in-uploadArchives/build.gradle' using BuildScriptTransformer.
|      All projects evaluated.
|      Selected primary task 'getStagingProfile' from project :
|      Tasks to be executed: [task ':getStagingProfile']
|      Using username '[email protected]' and password from repository 'Test repo'
|      Creating In-memory cache of /Library/Workflow/gradle-nexus-staging-plugin/build/test/io.codearte.gradle.nexus.functional.PasswordFunctionalSpec/should-read-password-from-repository-configured-in-uploadArchives/.gradle/2.13/taskArtifacts/fileHashes.bin: MaxSize{400000}
|      Creating In-memory cache of /Library/Workflow/gradle-nexus-staging-plugin/build/test/io.codearte.gradle.nexus.functional.PasswordFunctionalSpec/should-read-password-from-repository-configured-in-uploadArchives/.gradle/2.13/taskArtifacts/fileSnapshots.bin: MaxSize{10000}
|      Creating In-memory cache of /Library/Workflow/gradle-nexus-staging-plugin/build/test/io.codearte.gradle.nexus.functional.PasswordFunctionalSpec/should-read-password-from-repository-configured-in-uploadArchives/.gradle/2.13/taskArtifacts/taskArtifacts.bin: MaxSize{2000}
|      :getStagingProfile (Thread[Daemon worker Thread 2,5,main]) started.
|      :getStagingProfile
|      Executing task ':getStagingProfile' (up-to-date check took 0.0 secs) due to:
|        Task has not declared any outputs.
|      Getting staging profile for package group 'com.example.upload1'
|      :getStagingProfile FAILED
|      :getStagingProfile (Thread[Daemon worker Thread 2,5,main]) completed. Took 4.514 secs.
|       
|      BUILD FAILED
|       
|      Total time: 4.661 secs
|      Stopped 0 compiler daemon(s).
nebula.test.functional.internal.toolingapi.ToolingExecutionResult@564aa7e8

	at io.codearte.gradle.nexus.functional.PasswordFunctionalSpec.should read password from repository configured in uploadArchives(PasswordFunctionalSpec.groovy:16)

Std. out is not interesting and only prints out each running test. There is no std. err.

E2E tests should not be enabled in PR builds

E2E are enabled in Travis build with Java 7. In PR builds there is no Nexus credentials available which (intentionally) fails the build. E2E tests are not intended to be executed in PR builds.

releaseRepository FAILED but Succeded

I'm using latest 0.8.0 version to automate javers releases to Sonatype OSSRH.

So this is a main feature of gradle-nexus-staging-plugin: to release an OSS project to Central via Sonatype Nexus.

In my case, most (I mean more then 70%) releasing build fails. In most cases they are red but succeded.

For example, here is the red but Succeded build:
https://travis-ci.org/javers/javers/builds/233004324

plugin says:

Total time: 2 mins 26.62 secs
closeAndPromoteRepository...
:closeRepository
Requested operation wasn't successful in first try. Retrying maximum 10 times with 3 seconds delay between.
:releaseRepository
Requested operation wasn't successful in first try. Retrying maximum 10 times with 3 seconds delay between.
Attempt 11/11 failed. RepositoryInTransitionException was thrown with message 'Repository 'org[secure]-1145' (in 'closed' state) is in transition. Check again later.'. Giving up. Configure longer timeout if necessary.
:releaseRepository FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':releaseRepository'.
> Repository 'org[secure]-1145' (in 'closed' state) is in transition. Check again later.

but, surprisingly, release 3.2.0-RC4 was released properly to Sonatype and Staging repository is properly released and closed.

Make functional tests work also on Windows

As reported in #36. The issue is with old nebula-test version (nebula-plugins/nebula-test#77). PoC proved that there will be required to bump some other dependencies and Gradle version to fix it.

Running test from C:\code\gradle-nexus-staging-plugin\build\test\io.codearte.gradle.nexus.functional.MockedFunctionalSpec\should-not-do-request-for-staging-profile-when-provided-in-configuration-on-testedTaskName-task_8

org.gradle.api.GradleException: Build aborted because of an internal error.

	at nebula.test.functional.internal.DefaultExecutionResult.rethrowFailure(DefaultExecutionResult.groovy:97)
	at nebula.test.IntegrationSpec.runTasksSuccessfully(IntegrationSpec.groovy:265)
	at io.codearte.gradle.nexus.functional.MockedFunctionalSpec.should not do request for staging profile when provided in configuration on #testedTaskName task(MockedFunctionalSpec.groovy:36)
Caused by: org.gradle.internal.exceptions.LocationAwareException: Build file 'C:\code\gradle-nexus-staging-plugin\build\test\io.codearte.gradle.nexus.functional.MockedFunctionalSpec\should-not-do-request-for-staging-profile-when-provided-in-configuration-on-testedTaskName-task_8\build.gradle' line: 4
A problem occurred evaluating root project 'should-not-do-request-for-staging-profile-when-provided-in-configuration-on-testedTaskName-task'.
	at org.gradle.initialization.DefaultExceptionAnalyser.transform(DefaultExceptionAnalyser.java:74)
	at org.gradle.initialization.MultipleBuildFailuresExceptionAnalyser.transform(MultipleBuildFailuresExceptionAnalyser.java:47)
	at org.gradle.initialization.StackTraceSanitizingExceptionAnalyser.transform(StackTraceSanitizingExceptionAnalyser.java:30)
	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:101)
	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
	at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
	at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
	at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
	at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:81)
	at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:46)
	at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
	at org.gradle.util.Swapper.swap(Swapper.java:38)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
	at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
	at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: org.gradle.api.GradleScriptException: A problem occurred evaluating root project 'should-not-do-request-for-staging-profile-when-provided-in-configuration-on-testedTaskName-task'.
	at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:93)
	at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl$2.run(DefaultScriptPluginFactory.java:157)
	at org.gradle.configuration.ProjectScriptTarget.addConfiguration(ProjectScriptTarget.java:72)
	at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:162)
	at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:38)
	at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:25)
	at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:34)
	at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:55)
	at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:529)
	at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:90)
	at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:42)
	at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:35)
	at org.gradle.initialization.DefaultGradleLauncher$2.run(DefaultGradleLauncher.java:125)
	at org.gradle.internal.Factories$1.create(Factories.java:22)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:122)
	at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
	... 42 more
**Caused by: org.gradle.api.plugins.UnknownPluginException: Plugin with id 'io.codearte.nexus-staging' not found.**
	at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:110)
	at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.applyType(DefaultObjectConfigurationAction.java:113)
	at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.access$200(DefaultObjectConfigurationAction.java:36)
	at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction$3.run(DefaultObjectConfigurationAction.java:80)
	at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.execute(DefaultObjectConfigurationAction.java:136)
	at org.gradle.api.internal.project.AbstractPluginAware.apply(AbstractPluginAware.java:46)
	at org.gradle.api.internal.project.ProjectScript.apply(ProjectScript.groovy:35)
	at build_cw6cuz34b890se4thjgcstlxv.run(C:\code\gradle-nexus-staging-plugin\build\test\io.codearte.gradle.nexus.functional.MockedFunctionalSpec\should-not-do-request-for-staging-profile-when-provided-in-configuration-on-testedTaskName-task_8\build.gradle:4)
	at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:91)
	... 60 more

Applying the plugin to a library project

Issue

I'm having an issue applying the plugin to a library project:

  • If I follow the instructions, add the buildscript dependencies in the root build.gradle and configure via the nexusStaging block, then building a project with the library is impossible unless the project using our library has the plugin too:
FAILURE: Build failed with an exception.

* Where:
Build file '/projectRoot/myLibrary/build.gradle' line: 37

* What went wrong:
A problem occurred evaluating project ':myLibrary'.
> Could not find method nexusStaging() for arguments [build_b1zw94dj1r82plfo4rpw08r8e$_run_closure2@6b09ab9c] on project ':myLibrary'.
  • If I instead add the dependencies in myLibrary's build.gradle, everything works fine but every build displays WARNING. Nexus staging plugin should only be applied to the root project in build..

Questions

  • What is the issue with applying the plugin in the library's build.gradle rather than the root one?
  • Is there a recommended way of applying the plugin for the library's release without forcing every user to apply it to his project too?

Fail when applied on non-root project

Currently there is a warning displayed, but there were invalid issues reported which tends that people do not read it. Error should be thrown with detailed information why it happened and a request to report an issue when it is really needed.

When there is only one open repository but lots of closed ones, WrongNumberOfRepositories exception is thrown

Or am I doing something wrong?

io.codearte.gradle.nexus.logic.RepositoryFetcher#getOpenRepositoryIdForStagingProfileId method is called with ("open", stagingProfileId) and following the call stack it eventually reaches the

io.codearte.gradle.nexus.logic.RepositoryFetcher#verifyThatOneRepositoryAndReturnIt method which takes the response map and the repositoryState parameter. This parameter is never used. I have hundreds of "closed" repositories in a staging profile, but only one "open" one. This method of course throws a WrongNumberOfRepositories exception as it checks the response size only.

Shouldn't it be:

    private Map verifyThatOneRepositoryAndReturnIt(Map responseAsMap, String repositoryState) {
        int numberOfRespositories = responseAsMap.data.count { it.type == repositoryState }
        if (numberOfRespositories != 1) {
            throw new WrongNumberOfRepositories(numberOfRespositories, repositoryState)
        }
        Map repository = responseAsMap.data.find { it.type == repositoryState } as Map
        return repository
    }

People using this plugin, do you ever only have ONE repository in your staging profile and it's always open?

Deploying multiple artifacts failing

Hi,

first of all thanks for a great plugin. Using it on our CI/CD server, but have run into an issue. Not sure if it's related to our config or not but the problem arises when there are multiple staging repositories.
I'm getting this error message

Execution failed for task ':lib:closeRepository'.
> Wrong number of received repositories in state 'open'. Expected 1, received 2

It says there are two repositories in state open, however one of them is closed/released. Support for dropping, #17 , would solve the problem, but maybe there's something else we can do to fix this?

Thanks,
Håkon

Unable to close repository

Hi,
I've issues closing my staging repository.

I'm using the maven plugin to deploy the artifacty to OSS.

But when calling closeRepository I get a Bad Request response from the server. The response contains the following: Staging of Repository within profile ID='X' is not yet started!

Any ideas what is missing so that I'm able to call closeRepository?

Here is the build log without debuggging: https://travis-ci.org/foxylion/rethinkdb-orm-java/builds/137925647

Manually closing on the web GUI just went fine.

Regards,
Jakob

Verify that repository has been really closed

Nexus returns 201 Created when accepts request to close a repository:

Sending request: POST /service/local/staging/profiles/xxx/finish HTTP/1.1
Receiving response: HTTP/1.1 201 Created

It is enough for a Gradle tasks to finish successfully. Occasionally that operation can fail (e.g. signature validation when using Sonatype OSS instance). Usually it's not a big issue as closeRepository is followed by promoteRepository, however in CD pipeline with closeRepository -> pushReleaseTag -> promoteRepository steps pushing a release tag to SCM is performed while it should not.

A closeRepository task probably could wait for a close operation to finish.

Suggest longer timeout if failed on time related operations even without --info enabled

The output without --info:

closeRepository
POST response data: null
:promoteRepository FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':promoteRepository'.
> Unexpected state of reveived repository. Received open, expected closed

while underthehood there are multiple retries performed (pretty visible with --info).

ResponseParseException with every task but `getStagingProfile`

Calling closeRepository/promoteRepository/closeAndPromoteRepository fails with the following exception:

:myProject:promoteRepository
Error parsing 'text/html' response
groovy.json.JsonException: Unable to determine the current character, it is not a string, number, array, or object

The current character read is '<' with an int value of 60
Unable to determine the current character, it is not a string, number, array, or object
line number 1
index number 0
<html>
^
    at groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:216)
    at groovy.json.internal.JsonParserCharArray.decodeValue(JsonParserCharArray.java:166)
    at groovy.json.internal.JsonParserCharArray.decodeFromChars(JsonParserCharArray.java:45)
    at groovy.json.internal.JsonParserCharArray.parse(JsonParserCharArray.java:409)
    at groovy.json.internal.BaseJsonParser.parse(BaseJsonParser.java:121)
    at groovy.json.JsonSlurper.parse(JsonSlurper.java:224)
    at groovyx.net.http.ParserRegistry.parseJSON(ParserRegistry.java:280)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1206)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1073)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1015)
    at groovy.lang.Closure.call(Closure.java:423)
    at groovy.lang.Closure.call(Closure.java:439)
    at groovyx.net.http.HTTPBuilder.parseResponse(HTTPBuilder.java:560)
    at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:489)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1070)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1044)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:515)
    at groovyx.net.http.RESTClient.get(RESTClient.java:119)
    at io.codearte.gradle.nexus.infra.SimplifiedHttpJsonRestClient.get(SimplifiedHttpJsonRestClient.groovy:33)
    at io.codearte.gradle.nexus.infra.SimplifiedHttpJsonRestClient$get.call(Unknown Source)
    at io.codearte.gradle.nexus.logic.RepositoryFetcher.getRepositoryIdWithGivenStateForStagingProfileId(RepositoryFetcher.groovy:21)
    at io.codearte.gradle.nexus.logic.RepositoryFetcher.getClosedRepositoryIdForStagingProfileId(RepositoryFetcher.groovy:16)
    at io.codearte.gradle.nexus.PromoteRepositoryTask$_doAction_closure1.doCall(PromoteRepositoryTask.groovy:22)
    at io.codearte.gradle.nexus.PromoteRepositoryTask$_doAction_closure1.doCall(PromoteRepositoryTask.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:292)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1015)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at io.codearte.gradle.nexus.logic.OperationRetrier.doWithRetry(OperationRetrier.groovy:29)
    at io.codearte.gradle.nexus.PromoteRepositoryTask.doAction(PromoteRepositoryTask.groovy:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:226)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:219)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:208)
    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:589)
    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:572)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:90)
    at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:49)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:71)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
:myProject:promoteRepository FAILED

Rename "promote" operation to "release"

Working on #37 it turned out that in fact in OSSRH release operation is performed instead of promote. Therefore to be more consistent and in addition to open a possibility to add real "promote" operation in the future (could be used in self-hosted Nexus Professional) name of the tasks should be changed. Old tasks will be marked as deprecated and possibly be removed in the future.

closeAndPromoteRepository races with OSSRH

As of a month or two ago, my release builds are consistently failing with the error message

:promoteRepository FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':promoteRepository'.
> Unexpected state of reveived repository. Received open, expected closed

When I go to oss.sonatype.org, I always find the repository is in fact closed, so I'm pretty certain closeAndPromoteRepository is racing with the checks performed when a repository close is requested. I could add an artificial delay in my Gradle file, but this fragile and only helps me. Assuming the OSSRH API gives us no way to check whether promotion actually failed, one solution could be to wait and retry if the repository is still open, with a timeout to catch genuine failure.

Wrong number of received repositories in state 'open'. Expected 1, received 86

There's only one open staging repository for my groupId org.zanata (repository orgzanata-1177, with the staging profile org.zanata), but in the Nexus UI I can see lots of other open staging repositories, eg central_bundles-10602 from various other OSS projects, all with the staging profile Central Bundles. It's been like that for years, but now I'm wondering if that is normal after all. Should gradle-nexus-staging-plugin skip over the repositories with the generic profile Central Bundles?

Consider better lower level network errors handling

Currently only HttpResponseException (e.g. 404, 500) is caught in the REST client. Other, such as java.net.ConnectException: Connection refused (Connection refused) are caught at the Gradle level. Does it make sense to handle it in the plugin?

dryRun mode

To easier test manually when embedding in some larger solutions.

Auto drop repository after release

It turned out there is an undocumented parameter "autoDropAfterRelease" which drops staging repository "immediately" after release (in earlier Nexus versions it seemed to happen automatically anyway). It would be good to use it to time when more that one staging repository exists.

As that feature is not documented in the REST API it would be needed to create a functional tests with fake Nexus user to verify it's behavior before going to production.

Reusing stagingRepositoryId from close task bypasses retry mechanism and fails

When repository ID is read from server retry mechanism is able to wait for the repo to be effectively closed. This effectively breaks closeAndPromoteRepository task...

:closeRepository (Thread[Daemon worker Thread 9,5,main]) started.
:closeRepository
Putting task artifact state for task ':closeRepository' into context took 0.0 secs.
Executing task ':closeRepository' (up-to-date check took 0.0 secs) due to:
  Task has not declared any outputs.
Getting staging profile for package group 'io.gitlab.nexus-at'
Getting 'open' repository for staging profile '5027d084a01a3a'
Closing repository 'iogitlabnexus-at-1014' with staging profile '5027d084a01a3a'
Repository 'iogitlabnexus-at-1014' with staging profile '5027d084a01a3a' has been closed
:closeRepository (Thread[Daemon worker Thread 9,5,main]) completed. Took 5.408 secs.
:promoteRepository (Thread[Daemon worker Thread 9,5,main]) started.
:promoteRepository
Putting task artifact state for task ':promoteRepository' into context took 0.0 secs.
Executing task ':promoteRepository' (up-to-date check took 0.0 secs) due to:
  Task has not declared any outputs.
Using configured staging profile id: 5027d084a01a3a
Promoting repository 'iogitlabnexus-at-1014' with staging profile '5027d084a01a3a'
POST response failed. 500: Server Error, body: [errors:[[id:*, msg:Unhandled: Repository: iogitlabnexus-at-1014 has invalid state: open]]]
:promoteRepository FAILED
:promoteRepository (Thread[Daemon worker Thread 9,5,main]) completed. Took 1.531 secs.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':promoteRepository'.
> 500: Server Error, body: [errors:[[id:*, msg:Unhandled: Repository: iogitlabnexus-at-1014 has invalid state: open]]]

This is a regression in 0.6.0 in which reusing repo id has been introduced - #36.

uploadArchives does nothing. What am I missing?

I have my credentials in ~/.gradle/gradle.properties and this is my build.gradle

apply plugin: 'maven'
apply plugin: 'idea'

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.5.1"
  }
}

apply plugin: 'io.codearte.nexus-staging'

allprojects  {
  apply plugin: 'java'

  group = 'me.tomassetti'
  version = '0.2.0-SNAPSHOT'
}

subprojects {
  apply plugin: 'java'
  sourceCompatibility = 1.8
  targetCompatibility = 1.8


  repositories {
    mavenCentral()

    maven { url "http://repo.maven.apache.org/maven2" }
  }

}


if (project.hasProperty('release')) {

  subprojects {

    task javadocJar(type: Jar) {
      classifier = 'javadoc'
      from javadoc
    }

    task sourcesJar(type: Jar) {
      classifier = 'sources'
      from sourceSets.main.allSource
    }

    artifacts {
      archives javadocJar, sourcesJar
    }
  }

  allprojects {
    apply plugin: 'signing'
    apply plugin: 'maven'

    // Signature of artifacts
    signing {
      sign configurations.archives
    }

    if (JavaVersion.current().isJava8Compatible()) {
      allprojects {
        tasks.withType(Javadoc) {
          options.addStringOption('Xdoclint:none', '-quiet')
        }
      }
    }

    // OSSRH publication
    uploadArchives {
      repositories {
        mavenDeployer {
          // POM signature
          beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
          // Target repository
          repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
            authentication(userName: ossrhUsername, password: ossrhPassword)
          }
          pom.project {
            name project.name
            description project.description
            packaging 'jar'
            url 'https://github.com/ftomassetti/java-symbol-solver'

            scm {
              connection 'scm:git:https://github.com/ftomassetti/java-symbol-solver.git'
              developerConnection 'scm:git:[email protected]:ftomassetti/java-symbol-solver.git'
              url 'https://github.com/ftomassetti/java-symbol-solver.git'
            }

            licenses {
              license {
                name 'The MIT License (MIT)'
                url 'http://opensource.org/licenses/MIT'
                distribution 'repo'
              }
            }

            developers {
              developer {
                id = 'ftomassetti'
                name = 'Federico Tomassetti'
                email = '[email protected]'
              }
            }
          }
        }
      }
    }

  }
}

def v_ossrhUsername="FOO"
def v_ossrhPassword="FOO"

if (project.hasProperty("ossrhUsername")) {
  v_ossrhUsername = ossrhUsername
}
if (project.hasProperty("ossrhPassword")) {
  v_ossrhPassword = ossrhPassword
}

nexusStaging {
  username = v_ossrhUsername
  password = v_ossrhPassword
}

When I run gradle uploadArchives I see this:

~/r/java-symbol-solver ❯❯❯ gradle uploadArchives                                                                                                                                                                                     ⏎
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar UP-TO-DATE
:uploadArchives
:java-symbol-solver-model:compileJava UP-TO-DATE
:java-symbol-solver-model:processResources UP-TO-DATE
:java-symbol-solver-model:classes UP-TO-DATE
:java-symbol-solver-model:jar UP-TO-DATE
:java-symbol-solver-logic:compileJava UP-TO-DATE
:java-symbol-solver-logic:processResources UP-TO-DATE
:java-symbol-solver-logic:classes UP-TO-DATE
:java-symbol-solver-logic:jar UP-TO-DATE
:java-symbol-solver-core:compileJava UP-TO-DATE
:java-symbol-solver-core:processResources UP-TO-DATE
:java-symbol-solver-core:classes UP-TO-DATE
:java-symbol-solver-core:jar UP-TO-DATE
:java-symbol-solver-core:uploadArchives
:java-symbol-solver-examples:compileJava UP-TO-DATE
:java-symbol-solver-examples:processResources UP-TO-DATE
:java-symbol-solver-examples:classes UP-TO-DATE
:java-symbol-solver-examples:jar UP-TO-DATE
:java-symbol-solver-examples:uploadArchives
:java-symbol-solver-logic:uploadArchives
:java-symbol-solver-model:uploadArchives

BUILD SUCCESSFUL

Total time: 2.744 secs

However on OSSHR I cannot find anything in the staging repositories. Any idea?

Investigate correlation between artifacts upload and staging repository ID

Gradle doesn't provide any information about an ID of a staging repository (in a case of Nexus) where artifacts have been uploaded. It is needed to (optionally) correlate uploaded artifacts with a staging repository which should be closed/promoted by gradle-nexus-staging-plugin. It in turns is needed to make it possible have more than one open (closed) staging repository in Nexus for the same staging profile (see here and there why it is needed).

Cannot close Nexus repository with closeRepository task

Hi,

I'm not sure if this is the right place, but please correct me if it isn't :)

when I run: ./gradlew uploadArchives
the process runs successfully and the artifacts are uploaded.
But then when I then run: ./gradlew closeRepository (or closeAndPromoteRepository)
I get this error:

:closeRepository FAILED

FAILURE: Build failed with an exception.

* What went wrong:
A problem was found with the configuration of task ':closeRepository'.
> No value has been specified for property 'packageGroup'.

But in my build.gradle I have:

nexusStaging {
    packageGroup = GROUP //optional if packageGroup == project.getGroup()
}

and in gradle.properties: GROUP = com.company

when I ran it with --debug I noticed:

12:11:15.899 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Starting to execute task ':closeRepository'
12:11:15.902 [DEBUG] [java_lang_invoke_MethodHandles$lookup] project.group: '', class: class java.lang.String
12:11:15.903 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter] Finished executing task ':closeRepository'
12:11:15.903 [LIFECYCLE] [class org.gradle.TaskExecutionLogger] :closeRepository FAILED

So I also tried to add: group = GROUP
but that didn't help.

Any idea why is this happening? How do I fix it ?

Close all repositories

When running multiple, parallel builds, I often get errors such as:

Execution failed for task ':closeRepository'.
Wrong number of received repositories in state 'open'. Expected 1, received 4

It would be nice to have a way to force the closure of all four open repos.

Cannot promote staging repositories any longer with upgrade of OSSRH

Hi,

Since the recent update of the Nexus OSSRH from 2.11.1-01 to 2.12.1-01, I cannot promote the staging repositories any longer.

The closing operation works fine, but the promotion operation fails after a few attempts (in my case, after 9 tries out of 31), with an undetermined "Server Error".

All details are in OSSRH-21248.

Thanks,
Damien.

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.