////
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.
////
= Contributing

Contributions via GitHub pull requests are gladly accepted from their original author. By submitting any copyrighted
material via pull request, email, or other means you agree to license the material under the project's open source
license and warrant that you have the legal authority to do so.

[[ways-to-contribute]]
== Ways to Contribute

image:gremlin-apache.png[width=250,float=left] While the concept of an open source contribution can refer to doing
development work on the code base, there are many other ways outside of coding to contribute to Apache TinkerPop.
Participating on the various mailing lists, offering ideas, reporting bugs, writing documentation are all welcome
contributions to the project that help improve the TinkerPop. This section of the document is designed to help
provide some structure for potential contributors and to give them ideas for how they could get started becoming more
involved in the TinkerPop community.

NOTE: As a quick acknowledgment, this section was influenced by Apache Spark's well organized
link:https://cwiki.apache.org/confluence/display/SPARK/Contributing+to+Spark["Contributing to Spark"] document.

=== Mailing List Participation

TinkerPop has two mailing lists: link:https://groups.google.com/forum/#!forum/gremlin-users[gremlin-users] and
pass:[<a href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org">dev</a>]. Subscribing to and
participating on one or both of these mailing lists is a great way to contribute to TinkerPop. Helping users with their
problems by answering their questions on gremlin-users is a massive help to the community and an easy way for
the community to become familiar with the contributor.

The dev@tinkerpop.apache.org mailing list is where all design discussion, early feature announcements, release
discussions and other similar communication takes place. Having insight into the project at this level, will yield a
lot of information about the day-to-day course of TinkerPop and provides a way to help shape the direction of the
project.

=== Testing Releases

Proposed TinkerPop releases are not official until after they are evaluated by the community. The process of evaluation
occurs on the dev@tinkerpop.apache.org mailing list where the community is invited to review release artifacts and
vote if they should be released or not. Anyone is free to comment and provide a vote (+1/+0/-1) on a release. Note
that votes of non-PMC members are considered non-binding, but are certainly considered in the review process.

=== Reviewing Changes

Virtually all changes to TinkerPop's source code are performed via GitHub
link:https://github.com/apache/tinkerpop/pulls[pull requests]. When a pull request is issued it undergoes a
<<rtc,review process>> prior to being merged to a release branch. Anyone is free to comment and provide a vote
(+1/+0/-1) on a pull request. Note that votes of non-committers are considered non-binding, but are certainly
considered in the review process.

=== Writing Documentation

Proposing a documentation change is quite similar to providing a source code change, which is described below in more
detail. Note that there is a difference between project documentation and the
link:https://tinkerpop.apache.org/[TinkerPop web site]. The project documentation refers to the documentation that is
published per release like, tutorials, reference documentation, and other similar pages. This content is not updated
after release and remains static bound to that version. The TinkerPop web site refers to the static home page and its
related content, such as link:https://tinkerpop.apache.org/gremlin.html[Understanding Gremlin],
link:https://tinkerpop.apache.org/policy.html[Provider Listing and Graphic Usage Policies] and other similar pages.
This content is not bound to any particular version and can be published at any time where new content simply replaces
old content.

For both types of documentation, changes can be submitted via pull request. For project documentation, TinkerPop has
a robust documentation system that is based on link:http://asciidoc.org/[asciidoc]. The content can be found in the
link:https://github.com/apache/tinkerpop/tree/master/docs/src[docs/src]. Recall that this documentation is version
specific, so consider the appropriate branch on which to submit the pull request so that the documentation is reflective
of the version it is tied to. To view generated documentation locally, read more about environment configurations in
the <<documentation-environment,Documentation Environment>> section.

For web site changes, the process is largely the same except that the documentation system is HTML based instead of
Asciidoc. The content can be found in the source control tree at link:https://github.com/apache/tinkerpop/tree/master/docs/site[docs/site].
The web site is always published from the `master` branch as it is not bound to a version, so there is no need to
submit a pull request to any other branches besides that one. If the change to this documentation involves changing
provider listings in some way, first propose those changes on the dev@tinkerpop.apache.org mailing list and achieve
consensus (wait time is 72 hours as usual). At that point, pull requests or direct changes can be submitted.
Again, see the <<documentation-environment,Documentation Environment>> section for more information on how to generate
the site locally.

=== Reporting Bugs

Well formed bug reports (especially when accompanied by a pull request that fixes the problem) are welcome
contributions that ultimately help improve the quality of TinkerPop. Of course, a bug report is only as good as its
reproduction steps and the surrounding details of the issue. When a bug is encountered, it should be documented in
link:https://issues.apache.org/jira/browse/TINKERPOP[JIRA], where it will likely trigger some discussion and
ultimately a resolution.

=== TinkerPop Libraries

TinkerPop is more than just the core source code repository. It is a rich ecosystem of libraries developed by
link:https://tinkerpop.apache.org/providers.html[providers], who look to use or extend upon the TinkerPop interfaces.
TinkerPop is highly focused on its interfaces and a small set of reference implementations of those interfaces as part
of its core code base. As such, large and independent new functionality is often rejected from inclusion in TinkerPop
itself, however, it is very much encouraged that such a project stand on its own as separate repository. Projects like
this that meet the TinkerPop link:https://tinkerpop.apache.org/policy.html[listing policy] can be added to the
TinkerPop web site and promoted there. Please see the current listing of such libraries on the TinkerPop
link:https://tinkerpop.apache.org/#graph-systems[home page] to get an idea as to what kinds of libraries are available
from the community. When in doubt about whether a library might be a good fit for hosting and ongoing maintenance in
the TinkerPop project itself, please ask on the dev@tinkerpop.apache.org mailing list.

== Considering Code Changes

Code changes can take a fair bit of effort from both the contributor doing the work, as well as the people who
will be reviewing and testing that work. It is beneficial to all involved that some basic considerations be made by
the contributor to ensure the best use is made of everyone's time.

NOTE: For those who are trying to find a place to start to contribute, consider looking at unresolved issues that
have the "trivial" priority as these issues are specifically set aside as
link:https://issues.apache.org/jira/issues/?jql=project%20%3D%20TINKERPOP%20AND%20resolution%20%3D%20Unresolved%20AND%20priority%20%3D%20Trivial%20ORDER%20BY%20key%20DESC[low-hanging fruit]
for newcomers.

Before proceeding, contributors should evaluate if the proposed change is likely to be relevant, new and actionable:

* Is it clear that code must change? Proposing a JIRA issue and pull request is appropriate only when a clear problem
or change has been identified. When in doubt, email dev@tinkerpop.apache.org first about the possible change.
* Search the mailing list archives for related discussions. Often, the problem has been discussed before, with
a resolution that doesn't require a code change, or recording what kinds of changes will not be accepted as a
resolution.
* Search link:https://issues.apache.org/jira/browse/TINKERPOP[JIRA] for existing issues.
* Is the scope of the change matched to the contributor's level of experience? Anyone is qualified to suggest a typo
fix, but refactoring a core feature in serialization or OLAP requires much more understanding of TinkerPop. Some
changes require building up experience first.

Before considering how to contribute code, it is useful to understand how code is reviewed, and why changes may be
rejected. Simply put, changes that have many or large positives, and few negative effects or risks, are much more
likely to be merged, and merged quickly. Risky and less valuable changes are very unlikely to be merged, and may be
rejected outright rather than receive iterations of review.

*Positives*

* Change has already been discussed and is known to committers
* Fixes the root cause of a bug in existing functionality
* Adds functionality or fixes a problem needed by a large number of users
* Simple, targeted
* Easily tested; has tests
* Reduces complexity and lines of code

*Negatives, Risks*

* Band-aids a symptom of a bug only
* Introduces complex new functionality, especially an API that needs to be supported
* Adds complexity that only helps a niche use case
* Adds user-space functionality that does not need to be maintained in TinkerPop, but could be hosted externally and
promoted in link:https://tinkerpop.apache.org/#graph-systems[provider listings]
* Changes a public API or semantics thus introducing a breaking change
* Adds large dependencies
* Changes versions of existing dependencies
* Adds a large amount of code
* Makes lots of modifications in one "big bang" change

== Contributing Code Changes

Generally, TinkerPop uses link:https://issues.apache.org/jira/browse/TINKERPOP[JIRA] to track logical issues,
including bugs and improvements, and uses GitHub pull requests to manage the review and merge of specific code
changes. That is, JIRA issues are used to describe what should be fixed or changed, and high-level approaches, and pull
requests describe how to implement that change in the project's source code.

As a first step to making a contribution, consider *JIRA*:

. Find the existing JIRA ticket that the change pertains to.
.. Do not create a new ticket if creating a change to address an existing issue in JIRA; add to the existing
discussion and work instead.
.. Look for existing pull requests that are linked from the ticket, to understand if someone is already working on
the JIRA.
. If the change is new, then it usually needs a new ticket. However, trivial changes, where the change is virtually
the same as the how it should change do not require a JIRA (e.g. "Fix typos in Foo javadoc").
. If required, create a new ticket:
.. Provide a descriptive Title and a detailed Description. For bug reports, this should ideally include a short
reproduction of the problem.
.. Set required fields - these are detailed later in this document in the <<_issue_tracker_conventions, Issue Tracker
Conventions>> section.
. If the change is a large change, consider inviting discussion on the issue at dev@tinkerpop.apache.org first
before proceeding to implement the change.

Next, *make changes* and prepare a *pull request*:

. link:https://help.github.com/articles/fork-a-repo/[Fork and then clone] the Apache TinkerPop
link:https://github.com/apache/tinkerpop[GitHub repository] if not already done.
. Make changes in the fork
.. It is typically best to create a branch for the changes. Consider naming that branch after the JIRA issue number
to easily track what that branch is for.
.. Consider which release branch (e.g. `master`, `3.3-dev` - consult the
link:https://tinkerpop.apache.org/docs/x.y.z/dev/developer/#branches[Branches Section] for more information) to create
the development branch from in the first place. In other words, is the change to be targeted at a specific TinkerPop
version (e.g. a patch to an older version)? When in doubt, please ask on dev@tinkerpop.apache.org.
. Build the project and run tests.
.. A simple build can be accomplished with maven: `mvn clean install`.
.. Often, a "simple build" isn't sufficient and integration tests are required:
`mvn clean install -DskipIntegrationTests=false -DincludeNeo4j`. Note that Hadoop must be running for the integration
tests to execute.
.. Docker can help simplify building and testing: `docker/build.sh -t -i -n`
.. Please see the <<building-testing,Building and Testing>> section for more building and testing options.
. Consider whether documentation or tests need to be added or updated as part of the change, and add them as needed.
.. Nearly all changes should include a modification to the `CHANGELOG.asciidoc` file - one or more entries to
help summarize the change.
.. Some changes will require updates to the link:https://tinkerpop.apache.org/docs/x.y.z/upgrade/[Upgrade Documentation].
Updates to this documentation are usually reserved for major new features and breaking changes.
.. Docker can help simplify documentation generation: `docker/build.sh -d`
.. Please see the <<building-testing,Building and Testing>> section for more documentation generation options.
. Open the link:https://help.github.com/articles/using-pull-requests/[pull request] against the appropriate branch
on the Apache TinkerPop repository.
.. Target the pull request at the appropriate branch in TinkerPop's repository
.. Prefix the name of the pull request with the JIRA issue number (include a brief description after that).
.. Include a link to the ticket in JIRA in the pull request description.
.. Include a rough synopsis of how the changes were tested. This might be as simple as "Ran mvn clean install to
success and performed manual testing in the Gremlin Console".
.. Include other descriptive elements about the change if they are not already included in the JIRA ticket.
.. Automated builds will occur with Travis. Please be sure that the pull request passes those builds and
correct them if there are problems.

Once the pull request has been placed it will go into *review*:

. Other reviewers, including committers, may comment on the changes and suggest modifications. Changes can be added by
simply pushing more commits to the same branch.
. Lively, polite, rapid technical debate is encouraged from everyone in the community. The outcome may be a rejection
of the entire change.
. Reviewers can indicate that a change looks suitable for merging with by providing a "+1". Please see the
<<rtc, Review then Commit>> process for more details.
. Sometimes, other changes will be merged which conflict with your pull request's changes. The PR can't be merged
until the conflict is resolved. In these cases the PR must be rebased, conflicts resolved and the resulting changes
force pushed back to the branch.
. Try to be responsive to the discussion rather than let days pass between replies.
. Reviewers may request additional pull requests (e.g. one for each release branch that it may be related to) if
the changes brings extensive conflict between branches.

On successful review, the *pull request will be merged* to the main repository and the JIRA issue will be closed.

== Versioning

TinkerPop version numbers follow a format of `MAJOR.MINOR.PATCH`, where:

* `MAJOR` version is incremented for epochs of thinking around TinkerPop and its relation to the graph ecosystem.
* `MINOR` version is incremented when incompatible changes cannot be avoided.
* `PATCH` version is incremented when changes are backward compatible.

The number for `MAJOR` rarely changes and when it does, it typically represents a complete re-write of the software
and thus massive changes can be expected. As a result of the definition for `MAJOR`, we tend to focus on the other
two numbers when considering where changes will land.

The driving question for determining if a change is suitable for `MINOR` or `PATCH` versions is whether or not the
change introduces some form of incompatibility. As the focus for making the determination is "breaking change", we
therefore allow the option for new features to land in `PATCH` versions. Taking this approach, lengthens the life span
of `MINOR` versions considerably which is helpful to graph providers looking for stable long-lived support for a
particular release line.

With all of the above rules in mind, there are some subtle considerations that have come into play in the past when
trying to determine where a change should land:

* A `PATCH` has been known to take a breaking change if that breaking change:
** Is necessary to fix a critical bug
** Has a limited breaking scope (e.g. a utility class that no one would likely use, a break that affects graph
providers only)
* It is preferred that "major" new features go to `MINOR`, but it is sometimes the case that they will make their way
to `PATCH` if that change provides significant enough value.
* As `PATCH` release numbers get higher, there is less incentive to push new features there as there is likely new
focus on the next unreleased `MINOR`.
* The preference is to find deprecation paths whenever possible.

In short, the dev mailing list is open to discussion on where a change will land. The discussion just needs to have
good reasoning and use the general principles above as a framework for coming to a consensus.
