Giter VIP home page Giter VIP logo

nebula-release-plugin's Introduction

nebula-release-plugin

Support Status Gradle Plugin Portal Maven Central Build Apache 2.0

This plugin provides opinions and tasks for the release process provided by gradle-git.

Optional Configuration

If you want the release plugin to trigger or finalize a publishing task you will need to configure it:

tasks.release.dependsOn tasks.<publish task name>

-or-

tasks.release.finalizedBy tasks.<publish task name>

This plugin also detects the presence of the nebula-bintray-plugin and wires itself to depend on the task types used by bintrayUpload and artifactoryUpload.

Opinions

Project using this plugin will use semantic versions style strings. e.g. major.minor.patch-<prerelease>+<metadata>

All tasks default to bumping the minor version.

Extension Provided

nebulaRelease {
  Set<String> releaseBranchPatterns = [/master/, /HEAD/, /main/, /(release(-|\/))?\d+(\.\d+)?\.x/, /v?\d+\.\d+\.\d+/] as Set
  Set<String> excludeBranchPatterns = [] as Set
  String shortenedBranchPattern = /(?:(?:bugfix|feature|hotfix|release)(?:-|\/))?(.+)/

  void addReleaseBranchPattern(String pattern)
  void addExcludeBranchPattern(String pattern)
}
Property Type Default Description
releaseBranchPatterns Set<String> [master, HEAD, main, (release(-|\/))?\d+(\.\d+)?\.x, v?\d+\.\d+\.\d+] Branch patterns that are acceptable to release from. The default pattern will match things like master, 1.2.x, release-42.x, release/2.x, v1.2.3. If the set is empty releases will be possible from any branch that doesn't match excludeBranchPatterns.
excludeBranchPatterns Set<String> [] Branch patterns that you cannot release from. If a branch matches both releaseBranchPatterns and excludeBranchPatterns it will be excluded.
shortenedBranchPattern String (?:(?:bugfix|feature|hotfix|release)(?:-|\/))?(.+) Branch widget1 will append widget1 to snapshot version numbers, and branch (feature|bugfix|release|hotfix)/widget2 will append widget2 to snapshot version numbers. You may configure this field, the regex is expected to have exactly one capture group.
Method Arguments Description
addReleaseBranchPattern String pattern Calling this method will add a pattern to the set of releaseBranchPatterns, usage: nebulaRelease { addReleaseBranchPattern(/myregex/)
addExcludeBranchPattern String pattern Calling this method will add a pattern to the set of excludeBranchPatterns, usage: nebulaRelease { addExcludeBranchPattern(/myregex/)

Tasks Provided

All tasks will trigger gradle-git's release task which is configured to depend on the build task if the project produces JVM based jar or war artifacts.

  • final - Sets the version to the appropriate <major>.<minor>.<patch>, creates tag v<major>.<minor>.<patch>
  • candidate - Sets the version to the appropriate <major>.<minor>.<patch>-rc.#, creates tag v<major>.<minor>.<patch>-rc.# where # is the number of release candidates for this version produced so far. 1st 1.0.0 will be 1.0.0-rc.1, 2nd 1.0.0-rc.2 and so on.
  • devSnapshot - Sets the version to the appropriate <major>.<minor>.<patch>-dev.#+<hash>, does not create a tag. Where # is the number of commits since the last release and hash is the git hash of the current commit. If releasing a devSnapshot from a branch not listed in the releaseBranchPatterns and not excluded by excludeBranchPatterns the version will be <major>.<minor>.<patch>-dev.#+<branchname>.<hash>
    • You can use nebula.release.features.replaceDevWithImmutableSnapshot=true in your gradle.properties file to change pattern of version to <major>.<minor>.<patch>-snapshot.<timestamp>+<hash>. Where timestamp is UTC time in YYYYMMddHHmm format, ex. 201907052105 and hash is the git hash of the current commit. If releasing a immutableSnapshot from a branch not listed in the releaseBranchPatterns and not excluded by excludeBranchPatterns the version will be <major>.<minor>.<patch>-snapshot.<timestamp>+<branchname>.<hash>
  • snapshot - Sets the version to the appropriate <major>.<minor>.<patch>-SNAPSHOT, does not create a tag.

Use of devSnapshot vs snapshot is a project by project choice of whether you want maven style versioning (snapshot) or semantic versioned snapshots (devSnapshot).

Versioning Notes

We attempt to pick up on the fact that you're on certain release branches.

Examples:

  • On release/1.x - The plugin will default to versioning you 1.0.0-SNAPSHOT
  • On 3.x - The plugin will default to versioning you 3.0.0-SNAPSHOT
  • On 4.2.x - The plugin will default to versioning you 4.2.0-SNAPSHOT

Releasing: Bumping major or patch versions

There are many cases where a project may want to bump a part of the version string besides the minor number.

  • bump the major number: ./gradlew <snapshot|devSnapshot|candidate|final> -Prelease.scope=major
  • bump the patch number: ./gradlew <snapshot|devSnapshot|candidate|final> -Prelease.scope=patch

Releasing: Using last tag

In the scenario, where the tag is already created but you want to go through the release process, you can use the "Last Tag Strategy". When enabled, the plugin will respect the last tag as the version. This works well in a CI environment where a user will tag the code, and CI is configured to do just the release upon finding a new tag. The tag names need to follow the versioning scheme, e.g. "v1.0.1". To enact, provide the release.useLastTag project property, e.g.

git tag v1.0.0
./gradlew -Prelease.useLastTag=true final

Overriding version from the command line

To set the version from the command line, set the release.version system property:

./gradlew -Prelease.version=1.2.3 final

Caveats

First release with this plugin

If this is the first time releasing with this plugin and you've released in the past you may need to create a tag in your repository. You should find the hash of your latest release and create a tag of the format v<major>.<minor>.<patch> e.g. v1.4.2. For example, if the hash of your last release was da5d4f9:

git tag v1.4.2 da5d4f9
git push --tags
./gradlew final

Initial version not 0.1.0 or 1.0.0

This will create a tag v<string> where String is whatever you set on release.version. If you want the plugin to work from here on out you should choose a version that matches semantic versioning described above.

./gradlew -Prelease.version=42.5.0 final

Git root is in a different location from Gradle root

The plugin assumes Git root is in the same location as Gradle root. If this isn't the case, you may specify a different path for Git root via the git.root Gradle property. For example:

./gradlew -Pgit.root=<git root path> final

Sanitize versions

Historically, this plugin generated versions using build metadata which comes after the + sign. While we suggest using this approach to be semver compliant, some people has raised their need for removing the build medata and make it part of the pre-release string.

For this, starting on version 11.0.0 we have introduced a sanitizeVersion flag. Ex.

./gradlew -Prelease.sanitizeVersion=true devSnapshot

This will generate a version string similar to: 0.1.0-dev.2.e1c43c7

Please note that now the build metadata is part of the pre-release information and could affect how versions are handled by a SemVer library/tool.

Lifecycle Hooks

For devSnapshot

  • devSnapshotSetup - any kind of setup is good to live around here, e.g. setting status, various checks
  • release - probably have release dependOn any assemble and check tasks, dependsOn devSnapshotSetup
  • postRelease - any steps you want to happen after the repo tag, in our case this is where publishing happens since if the publish partially fails we don't want to fix the tags, dependsOn release
  • devSnapshot - command line task to kick off devSnapshot workflow, dependsOn postRelease

For snapshot

  • snapshotSetup - any kind of setup is good to live around here, e.g. setting status, various checks
  • release - probably have release dependOn any assemble and check tasks, dependsOn snapshotSetup
  • postRelease - any steps you want to happen after the repo tag, in our case this is where publishing happens since if the publish partially fails we don't want to fix the tags, dependsOn release
  • snapshot - command line task to kick off snapshot workflow, dependsOn postRelease

For candidate

  • candidateSetup - any kind of setup is good to live around here, e.g. setting status, various checks
  • release - this is where the tag is pushed to the repo, so probably have release dependOn any assemble and check tasks, dependsOn candidateSetup
  • postRelease - any steps you want to happen after the repo tag, in our case this is where publishing happens since if the publish partially fails we don't want to fix the tags, dependsOn release
  • candidate - command line task to kick off candidate workflow, dependsOn postRelease

For final

  • finalSetup - any kind of setup is good to live around here, e.g. setting status, various checks
  • release - this is where the tag is pushed to the repo, so probably have release dependOn any assemble and check tasks, dependsOn finalSetup
  • postRelease - any steps you want to happen after the repo tag, in our case this is where publishing happens since if the publish partially fails we don't want to fix the tags, dependsOn release
  • final - command line task to kick off final workflow, dependsOn postRelease

Gradle and Java Compatibility

Built with OpenJDK8 Tested with OpenJDK8

Gradle Version Works
5.0 yes
5.1 yes
5.2 yes
5.3 yes
5.4 yes
5.5 yes

LICENSE

Copyright 2014-2019 Netflix, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

nebula-release-plugin's People

Contributors

chali avatar danielthomas avatar emccallum avatar gw-vsasidharan avatar jkschneider avatar jotel avatar kranich avatar lavcraft avatar nadavc avatar odysseuslives avatar quidryan avatar rahulsom avatar reillylm avatar rpalcolea avatar rspieldenner avatar sabberworm avatar sghill avatar tobiasroland avatar tonit 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nebula-release-plugin's Issues

Underscores in feature branch names throw an error

Using this sort of branch name: feature/readjust_releasenote_publish throws the error below. (full output, just in case thatā€™s valuable)

I know this isnā€™t a bug in your library, but rather an (intended?) omission in https://github.com/zafarkhaja/jsemver, but Iā€™m trying to figure out why the actual branch name is being parsed once itā€™s clear itā€™s a feature branch versus a release branch, where the version might be needed? Iā€™d think that once feature was detected in the branch name, then the parsing of a version should stop, unless feature was a valid release branch?

Would you agree that _ should be a valid character in a branch name?

EDIT - I think what Iā€™m really trying to ask is whatā€™s the overall flow for parsing the branch name? At what point is it trying to extract a version, and how does that tie into the fact that Iā€™ve already declared that this should run as devSnapshot by using feature/ in the branch name?

Cause 1: Unexpected character 'ILLEGAL(_)' at position '32', expecting '[EOL]'
    at com.github.zafarkhaja.semver.VersionParser.consumeNextCharacter(VersionParser.java:516)
    at com.github.zafarkhaja.semver.VersionParser.parseValidSemVer(VersionParser.java:269)
    at com.github.zafarkhaja.semver.VersionParser.parseValidSemVer(VersionParser.java:195)
    at com.github.zafarkhaja.semver.Version$Builder.build(Version.java:158)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    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:368)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:137)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategyState$_toVersion_closure1.doCall(SemVerStrategyState.groovy:47)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    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:278)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
    at groovy.lang.Closure.call(Closure.java:423)
    at groovy.lang.Closure.call(Closure.java:439)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:235)
    at org.codehaus.groovy.runtime.dgm$614.invoke(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategyState.toVersion(SemVerStrategyState.groovy:43)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategyState$toVersion$9.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategy.doInfer(SemVerStrategy.groovy:145)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:207)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:56)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategy.infer(SemVerStrategy.groovy:119)
    at org.ajoberstar.gradle.git.release.base.VersionStrategy$infer$1.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
    at org.ajoberstar.gradle.git.release.base.ReleasePluginExtension$DelayedVersion.infer(ReleasePluginExtension.groovy:114)
    at org.ajoberstar.gradle.git.release.base.ReleasePluginExtension$DelayedVersion.toString(ReleasePluginExtension.groovy:120)
    at org.gradle.api.internal.artifacts.ProjectBackedModule.getVersion(ProjectBackedModule.java:38)
    at org.gradle.api.publish.maven.plugins.MavenPublishPlugin$MavenPublicationFactory.create(MavenPublishPlugin.java:176)
    at org.gradle.api.publish.maven.plugins.MavenPublishPlugin$MavenPublicationFactory.create(MavenPublishPlugin.java:162)
    at org.gradle.api.internal.DefaultPolymorphicDomainObjectContainer.doCreate(DefaultPolymorphicDomainObjectContainer.java:61)
    at org.gradle.api.internal.AbstractPolymorphicDomainObjectContainer.create(AbstractPolymorphicDomainObjectContainer.java:62)
    at org.gradle.api.internal.AbstractPolymorphicDomainObjectContainer.create(AbstractPolymorphicDomainObjectContainer.java:49)
    at org.gradle.api.PolymorphicDomainObjectContainer$create.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
    at nebula.plugin.publishing.maven.NebulaMavenPublishingPlugin$1.execute(NebulaMavenPublishingPlugin.groovy:79)
    at nebula.plugin.publishing.maven.NebulaMavenPublishingPlugin$1.execute(NebulaMavenPublishingPlugin.groovy)
    at org.gradle.listener.ActionBroadcast.execute(ActionBroadcast.java:39)
    at org.gradle.api.internal.plugins.ExtensionsStorage$DeferredConfigurableExtensionHolder.configureNow(ExtensionsStorage.java:183)
    at org.gradle.api.internal.plugins.ExtensionsStorage$DeferredConfigurableExtensionHolder.get(ExtensionsStorage.java:162)
    at org.gradle.api.internal.plugins.ExtensionsStorage.getByType(ExtensionsStorage.java:77)
    at org.gradle.api.internal.plugins.DefaultConvention.getByType(DefaultConvention.java:116)
    at org.gradle.api.publish.plugins.PublishingPlugin$Rules.publishing(PublishingPlugin.java:87)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
    at org.gradle.model.internal.inspect.ModelRuleInspector$MethodModelCreator.invoke(ModelRuleInspector.java:271)
    at org.gradle.model.internal.inspect.ModelRuleInspector$MethodModelCreator.create(ModelRuleInspector.java:253)
    at org.gradle.model.internal.registry.DefaultModelRegistry.doCreate(DefaultModelRegistry.java:389)
    at org.gradle.model.internal.registry.DefaultModelRegistry.createAndClose(DefaultModelRegistry.java:319)
    at org.gradle.model.internal.registry.DefaultModelRegistry.get(DefaultModelRegistry.java:315)
    at org.gradle.model.internal.registry.DefaultModelRegistry.element(DefaultModelRegistry.java:211)
    at org.gradle.model.internal.registry.DefaultModelRegistry.toInput(DefaultModelRegistry.java:430)
    at org.gradle.model.internal.registry.DefaultModelRegistry.toInputs(DefaultModelRegistry.java:422)
    at org.gradle.model.internal.registry.DefaultModelRegistry.fireMutation(DefaultModelRegistry.java:405)
    at org.gradle.model.internal.registry.DefaultModelRegistry.fireMutations(DefaultModelRegistry.java:340)
    at org.gradle.model.internal.registry.DefaultModelRegistry.close(DefaultModelRegistry.java:326)
    at org.gradle.model.internal.registry.DefaultModelRegistry.createAndClose(DefaultModelRegistry.java:320)
    at org.gradle.model.internal.registry.DefaultModelRegistry.get(DefaultModelRegistry.java:315)
    at org.gradle.model.internal.registry.DefaultModelRegistry.get(DefaultModelRegistry.java:205)
    at org.gradle.configuration.project.TaskModelRealizingConfigurationAction.execute(TaskModelRealizingConfigurationAction.java:31)
    at org.gradle.configuration.project.TaskModelRealizingConfigurationAction.execute(TaskModelRealizingConfigurationAction.java:27)
    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:521)
    at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:82)
    at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:31)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:129)
    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:80)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:36)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
    at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:51)
    at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:171)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
    at org.gradle.launcher.Main.doAction(Main.java:33)
    at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
    at org.gradle.launcher.GradleMain.main(GradleMain.java:23)

