= Contributing

Anyone is welcome to open issues and/or pull-requests for bugfixes, feature-requests and/or ideas.

== Just

If you have https://github.com/casey/just[just] installed you can run `just` to see and choose from the available commands.

If `just` fails with error about `fzf` missing you can use `just --list` to manually see the commands.

== How to build

=== Prerequisite

Java 11 must be installed for the build

=== Quickstart

Clone the repository, cd `jbang` and run `./gradlew build`.
There will be a warning in the output but don't despair - that is just
Java being picky.

[source, bash]
----
$ git clone https://github.com/jbangdev/jbang
$ cd jbang
$ ./gradlew build
> Task :test
WARNING: An illegal reflective access operation has occurred # <.>
WARNING: Illegal reflective access by org.junit.contrib.java.lang.system.EnvironmentVariables (file:/Users/max/.gradle/caches/modules-2/files-2.1/com.github.stefanbirkner/system-rules/1.17.2/ff31c2f41e8d0eb7063c3a3c207b11acea6fdf7b/system-rules-1.17.2.jar) to field java.util.Collections$UnmodifiableMap.m
WARNING: Please consider reporting this to the maintainers of org.junit.contrib.java.lang.system.EnvironmentVariables # <.>
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 5s
19 actionable tasks: 14 executed, 5 up-to-date
----
<.> This error happens as in the junit tests we test behaviors under different environment variables and to do that we need to modify internal state in java's `System` handling of properties. Java 9+ does not like that.
<.> Already https://github.com/stefanbirkner/system-rules/issues/64[reported] but it can't be fixed as the jvm does not allow this; but fine for `jbang` as this is just for the test runs.

=== Changing the Java version

The build uses the `testJavaVersion` and `testJavaVendor` properties to set the Java version for the test runs.

To change the Java version for the test runs, set the `testJavaVersion` and `testJavaVendor` properties in the `build.gradle` file.

For example, to run the tests with Java 17 use:

```
./gradlew test -PtestJavaVersion=17
```

and if want a different vendor, use:

```
./gradlew test -PtestJavaVersion=17 -PtestJavaVendor=zulu
```

=== Building on Windows specifics

The guidelines above should work for Windows, and this configuration is covered by the CI pipeline.
Some tests may be skipped in your local environment if symbolic linking is not enabled for your filesystem
OR if your test process does not have the required permissions for a directory.
See the configuration guidelines in the link:readme.adoc#usage-on-windows[Usage on Windows] section.

== Conventional Commits + squash and merge

To make releasing as automated and fast as possible we (since 2020-09-13) use https://www.conventionalcommits.org. On Pull-request we have https://github.com/zeke/semantic-pull-requests running to sanitize that at least PR title or one commit uses the conventional commit format.

Intent is that on merge we squash to get as clean as changelog as possible.

== Source formatting

The build uses the https://github.com/diffplug/spotless[spotless] plugin to ensure Java and other files are formatted uniformly.
If your build fails due to formatting errors then run `gradle spotlessApply` and it will reformat to be compatible.

If you are running on a bash capable system the following pre-commit hook from https://github.com/diffplug/spotless/issues/178#issuecomment-735284262[spotless issues] is useful to help remember applying correct formatting
before `git push`:

[source,shell]
----
curl -o .git/hooks/pre-commit https://gist.githubusercontent.com/toefel18/23c8927e28b7e7cf600cb5cdd4d980e1/raw/8636aa5dab09e1f34ba9b6b6544131f96a0112c0/pre-commit && chmod +x ./.git/hooks/pre-commit
----


== Versioning

`jbang` uses semi-automatic versioning via the https://github.com/toolebox-io/gradle-git-versioner[git-versioner] plugin.
This plugin uses the git log to derive what version number are the current one by looking for `[major]`, `[minor]` and `[patch]` in commit messages.

This means there is no place in code or meta-data we need to manually maintain version info.

You can see the current version by running `./gradlew printVersion` - if you have 3 commits since last bump at `0.10.1` you would get a version number like `0.10.1.3`.

For pull-requests don't try and trigger bump of a version; we'll apply that once it is time for a release.

NOTE: The `dev.jbang.VersionProvider` class will show a compile error in IDE's but ignore that, the `BUILDCONFIG` class gets generated during the Gradle build.

== How releases are made

Run a build check to see if things are clean:

[source,shell]
----
$ gradle spotlessApply build clean
----

if nothing changed (use `git status`) then run:

[source,shell]
----
$ gradle printVersion
----

to see if the right version are printed.
If should have only 3 digits, i.e. `v0.45.1`, not `v0.45.1.23`.

If 4 digits then make sure last commit as a `[minor]` or `[patch]` as part of its text.

Once ready run:

`$ gradle changelog`

This will generate `CHANGELOG.md` using commitizen conventions.

Edit the changelog with some header on what changed in an overview form.

Then run:

`$ gradle tag`

This will create an annotated tag using the `CHANGELOG.md` message.

If all is good, run `$ gradle push --tags`.

This will trigger github action flow which will prepare a github release.

When all is good - go to https://github.com/jbangdev/jbang/releases and check all is good;
do final (cosmetic) edits on the release message and save.

When saved, a github action workflow will get triggered. That workflow will push update the distribution mechanism for chocolatey, brew, container, scoop, sdkman etc.


