= Spring Functions Catalog Contributor Guidelines

Have something you'd like to contribute to **Spring Functions Catalog**?
We welcome pull requests, but ask that you carefully read this document first to understand how best to submit them; what kind of changes are likely to be accepted; and what to expect from the Spring team when evaluating your submission.

Please refer back to this document as a checklist before issuing any pull request; this will save time for everyone!

== Code of Conduct

Please see our https://github.com/spring-projects/.github/blob/main/CODE_OF_CONDUCT.md[code of conduct]

== Reporting Security Vulnerabilities

Please see our https://github.com/spring-cloud/spring-functions-catalog/security/policy[Security policy].

== Understand the basics

Not sure what a *pull request* is, or how to submit one?
Take a look at GitHub's excellent documentation: https://help.github.com/articles/using-pull-requests/[Using Pull Requests] first.

== Search GitHub issues first; create one if necessary

Is there already an issue that addresses your concern?
Search the https://github.com/spring-cloud/spring-functions-catalog/issues[GitHub issue tracker] to see if you can find something similar.
If not, please create a new issue in GitHub before submitting a pull request unless the change is truly trivial, e.g. typo fixes, removing compiler warnings, etc.

== Sign the contributor license agreement

If you have not previously done so, please fill out and submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement (CLA)].

Very important, before we can accept any *Spring Functions Catalog contributions*, we will need you to sign the CLA.
Signing the CLA does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do.

== Fork the Repository

1. Go to https://github.com/spring-cloud/spring-functions-catalog
2. Hit the "fork" button and choose your own GitHub account as the target
3. For more detail see https://help.github.com/fork-a-repo/[Fork A Repo].

== Setup your Local Development Environment

1. `git clone --recursive git@github.com:<your-github-username>/spring-functions-catalog.git`
2. `cd spring-functions-catalog`
3. `git remote show`
_you should see only 'origin' - which is the fork you created for your own GitHub account_
4. `git remote add upstream git@github.com:spring-cloud/spring-functions-catalog.git`
5. `git remote show`
_you should now see 'upstream' in addition to 'origin' where 'upstream' is the Spring repository from which releases are built_
6. `git fetch --all`
7. `git branch -a`
_you should see branches on origin as well as upstream, including 'main'_

== Build from Source

The build system for the project is https://gradle.org/[Gradle].
It is recommended to rely on the `wrapper` provided in the project code based and use a `gradlew` script from command line for the target operating system.
The current Gradle version in use you can obtain from the `/gradle/gradle-wrapper.properties` file in the source tree.
It is also recommended to use a Gradle import feature of your IDE for the best contribution experience.

The minimum JDK version at the moment is `17`.
You always can find the currently required Java version in the `build.gradle`.
For example, for the current project version:

----
compileJava {
    options.release = 17
}

compileTestJava {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
    options.encoding = 'UTF-8'
}
----

To build and install jars into your local Maven cache:

----
./gradlew build publishToMavenLocal
----

To build api Javadoc (results will be in `build/api`):

----
./gradlew api
----

To build the reference documentation (results will be in `build/site`):

You can build and test only a specific module if your contribution is only over there:

----
./gradlew :spring-http-supplier:check
----

== A Day in the Life of a Contributor

* _Always_ work on topic branches (Typically use the GitHub issue ID as the branch name).
  - For example, to create and switch to a new branch for issue 123: `git checkout -b GH-123`
* You might be working on several different topic branches at any given time, but when at a stopping point for one of those branches, commit (a local operation).
* Please follow the "Commit Guidelines" described in https://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project[this chapter of Pro Git].
* Then to begin working on another issue (say 101): `git checkout GH-101`.
 The _-b_ flag is not needed if that branch already exists in your local repository.