Interplay between release-plugin and plugins that consume project.version

Say you have a project configured to use gradle-ospackage-plugin to build daemon enabled RPMs.

You can run:

gradle clean final buildRpm

This will create a new tag v1.1.0 based on the rules for the release plugin the project.version property will be set to 1.1.0. buildRpmwill then create a new RPM using project.version=1.1.0. The rpm and jars created all have the correct version. Everything works as expected.

If I come back and run git checkout v1.1.0 the run gradle clean buildRpm I get the devSnapshot version beyond my checked out tag. (something like 1.2.0-dev.0+b6842e9).

Is this plugin intended to set the project.version property to the ambient version from git?

Option not to push tags to a git repo on a release

Howdy,

Spinnaker uses this extension to do its builds and releases. We are managing two different tag patterns for releases -- one with a build number and one without. We'd like to forego pushing the tags in certain types of releases while still specifying a version using -Prelease.version=, e.g.

./gradlew -Prelease.version=<someversion> -Prelease.noTagSync

where the version is overridden, but the tags aren't synced with the github repo.

Would you guys be open to a PR adding a flag to forego syncing tags? This seems like a reasonable thing to support, and shouldn't break any previous workflows.

How to re-release existing tag

How to re-release an already released or tag, when i have done further taggings and releases.

