Skip to content

Latest commit

 

History

History
285 lines (193 loc) · 11.2 KB

CONTRIBUTING.md

File metadata and controls

285 lines (193 loc) · 11.2 KB

Join Us

Arrow is an inclusive community powered by awesome individuals like you. As an actively growing ecosystem, Arrow and its associated libraries and toolsets are in need of new contributors! We have issues suited for all levels, from entry to advanced, and our maintainers are happy to provide 1:1 mentoring. All are welcome in Arrow.

If you’re looking to contribute, have questions, or want to keep up-to-date about what’s happening, please follow us here and say hello!

How-tos

In this page you'll find these guidelines for contributions:

Can't find what you're looking for? Please, contact us at #arrow on Kotlin Slack or create an issue.

How to build the libraries

Requirements

  • JDK 8

Building the whole project

To build all the libraries (compilation + tests) and examples run in the project root (arrow directory):

./gradlew build

Building a single library

To build just CORE library, FX library, OPTICS library etc.:

  1. Find the Gradle subproject name by running
./gradlew projects

E.g. for the CORE subproject you will get

Root project 'arrow'
...
+--- Project ':arrow-core'
  1. Append :build after the subproject name and run this task. See also Gradle documentation how to run subproject tasks.
./gradlew :arrow-core:build

How to generate and validate the documentation

Dokka is responsible for generating documentation based on source code annotations. Knit is in charge of compiling and validating your doc snippets and deploying the proper binaries for those.

The build task runs knitCheck to check if all Knit annotated code snippets in KDoc comments have been generated as examples. Knit code snippet annotations look like HTML comments inside KDoc:

/**
 * ```kotlin
 * // Code example goes here
 * ```
 * <!--- KNIT example-arrow-core-01.kt -->
 */

If you added/changed any Knit annotated code snippets in the docs you have to run the knit task to (re-)generate the examples, otherwise your build will fail:

./gradlew knit

In order to generate the documentation and validate it:

./gradlew buildDoc

Doc snippets policies

Whenever you are documenting a new type (type class, data type, whatever) you'll wonder how to add code snippets to it. Please, use the following priority check list:

1. Snippets for public API docs

If the snippet is just docs for a public method of a type (as in arguments, return type, or how it should be used from call sites), that should be inlined in the Kdocs of that given method using Dokka and annotated with Knit (see above for more details). That's done under the actual type file. Here you have a simple example for Option type.

That will automatically inline the docs of each method into the docs of the given data type. This is intended to be used just for public APIs exposed to users of the library.

All public classes, functions, and properties must include public docs in Arrow before merging into main.

Public docs in Arrow follow a particular structure that ensures users have a similar experience when browsing the arrow website and documentation.

Declarations including classes, functions, and others must include docs in the following structure:

All Kdocs should include a short header that describes what the data type or function is for and a triple backticks ``` fenced block demonstrating its use (ending with an appropriate Knit annotation)

for example

/**
 * (...)
 * 
 * `Option<A>` is a container for an optional value of type `A`. If the value of type `A` is present, the `Option<A>` is an instance of `Some<A>`, containing the present value of type `A`. If the value is absent, the `Option<A>` is the object `None`.
 *
 * ```kotlin
 * import arrow.core.Option
 * import arrow.core.Some
 * import arrow.core.none
 *
 * //sampleStart
 * val someValue: Option<String> = Some("I am wrapped in something")
 * val emptyValue: Option<String> = none()
 * //sampleEnd
 * fun main() {
 *  println("value = $someValue")
 *  println("emptyValue = $emptyValue")
 * }
 *
 * <!--- KNIT example-option-01.kt -->
 *  
 * (...)
 */ 
public sealed class Option<out A> {
  
}

2. Snippets for broader samples

If your snippet is showing examples on how to use the public APIs in a broader scenario (like describing FP patterns or similar), then you'll add those snippets to the described docs Markdown file.

How to propose an improvement

If it's the first time you contribute with a GitHub repository, take a look at Collaborating with issues and pull requests.

How to create an issue

Please, follow the link to create an issue.

How to create a pull request

The easiest way to contribute to Arrow is to create a branch from a fork, and then create a PR on GitHub from your branch.

Arrow is a large project that uses several tools to verify that the code is formatted consistently, and that we don't break downstream projects that rely on Arrow's API across versions.

For code formatting we use Spotless with KtFmt and for API binary compatibility we use Binary Compatibility Validator. They need to run before you commit and push your code to GitHub.

If you've included those changes for binary compatibility and formatted the code correctly it's time to open your PR and get your contribution into Arrow. Thanks ahead of time for your effort and contributions 🙏

Requirements to change an existing feature

If you want to propose a fix, rename, move etc., please execute these required tasks and make sure they pass:

  • If you changed/added Knit annotated code snippets in KDocs:
./gradlew knit # (Re-)generate code examples from snippets in docs
  • Required tasks:
./gradlew spotlessApply # Format code
./gradlew build
./gradlew buildDoc

Note: if, when running build, you see the following error:

> Task :arrow-core:apiCheck FAILED

This means you have changed (inadvertently or not) some public API. In this case read in the next point below how to resolve this.

  • The approval by 2 maintainers of the Arrow Community.

Requirements to add a new feature

Please, ensure these points when adding a new feature:

  • Include documentation via Dokka. Please, find examples in the existing code to follow the same pattern.
  • Include tests that cover the proper cases

When creating the pull request, please execute these required tasks and make sure they pass:

  • If you changed/added Knit annotated code snippets in KDocs:
./gradlew knit # (Re-)generate code examples from snippets in docs
  • Required tasks:
./gradlew spotlessApply # Format code
./gradlew build
./gradlew buildDoc

Note: as part of the build task apiCheck is run. If you have added/changed any public APIs, this task will fail with a message like this one:

> Task :arrow-core:apiCheck FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':arrow-core:apiCheck'.
> API check failed for project arrow-core.
  --- /Users/john/projects/arrow/arrow-libs/core/arrow-core/api/arrow-core-retrofit.api
  +++ /Users/john/projects/arrow/arrow-libs/core/arrow-core/build/api/arrow-core-retrofit.api

To make the check pass you need to run:

./gradlew apiDump

This will generate updated .api files which you can then manually review (if the API changes are the ones you intended) and commit and push for the Arrow maintainers to review as well.

  • The approval by 2 maintainers of the Arrow Community is required as well.

How to download the tests report

Both successful or failed build checks allow to download the tests report to review it:

how-to-download-tests-report

What happens when merging a pull request

When merging the pull request, a new SNAPSHOT library will be published into Sonatype OSS.

On the other hand, the documentation for the next version (SNAPSHOT) will be updated:

If any of these actions fails, an issue will be created to be solved as soon as possible.

Notes

How to upgrade Gradle

The use of Gradle appears in several subprojects: arrow-core, arrow-stack, etc.

However, links are being used, so it's just necessary to upgrade Gradle in the project root directory:

./gradlew wrapper --gradle-version <new-version>

How to add a new module

This short guideline provides all the things to keep in mind when adding a new module:

  • Configuration:
    • Add <module>/gradle.properties
    • Add <module>/build.gradle.kts
    • Update settings.gradle.kts
  • Utilities:

Gradle dependency configurations

Configuration Use Note
api compilation exported to consumers for compilation
implementation compilation + runtime exported to consumers for runtime
compileOnly just compilation not exported to consumers
runtimeOnly just runtime exported to consumers for runtime
testImplementation test compilation + test runtime
testCompileOnly test compilation
testRuntimeOnly test runtime