# Contributing to mink-idl-compiler

Hi there!
We’re thrilled that you’d like to contribute to this project.
Your help is essential for keeping this project great and for making it better.

## Branching Strategy

In general, contributors should develop on branches based off of `main` and pull requests should be made against `main`.

## Submitting a pull request

1. Please read our [code of conduct](CODE-OF-CONDUCT.md) and [license](LICENSE.txt).
1. [Fork](https://github.com/qualcomm/mink-idl-compiler/fork) and clone the repository.

    ```bash
    git clone https://github.com/<username>/mink-idl-compiler.git
    ```

1. Create a new branch based on `main`:

    ```bash
    git checkout -b <my-branch-name> main
    ```

1. Create an upstream `remote` to make it easier to keep your branches up-to-date:

    ```bash
    git remote add upstream https://github.com/qualcomm/mink-idl-compiler.git
    ```

1. Make your changes, add tests, and make sure the tests still pass.
1. Commit your changes using the [DCO](https://developercertificate.org/). You can attest to the DCO by commiting with the **-s** or **--signoff** options or manually adding the "Signed-off-by":

    ```bash
    git commit -s -m "Really useful commit message"`
    ```

1. After committing your changes on the topic branch, sync it with the upstream branch:

    ```bash
    git pull --rebase upstream main
    ```

1. Push to your fork.

    ```bash
    git push -u origin <my-branch-name>
    ```

    The `-u` is shorthand for `--set-upstream`. This will set up the tracking reference so subsequent runs of `git push` or `git pull` can omit the remote and branch.

1. [Submit a pull request](https://github.com/qualcomm/mink-idl-compiler/pulls) from your branch to `main`.
1. Pat yourself on the back and wait for your pull request to be reviewed.

## Security Analysis of Pull Requests

To maintain the security and integrity of this project, all pull requests from external contributors are automatically scanned using [Semgrep](https://github.com/semgrep/semgrep) to detect insecure coding patterns and potential security flaws.

**Static Analysis with Semgrep:**  We use Semgrep to perform lightweight, fast static analysis on every PR. This helps identify risky code patterns and logic flaws early in the development process.

**Contributor Responsibility:** If any issues are flagged, contributors are expected to resolve them before the PR can be merged.

**Continuous Improvement:** Our Semgrep ruleset evolves over time to reflect best practices and emerging security concerns.

By submitting a PR, you agree to participate in this process and help us keep the project secure for everyone.


Here are a few things you can do that will increase the likelihood of your pull request to be accepted:

- Follow the existing style where possible. **INSERT LINK TO STYLE, e.g. PEP8 for python**
- Write tests.
- Keep your change as focused as possible.
  If you want to make multiple independent changes, please consider submitting them as separate pull requests.
- Write a [good commit message](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
- It's a good idea to arrange a discussion with other developers to ensure there is consensus on large features, architecture changes, and other core code changes. PR reviews will go much faster when there are no surprises.

## Pre-PR Checklist

When making changes, be sure to use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). That is, prefix your
commit messages with `feat:`, `fix:`, `deps:`, etc. Since we use squash commits for PRs, this is only relevant for the squash commmit itself but it is still helpful to follow this for the PR branch commits.

For each PR branch, ensure that the source code
1. is formatted with `cargo fmt`
2. has no warnings from `cargo clippy --all-targets -- -D clippy::all -D unused -D warnings`
3. has properly formatted documentation

Run these before opening a pull request:

```sh
cargo fmt -- --check
cargo clippy --all-targets -- -D clippy::all -D unused -D warnings
cargo test
cd tests && cargo test && cargo test --release
```

## Troubleshooting

`idlc` not found in integration tests:
- Ensure `cargo build` has completed.
- Set `IDLC=../target/debug/idlc` before running `tests` crate commands.

Rust/Java output path errors:
- Rust and Java generation require `-o` to point to a directory.

C/C++ integration failures:
- Confirm `clang` and `clang++` are installed and available on `PATH`.

# Releases
The release process strives to ensure that each release contains the following:
1. A succinctly-worded release body
2. A git tag with a matching version
3. A copy of the pre-compiled `idlc` that was generated by the Github CI

The release process involves some automation and the following steps should be carefully followed to
ensure uniformity among the releases.

Due to the structure of this repo and Qualcomm's Github CI policies, some obvious approaches to automating releases are
not possible. The current approach uses a mix of semi-manual updates with [cargo-workspaces](https://github.com/pksunkara/cargo-workspaces) and automated releases with [release-please](https://github.com/marketplace/actions/release-please-action).

## Release-prep model

*Version Policy*
- PRs:
    - modify code only
    - **never touch versions** (including Cargo.lock)
- Versions are bumped only during release preparation
- `cargo ws changed` determines affected crates
- Patch/minor/major is chosen intentionally
- Version bumps are committed as a single release commit

*Release Procedure*
- A release PR will be created and updated by `release-please`
  - CHANGELOG.md and release message body automatically updated, based on
  - Updates the `release-please` manifest
- After 1 or more version bumps, a release PR can be merged
- `release-please` rebuilds the target binaries and uploads them to the release itself.

*Benefits*
1. Squash merges freely
2. `main` stays clean and stable
3. No version churn, no Cargo.lock noise

## Example
Here is an example of the typical development flow:
1. Merge 1 or more feature/patch/bug fix PRs (no version changes)
2. Prepare for release
   1. ```sh
       cargo install cargo-workspaces
       cargo ws changed
       cargo ws version --no-git-push --no-git-tag -m "chore(release): bump crate versions"
       ```
        1. This analyzes the workspace, bumps the Cargo.toml (AND Cargo.lock) versions based **solely** on if any changes occur within the crate, and commits the changes.
        2. `cargo ws` will prompt for each crate to specify which type of release (major, minor, or patch) is appropriate.
        3. **The release type is determined by the user**
   2. Review the commit
   3. Push to `origin/main` - either directly or through PR.
3. `release-please` captures all conventional commits through PRs and "bump" commit
4. Review `release-please` release PR to make sure everything is captured correctly
5. Merge release PR and `release-please` takes care of the rest