For example:

Two months back i released with rpm builds and with some tag 1.0.0, now i had already moved on to 2.0.0, but somehow i am realizing that i am missing some artefacts from the previous release and need to build the same release again.

How can i do that, cos i can't use the last tag true which will be 2.0.0 and above, I can't use the release.version=1.0.0 cos that will reset the tagging i believe in the repository or complain or can mess with something else which i don't even want to try before, knowing if that will be the best way to re-release using nebula ?

Unable to run final task with gradle version 4.3-rc-2

I recently upgraded gradle vserion to 4.3-rc-2 and nebula-release-plugin to the latest in my project and unable to run final task.When the final task tries to tag the git repository, its unable to create a release and also its attempting to start over again. By that i mean its trying to create a tag v0.0.1 rather than where it needs to increment from a previous version.

no tag is being created and no versioned is bumped

Executing several tasks on my "release-v0.2.0" branch does not lead to any useful result.
The tag is not pushed (even tho the log says it) and I don't know how it starts to bump the minor-version up or how I can tell him what version to bump. The documentation is not very helpful. Would love to see a real walkthrough in an example.

Here are some log outputs. As you can see the version never changed. I can tell you that the tag isn't created either.

final task

18:51:08: Executing external task ':final'...
Inferred project: toolbox-backend, version: 0.2.0-dev.35+2428dbf
:releaseCheck
:final
:prepare
:release
Pushing changes in [refs/heads/release-0.2.0] to origin