* When ready to resolve an issue or to collaborate with others, you can push your branch to origin (your fork), e.g.: `git push origin GH-123`
* If you want to collaborate with another contributor, have them fork your repository (add it as a remote) and `git fetch <your-username>` to grab your branch.
Alternatively, they can use `git fetch --all` to sync their local state with all of their remotes.
* If you grant that collaborator push access to your repository, they can even apply their changes to your branch.
* When ready for your contribution to be reviewed for potential inclusion in the main branch of the canonical `spring-functions-catalog` repository (what you know as 'upstream'), issue a pull request to the SpringSource repository (for more detail, see https://help.github.com/articles/using-pull-requests/[Using pull requests]).
* The project lead may merge your changes into the upstream main branch as-is, he may keep the pull request open yet add a comment about something that should be modified, or he might reject the pull request by closing it.
* A prerequisite for any pull request is that it will be cleanly merge-able with the upstream main's current state.
**This is the responsibility of any contributor.**
If your pull request cannot be applied cleanly, the project lead will most likely add a comment requesting that you make it merge-able.
For a full explanation, see https://git-scm.com/book/en/Git-Branching-Rebasing[the Pro Git section on rebasing].
As stated there: _"> Often, you’ll do this to make sure your commits apply cleanly on a remote branch — perhaps in a project to which you’re trying to contribute but that you don’t maintain."_

== Keeping your Local Code in Sync

* As mentioned above, you should always work on topic branches (since 'main' is a moving target). 
However, you do want to always keep your own 'origin' main branch in synch with the 'upstream' main.
* Within your local working directory, you can sync up all remotes' branches with: `git fetch --all`
* While on your own local main branch: `git pull upstream main` (which is the equivalent of fetching upstream/main and merging that into the branch you are in currently)
* Now that you're in synch, switch to the topic branch where you plan to work, e.g.: `git checkout -b GH-123`
* When you get to a stopping point: `git commit`
* If changes have occurred on the upstream/main while you were working you can sync again:
    - Switch back to main: `git checkout main`
    - Then: `git pull upstream main`
    - Switch back to the topic branch: `git checkout GH-123` (no -b needed since the branch already exists)
    - Rebase the topic branch to minimize the distance between it and your recently synced main branch: `git rebase main`
(Again, for more detail see https://git-scm.com/book/en/Git-Branching-Rebasing[the Pro Git section on rebasing]).
* **Note** While it is generally recommended to __not__ re-write history by using `push --force`, and we do not do this on `main` (and release) branches in the main repo, we require topic branches for pull requests to be rebased before merging, in order to maintain a clean timeline and avoid "merge" commits.
* If, while rebasing for the merge, we find significant conflicts, we may ask you to rebase and `push --force` to your topic branch after resolving the conflicts.
* Assuming your pull request is merged into the 'upstream' main, you will end up pulling that change into your own main eventually and, at that time, you may decide to delete the topic branch from your local repository and your fork (origin) if you pushed it there.
    - to delete the local branch: `git branch -d GH-123`
    - to delete the branch from your origin: `git push origin :GH-123`

== Maintain a linear commit history

When merging to main, the project __always__ uses fast-forward merges.
As discussed above, when issuing pull requests, please ensure that your commit history is linear.
From the command line you can check this using:

----
git log --graph --pretty=oneline
----

As this may cause lots of typing, we recommend creating a global alias, e.g. `git logg` for this:

----
git config --global alias.logg 'log --graph --pretty=oneline'
----

This command, will provide the following output, which in this case shows a nice linear history:

----
* c129a02e6c752b49bacd4a445092a44f66c2a1e9 GH-2721 Increase Timers on JDBC Delayer Tests
* 14e556ce23d49229c420632cef608630b1d82e7d GH-2620 Fix Debug Log
* 6140aa7b2cfb6ae309c55a157e94b44e5d0bea4f GH-3037 Fix JDBC MS Discard After Completion
* 077f2b24ea871a3937c513e08241d1c6cb9c9179 Update Spring Social Twitter to 1.0.5
* 6d4f2b46d859c903881a561c35aa28df68f8faf3 GH-3053 Allow task-executor on <reply-listener/>
* 56f9581b85a8a40bbcf2461ffc0753212669a68d Update Spring Social Twitter version to 1.0.4
----

If you see intersecting lines, that usually means that you forgot to rebase you branch.
As mentioned earlier, **please rebase against main** before issuing a pull request.

== Follow the Code Style

The project uses https://github.com/spring-io/spring-javaformat[Spring Java Format].
Make sure you have installed respective plugin for your IDE to follow code style enforced by the Spring Java Format.
Sometimes it might not be enough to follow IDE auto-formatting and when you run Gradle `check` task, it will complain that code format is broken.
Then just run `./gradlew format` and respective Spring Java Format Gradle plugin will do that for you.

If code does not follow respective style, the `check` task will report Checkstyle violations.
Consider to follow its recommendations to avoid unnecessary requests from pull request reviewers.

== Use `@since` tags

Use `@since` tags for newly-added public API types and methods e.g.

[source java]
----
/**
 * ...
 *
 * @author First Last
 *
 * @since 3.0
 *
 * @see ...
 */
----

== Use `@author` tags

Use `@author` tag with your real name, when you change any class e.g.

[source java]
----
/**
 * ...
 *
 * @author First Last
 */
----


== Submit JUnit test cases for all behavior changes

Search the codebase to find related unit tests and add additional `@Test` methods within.
It is also acceptable to submit test cases on a per GH issue basis.

== Squash commits

Use `git rebase --interactive`, `git add --patch` and other tools to "squash" multiple commits into atomic changes.
In addition to the man pages for git, there are many resources online to help you understand how these tools work.
However, we do recommend to do this only for the first commit in the PR.
All the subsequent commits added after review should preserve the history for better context of the previous and current changes.

== Use your real name in git commits

Please configure git to use your real first and last name for any commits you intend to submit as pull requests.
For example, this is not acceptable:

    Author: Nickname <user@mail.com>

Rather, please include your first and last name, properly capitalized, as submitted against the SpringIO contributor license agreement:

    Author: First Last <user@mail.com>

This helps ensure traceability against the CLA, and also goes a long way to ensuring useful output from tools like `git shortlog` and others.

You can configure this globally via the account admin area GitHub (useful for fork-and-edit cases); globally with

    git config --global user.name "First Last"
    git config --global user.email user@mail.com

or locally for the *spring-functions-catalog* repository only by omitting the '--global' flag:

    cd spring-functions-catalog
    git config user.name "First Last"
    git config user.email user@mail.com

== Run all tests prior to submission

`./graldew clean check`.
Make sure that all tests pass prior to submitting your pull request.

== Provide a Link to the GitHub issue in the Associated Pull Request

Add a GitHub issue link to your first commit comment of the pull request on the last line, so your commit message may look like this:

----
    GH-1: Initial commit

    Fixes: gh-1

    * Start the project with respective infrastructure
----

NOTE:: The link to the issue must follow requirements of the https://github.com/spring-io/backport-bot[Backport Bot] used in the project for automatic back-port issues creation.

Please, follow Chris Beams' recommendations in regard to the good commit message: https://chris.beams.io/posts/git-commit[How to Write a Git Commit Message].