BUILD SUCCESSFUL

Total time: 1.269 secs
18:51:09: External task execution finished ':final'.

releaseCheck task

18:50:13: Executing external task ':releaseCheck'...
Inferred project: toolbox-backend, version: 0.2.0-dev.35+2428dbf
:releaseCheck

BUILD SUCCESSFUL

Total time: 0.301 secs
18:50:14: External task execution finished ':releaseCheck'.

Can I have 2 releases branches with 2 different versions ?

Can I have a release/0.1.x and a release/0.2.x branches and do release in those 2 branches ? Example I want to do a fix in version 0.1.0 even if the version 0.2.2 exists.

I would like to be able to do gradle final in the release/0.1.x and it creates a 0.1.1 version. Is it doable ? I thought it would be possible but I don't know how.

Not inferring correct version

I downloaded the plugin and and made a simple test project to play with.
After committing all changes and running the "final" command, the version was correctly set as "0.1.0"
However, I then immideiatly ran a build, and the project version was inferred as "0.2.0-dev.0+4a7632c", which is incorrect since there are no uncommited changes and 4a7632c is the "0.1.0" commit.
I've attached command output below, but I'm not sure how useful it is.

PS F:\Projects<removed> ./gradlew final
:releaseCheck
:final
:prepare
:release
Inferred project: , version: 0.1.0
Tagging repository as v0.1.0
Pushing changes in [refs/heads/master, v0.1.0] to origin

PS F:\Projects<removed> ./gradlew build

Inferred project: , version: 0.2.0-dev.0+4a7632c

Improve Error Message When Version Already Set

If the version property has already been set, the release task fails with this message:

* What went wrong:
Execution failed for task ':release'.
> No such property: inferredVersion for class: java.lang.String

better handling of project bootstrap errors

Not sure if this is covered in #15 - and maybe it doesn't totally make sense in the context of this plugin itself but it does in the context of something like nebula.netflixoss bringing this in.

If you are just trying to set up a brand new project (and haven't even git init'd it yet) the error displayed is something along the lines of 'Unable to locate repository' which given the overloaded usage of the word repository in both gradle and git land can be confusing. --stacktrace at least shows it coming from a git class which twigged that I should git init the thing (and then get an initial commit in place so it has a HEAD to locate)

Plugin can not be applied if root project does not have release task

Steps to reproduce:

  1. Clone RxJava repo https://github.com/ReactiveX/RxJava
  2. Create subdir rxjava
  3. Move src, build.gradle, gradle.properties to the rxjava folder
  4. Change settings.gradle to include ':rxjava'

The problem is that this plugin thinks that rootProject declares release task, but this is not true for setup when root project is just a container for subprojects (which is normal and common setup).

project.rootProject.tasks.release.dependsOn(task) in the ReleasePlugin ā€” is the reason of failure with message: Could not find property 'release' on task set.

Release branch with .x

Could you explain to me the choice to make the default release branch name regexp end with an explicit ".x"? I understand that I am able to change this (thanks very much for that), but I was hoping to understand the thinking here a little bit better. All the Gitflow articles I have read, including Driessen's, use release branches with names like 'release-2.2'.

Thank you.

Support Building Brand New Repository (without Commits)

A brand new repository will fail to build if the plugin is applied:

./gradlew build                                                                                                                                                  (1m 20s 301ms)
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar

FAILURE: Build failed with an exception.

* What went wrong:
No commit found for revision string: HEAD

Committing once fixes this:

Inferred project: gradlepoet, version: 0.1.0-dev.1.uncommitted+d8f0340

I think ideally we'd assume a version of 0.1.0-dev.1.uncommitted if there haven't been any commits.

Sample Buildfile:

plugins {
    id 'java'
    id 'nebula.release' version '4.1.0'
}

release.version can be set to empty string/null but is still used

Noticed while playing with various options in a Jenkins build that I can pass -Prelease.version= -Prelease.scope=patch and that created a tag of v. That is, a blank value for the version is accepted. This is on 2.2.4.

Seems like the point of the plugin would be to enforce server, so a version specified that doesnā€™t validate as server ought to be rejected or ignored.

In my case, I was hoping that I could pass a blank there and have that property ignored, which would be ideal for my use case but perhaps not what youā€™d prefer.

authenticity of host 'github.com' can't be established.

I use these commands:

gradle final
gradle candidate
gradle devSnapshot
gradle snapshot

pretask swt dialog window tell me
authenticity of host 'github.com' can't be established.
RSA key fingerprint is xxxx . It's diff with my github key fingerprint.

can someone help me ? thx.

Gnome-keyring asking for password for unrelated (?) ssh keys

(I'm on Ubuntu 14.04) I have multiple private keys in my ~/.ssh folder, but also one with the default name (id_rsa). When running ./gradlew prepare, gnome-keyring asks for the password for those SSH keys, while they are irrelevant for the git repository I'm using this plugin for. I deny to pass the passwords for those keys, after which the gradle task fails with:

Problem fetching from remote.

I'm not sure if this is a problem with this plugin or with the grgit plugin?

Git credentials

Hi

How can i send the git credentials by parameters? when i use on local, the plugin open a dialog to put, but how it is work on CI like jenkins

thanks

artifactorypublish execute when run final task

Hi
I am newbie to use nebula plugins, i came across a issue when combine bintray and release plugin. When I execute final task, why artifactory still running and try to publish a non snapshot version to oss.jfrog.org. Another similar issue when i execute snapshot task, why bintrayupload task also execute?

Release patches with patch version from existing tag

Releasing a patch should allow update of patch version, even if it is lower than the current master branch versions. This i believe is a critical issue.

Think of same product running some different versions on different sites 4.2.0 and 4.3.0. Now you end up finding some bug in 4.2.0 you need to patch it with different branch and need to release 4.2.1 with scope patch creating a branch called 4.2.X, this is not allowed due to some strategy in the nebula release.

Example:

gradle final -x test -x integrationTest -Prelease.scope=patch
Inferred project: test-project, version: 4.11.1

FAILURE: Build failed with an exception.

  • What went wrong:
    A problem occurred evaluating script.

    Inferred version (4.11.1) cannot be lower than nearest (4.12.0-rc.7). Required by selected strategy.

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

Some issue with nebula release plugin

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

    No such property: inferredVersion for class: java.lang.String

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

My build.gradle

/*
 * This build file was auto generated by running the Gradle 'init' tasks
 * by 'ajeets' at '1/6/16 1:42 PM' with Gradle 2.7
 *
 * This generated file contains a commented-out sample Java project to get you started.
 * For more details take a look at the Java Quickstart chapter in the Gradle
 * user guide available at https://docs.gradle.org/2.7/userguide/tutorial_java_projects.html
 */

/*
// Apply the java plugin to add support for Java
apply plugin: 'java'

// In this section you declare where to find the dependencies of your project
repositories {
    // Use 'jcenter' for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

// In this section you declare the dependencies for your production and test code
dependencies {
    // The production code uses the SLF4J logging API at compile time
    compile 'org.slf4j:slf4j-api:1.7.12'

    // Declare the dependency for your favourite test framework you want to use in your tests.
    // TestNG is also supported by the Gradle Test tasks. Just change the
    // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
    // 'test.useTestNG()' to your build script.
    testCompile 'junit:junit:4.12'
}
*/

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.netflix.nebula:nebula-release-plugin:3.1.1'
    }
}
apply plugin: 'nebula.nebula-release'
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'maven-publish'

// In this section you declare where to find the dependencies of your project
repositories {

    // Finds the snapshot jar in local repo first
    mavenLocal()

    // Nexus snapshots
    maven {
        url "http://172.0.1.50:8081/nexus/content/repositories/snapshots/"
    }

    // Nexus releases
    maven {
        url "http://172.0.1.50:8081/nexus/content/repositories/releases/"
    }
    // Novatti public repo for third parties
    maven {
        url "http://172.0.1.50:8081/nexus/content/groups/public"
    }

    // Maven central repositories for thirdparty libraries
    mavenCentral()

}

publishing {
    publications {
        maven (MavenPublication) {
            groupId = 'com.novatti.common'
            artifactId = 'common-novatti'
            from project.components.java
        }
    }

    repositories {
        maven {
            credentials {
                username "admin"
                password "devbox"
            }
            if (project.version.endsWith('-SNAPSHOT')){
                url "http://1.2.3.4:8081/nexus/content/repositories/snapshots/"
            } else {
                url "http://1.2.3.4:8081/nexus/content/repositories/releases"
            }
        }
    }
}

version = project.version.toString();

//tasks.release.dependsOn tasks.publish
//tasks.build.dependsOn tasks.snapshot

Improve releasing from an existing tag

Run through more test cases to discover edge cases.

including but not limited to:

  • Releasing from a tag that is not at head
  • Checking that the commit the build is releasing from is at the last tag

Release task fails if version set explicitly to a version

    * What went wrong:
    Execution failed for task ':release'.
    > No such property: inferredVersion for class: java.lang.String

    * Try:
    Run with --info or --debug option to get more log output.

    * Exception is:
    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':release'.
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:98)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:68)
            at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
            at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
            at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
            at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:46)
            at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)
            at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
            at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
            at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
            at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:236)
            at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:228)
            at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
            at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
            at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)
            at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:228)
            at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:215)
            at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:77)
            at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:58)
            at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:32)
            at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:113)
            at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
            at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
            at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
            at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
            at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
            at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
            at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
            at org.gradle.initialization.DefaultGradleLauncher$RunTasksAction.execute(DefaultGradleLauncher.java:230)
            at org.gradle.initialization.DefaultGradleLauncher$RunTasksAction.execute(DefaultGradleLauncher.java:227)
            at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
            at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
            at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
            at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:161)
            at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:112)
            at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:95)
            at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:66)
            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:26)
            at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)
            at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)
            at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:49)
            at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:31)
            at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
            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.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
            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.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
            at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
            at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
            at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
    Caused by: groovy.lang.MissingPropertyException: No such property: inferredVersion for class: java.lang.String
            at org.ajoberstar.gradle.git.release.base.BaseReleasePlugin$_addReleaseTask_closure4_closure6.doCall(BaseReleasePlugin.groovy:90)
            at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:656)
            at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:637)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.execute(ExecuteActionsTaskExecuter.java:115)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.execute(ExecuteActionsTaskExecuter.java:109)
            at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
            at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
            at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:109)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:90)
            ... 70 more

release tasks is not working if runned in composite build

release plugin works perfectly if runned from plain old gradle build

but when it's runned from composite build it fails to increment version falling back to devSnapshot

How to reproduce:
checkout
https://github.com/saladinkzn/release-report-composite
https://github.com/saladinkzn/release-report

runing following command in "release-report" folder leads to following output:

$ ./gradlew -q snapshot pV
1.1.0-SNAPSHOT

but if I run it in "release-report-composite" folder it leads to:

$ ./gradlew -q snapshot pV
1.1.0-dev.1.uncommitted+f978b71

Cannot configure the 'publishing' extension after it has been accessed.

Hi,
I've run into the following problem. Given the plugin configuration like:

buildscript {
    repositories { ... }
    dependencies {
        classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:4.4.0'
        classpath 'org.ajoberstar:gradle-git:1.5.1'
        classpath 'com.netflix.nebula:nebula-release-plugin:4.1.0'
    }
}

plugins {
    id "nebula.rpm" version "4.1.0"
}

apply plugin: 'com.jfrog.artifactory'
apply plugin: 'org.ajoberstar.release-opinion'
apply plugin: 'nebula.nebula-release'
apply plugin: 'maven-publish'

And publishing configuration like:

publishing {
    publications {
        mavenRpm(MavenPublication) {
            artifact rpm
        }
    }

When trying to add the following logic to releaseCheck task:

releaseCheck << {
    if (!(vbrVersion ==~ /^\d+\.\d+\.\d+$/) && !isSnapshotRelease) {
        throw new TaskExecutionException(it,
                new RuntimeException("VBR version not in correct format (d+.d+.d+)"))
    }
}

I get

Cannot configure the 'publishing' extension after it has been accessed.

When I check the publishing configration to

publishing.publications {
    mavenRpm(MavenPublication) {
        artifact rpm
    }
}

it works fine.
What is going on?

Question: Behavior across branches

We are using the release plugin and are a bit unsure of the correct behavior when working with multible branches.

The scenario:

  1. We have a MASTER branch with tag v1.0.0.
  2. We branch out to a DEVELOP branch. This will get v1.0.1-SNAPSHOT when building.
  3. We then commit changes to MASTER and release which will create tag v1.0.1
  4. We see that if we build on DEVELOP branch - it will remain a 1.0.1-SNAPSHOT, but we would expect it to be v1.0.2-SNAPSHOT?

What is the expected behavior when we are working on multible branches?

Thanks!

Poor behavior when version cannot be parsed

Branch dev/sdelaquier results in a really unfriendly failure:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'local-dev'.
> Failed to notify project evaluation listener.
   > Could not resolve all dependencies for configuration ':resolutionRules'.
      > com.github.zafarkhaja.semver.UnexpectedCharacterException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > java.lang.NullPointerException (no error message)
   > com.github.zafarkhaja.semver.UnexpectedCharacterException (no error message)
   > com.github.zafarkhaja.semver.UnexpectedCharacterException (no error message)
   > java.lang.NullPointerException (no error message)
   > com.github.zafarkhaja.semver.UnexpectedCharacterException (no error message)
   > java.lang.NullPointerException (no error message)
   > com.github.zafarkhaja.semver.UnexpectedCharacterException (no error message)
   > java.lang.NullPointerException (no error message)
   > com.github.zafarkhaja.semver.UnexpectedCharacterException (no error message)

All changes commited error.

I'm trying to release a final version for my project, but the plugin keep validating, telling that a final release require all changes to be committed into Git. But I don't have changes to commit.
screen shot 2016-06-19 at 8 30 11 am

Ordering of tasks can be wrong

Hey.
I just tried out the 5.0.0 lifecycle feature and noticed that despite the description that the release task depends on the specific xxxSetup task it does not. The ordering is determined by the task ordering logic of Gradle when there are no rules or dependencies (which is alphabetically I think).

So the feature works for e.g. with candidate, final, devSnapshot where the ordering is right but does not work with snapshot.

Output in my sample:

$> gradle snapshot -m

Inferred project: myproject, version: 2.0.0-SNAPSHOT
:prepare SKIPPED
:release SKIPPED
:compileJava SKIPPED
:compileGroovy SKIPPED
:generateResources SKIPPED
:pluginDescriptors SKIPPED
:processResources SKIPPED
:classes SKIPPED
:jar SKIPPED
:groovydoc SKIPPED
:publishPluginGroovyDocsJar SKIPPED
:publishPluginJar SKIPPED
:javadoc SKIPPED
:publishPluginJavaDocsJar SKIPPED
:publishPlugins SKIPPED
:postRelease SKIPPED
:releaseCheck SKIPPED
:snapshotSetup SKIPPED
:snapshot SKIPPED

My expectation would be that snapshotSetup and releaseCheck would always run before release.

Gradle task to retrieve the generated version use nebula

Hi,
after the build task,which produced new build version of our code,we want to call to a post gradle task.that will store/print/do somthing with the version that currently built

Any suggest how to that that?

note: our project produce a zip with pom file and we upload it to nexus,
maybe we can retrieve to version from that pom using gradle task?
Thanks !

Nebula Snapshot / Build

Nebula Snapshot & Build should not push any changes back to git, i consider build and snapshot being used for dev environment as well. I don't believe that any build should push the changes committed or un-committed to git. That process should be manual only because of many reasons for different dev environements and CI environments.

Example:

Our code review thing works with commit, but in between if I do a gradle build or snapshot it pushes the changes to git and closes our reviews because of that push.

Not compatible with nebula-publishing-plugins newer than v4.4.4

This works:

plugins {
    id 'nebula.maven-publish' version '4.4.4'
    id 'nebula.nebula-release' version '4.0.1'
}

This doesn't:

plugins {
    id 'nebula.maven-publish' version '4.7.0'
    id 'nebula.nebula-release' version '4.0.1'
}

Using gradle v2.13 on OSX. When I switch to using the newer maven-publish plugin, the release plugin is giving me the following error:

* What went wrong:
An exception occurred applying plugin request [id: 'nebula.nebula-release', version: '4.0.1']
> Failed to apply plugin [id 'nebula.nebula-release']
   > Systen wide config file /usr/local/git/etc/gitconfig is invalid org.eclipse.jgit.errors.ConfigInvalidException: Cannot read file /usr/local/git/etc/gitconfig

The /usr/local/git/etc/gitconfig file is on my system, and readable (git config -l works, for example) - but I'm not sure why upping the publish plugin version is breaking the release plugin. To me, it's a little hard to tell if this issue is really in the release plugin or the newer publishing plugin, but the combo is definitely giving me trouble. Any suggestions?

> Problem fetching from remote.

Hi,

I need some help to solve the issue from the subject when running
./gradlew candidate

from osx. The task failed with the following error message "Problem fetching from remote". When looking at gradle's stacktrace, I found the following error message related to authentication:

Caused by: org.eclipse.jgit.api.errors.TransportException: ssh://[email protected]:7999/op/springboot-playground.git: Auth fail at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:139) at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:76)

I am using a RSA private key and when I run git fetch or other remote commands at shell prompt everything works smoothly.

Any hints on how to get past this issue?

Question - possible to change scope for a devSnapshot build based on branch ancestry?

Not even sure if this makes sense, but we do release branches, and sometimes feature branches off those. However, if we do a final release of v1.1.0 on release/1.1.x, then the next inferred version by the devSnapshot task for our feature builds thinks we should jump to v1.2.0. I want this behavior if Iā€™m on master, but not when I am on a long lived release branch.

Iā€™m thinking an implementation that reads release branch structure and does the following:

  • if on a branch like release/1.1.x, run devSnapshot tasks with scope=patch
  • if on a branch like `release/1.x.x, run devSnapshot tasks with scope=minor

Do you think this would even be possible?

Typical workflow?

Hi, I'm looking at moving our builds to use nebula-release-plugin and was wondering what the typical/best workflow is? What does netflix use?

We currently use git-flow and manually release via sourcetree/smartgit (which merges our changes from develop->master and creates the specified tag in the process). We then build off master to create our release artifacts (with a simple semver script that uses the last tag to derive the version).

gradle-git/nebula-release-plugin seems to be more suited for a pull-request model (i.e. most OSS projects). If that's the case, are we better off moving to that model?

Better error messages for usage issues

gradle-git throws some hard to grok stack traces on usage issues such as trying to release a candidate or final version in a dirty repository. Improve error messages

Extension Provided methods throwing error

While I tried to achieve this, which I saw in the documentation:

nebulaRelease {
    Set<String> releaseBranchPatterns = [/master/, /HEAD/, /(release(-|\/))?\d+(\.\d+)?\.x/, /v?\d+\.\d+\.\d+/] as Set
    addReleaseBranchPattern(releaseBranchPatterns)
}

Gradle tells me off with this:

Error:(54, 0) Could not find method addReleaseBranchPattern() for arguments [[master, HEAD, (release(-|/))?\d+(.\d+)?.x, v?\d+.\d+.\d+]] on object of type nebula.plugin.release.ReleaseExtension.
Open File

Version not calculated correctly from release candidates

Scenario 1: do a ./gradlew candidate and then a simple ./gradlew version. You'll see that the inferred version is something like 2.1.0-rc.2.dev.0+0faf0e7 instead of 2.1.0-rc.2.0+0faf0e7

Scenario 2: do a ./gradlew candidate and then a ./gradlew devSnapshot. The snapshot released will be 2.1.0-rc.2.dev.0+0faf0e7. It would be better to either advance to the next version (e.g.2.2.0-dev.0+0faf0e7) or fail the build until ./gradlew final is called.

Thoughts?

check if version provided from command line is not in conflict to intended stage

I was (unfortunately) able to invoke the following command:
./gradlew clean snapshot -Prelease.version="2.7.1" which led to tagging my repo with sort of 'final' version tag despite the fact that the stage was 'snapshot' (as defined by the task 'snapshot')

I think this behaviour is incorrect - the plugin should either check for/append "-SNAPSHOT" to the version or better throw an exception with appropriate explanation.

Branch names with / cause version inference to fail

A branch name with a / separator isn't handled correctly for version schemes where the branch name is included. For example, bugfix/SPY-9208-test results in:

org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':common'.
    at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:79)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:57)
    at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:510)
    at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:90)
    at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:47)
    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)
    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.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
    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:78)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:48)
    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: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: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.artifacts.ResolveException: Could not resolve all dependencies for configuration ':common:classpath'.
    at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver.wrapException(ErrorHandlingConfigurationResolver.java:70)
    at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver.resolve(ErrorHandlingConfigurationResolver.java:45)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveGraphIfRequired(DefaultConfiguration.java:367)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveNow(DefaultConfiguration.java:342)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getResolvedConfiguration(DefaultConfiguration.java:335)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getResolvedConfiguration(Unknown Source)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:661)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getFiles(DefaultConfiguration.java:288)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getFiles(Unknown Source)
    at org.gradle.api.internal.initialization.DefaultScriptHandler.getScriptClassPath(DefaultScriptHandler.java:67)
    at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.defineScriptHandlerClassScope(DefaultPluginRequestApplicator.java:148)
    at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:55)
    at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:126)
    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)
    ... 51 more
Caused by: Unexpected character 'ILLEGAL(/)' at position '30', expecting '[EOI]'
    at com.github.zafarkhaja.semver.VersionParser.consumeNextCharacter(VersionParser.java:516)
    at com.github.zafarkhaja.semver.VersionParser.parseValidSemVer(VersionParser.java:269)
    at com.github.zafarkhaja.semver.VersionParser.parseValidSemVer(VersionParser.java:195)
    at com.github.zafarkhaja.semver.Version$Builder.build(Version.java:158)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategyState$_toVersion_closure1.doCall(SemVerStrategyState.groovy:47)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategyState.toVersion(SemVerStrategyState.groovy:43)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategyState$toVersion$9.call(Unknown Source)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategy.doInfer(SemVerStrategy.groovy:146)
    at org.ajoberstar.gradle.git.release.semver.SemVerStrategy.infer(SemVerStrategy.groovy:120)
    at org.ajoberstar.gradle.git.release.base.VersionStrategy$infer$1.call(Unknown Source)
    at org.ajoberstar.gradle.git.release.base.ReleasePluginExtension$DelayedVersion.infer(ReleasePluginExtension.groovy:117)
    at org.ajoberstar.gradle.git.release.base.ReleasePluginExtension$DelayedVersion.toString(ReleasePluginExtension.groovy:123)
    at org.gradle.api.internal.artifacts.ProjectBackedModule.getVersion(ProjectBackedModule.java:38)
    at org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier.newId(DefaultModuleVersionIdentifier.java:95)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.toRootComponentMetaData(DefaultConfiguration.java:549)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver$DefaultResolveContextToComponentResolver.resolve(DefaultArtifactDependencyResolver.java:140)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphBuilder.resolve(DependencyGraphBuilder.java:70)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver$1.execute(DefaultArtifactDependencyResolver.java:88)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver$1.execute(DefaultArtifactDependencyResolver.java:78)
    at org.gradle.internal.Transformers$4.transform(Transformers.java:137)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:61)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:39)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver.resolve(DefaultArtifactDependencyResolver.java:78)
    at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver$1.run(CacheLockingArtifactDependencyResolver.java:41)
    at org.gradle.internal.Factories$1.create(Factories.java:22)
    at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:192)
    at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:175)
    at org.gradle.cache.internal.DefaultPersistentDirectoryStore.useCache(DefaultPersistentDirectoryStore.java:106)
    at org.gradle.cache.internal.DefaultCacheFactory$ReferenceTrackingCache.useCache(DefaultCacheFactory.java:187)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultCacheLockingManager.useCache(DefaultCacheLockingManager.java:64)
    at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver.resolve(CacheLockingArtifactDependencyResolver.java:39)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultConfigurationResolver.resolve(DefaultConfigurationResolver.java:91)
    at org.gradle.api.internal.artifacts.ivyservice.SelfResolvingDependencyConfigurationResolver.resolve(SelfResolvingDependencyConfigurationResolver.java:40)
    at org.gradle.api.internal.artifacts.ivyservice.ShortCircuitEmptyConfigurationResolver.resolve(ShortCircuitEmptyConfigurationResolver.java:52)
    at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver.resolve(ErrorHandlingConfigurationResolver.java:43)
    ... 66 more

Prevent Non-Linear Version Incrementing by Default

Releasing a version that makes an unexpected jump is often unintended. It would be great if the plugin would prevent such changes by default. It's possible someone could want to do a larger jump (e.g. v8.0.0 to v8.5.0), so there should be a way to opt-out.

Successful examples:

Last Version on BranchNext Version
0.0.10.0.2
0.0.10.1.0
0.0.11.0.0

Failed examples:

Last Version on BranchNext Version
0.0.10.0.12
0.0.10.22.0
0.0.144.0.0

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.