# Contributing

## Get Source Code

Clone the repo from github:
```
$ git clone git@github.com:kotfu/dye-my-shell.git
```


## Install Tools and Dependencies

This project uses [uv](https://github.com/astral-sh/uv)

```bash
$ uv python 3.14
$ uv venv
$ uv pip install -e .[dev]
```


## Branches, Tags, and Versions

This project uses a simplified version of the
[git flow branching strategy](http://nvie.com/posts/a-successful-git-branching-model/).
We don't use release branches, and we generally don't do hotfixes, so we don't have
any of those branches either. The `main` branch always contains the latest release of
the code uploaded to PyPI, with a tag for the version number of that release.

The `develop` branch is where all the action occurs. Feature branches are welcome.
When it's time for a release, we merge `develop` into `main`.

This project uses [semantic versioning](https://semver.org/).


## Invoking Common Development Tasks

This project uses many other python modules for various development tasks, including
testing, rendering documentation, and building and distributing releases. These
modules can be configured many different ways, which can make it difficult to learn
the specific incantations required for each project you are familiar with.

This project uses [invoke](http://www.pyinvoke.org) to provide a clean, high level
interface for these development tasks. To see the full list of functions available:
```
$ invoke -l
```

You can run multiple tasks in a single invocation, for example:
```
$ invoke clean build
```

That one command will remove all superflous cache, testing, and build files, then
build a source distribution and a wheel distribution.

To make it easy to check everything before you commit, you can just type:
```
$ invoke check
...
$ echo $?
0
```

and it will test, lint, and check the format of all the code. If this doesn't complete
everything successfully then you still need to fix some stuff before you commit or
submit a pull request. In this context, complete everything successfully means: all
tests pass, lint returns a perfect score, etc.

To see what is actually getting executed by `invoke`, check the `tasks.py` file.


## Testing

Unit testing provides reliability and consistency in released software. This project
has 100% unit test coverage. Pull requests which reduce test coverage will not
be merged.

Run the tests in your current python environment, use pytest:
```
$ pytest
```


## Code Quality

Use `ruff` to check code quality. The pylint config is in `pyproject.toml`
can be used for both the tests and package:
```
$ ruff check *.py src/dye tests
```


## Code Formatting

Use [ruff](https://docs.astral.sh/ruff/) to format your code.
We use the default configuration, including a line length of 88 characters.

To format all the code in the project using `ruff`, do:
```
$ ruff format *.py tests src
```

You can check whether `ruff` would make any changes to the source code by:
```
$ ruff format --check *.py tests src
```

`ruff` integrates with many common editors and IDE's, that's the easiest way to ensure
that your code is always formatted.

Please format the code in your PR using `ruff` before submitting it.


## Punctuation and Capitalization for Users

Usage messages for individual commands are in all lower case letters with no periods.
If the help for a particular option contains multiple phrases, separate them with
a semi-colon. This matches the style of `argparse.ArgumentParser`. For example the
message generated for the `-h` option is an uncapitalized phrase with no period.
`ArgumentParser` epilogs should be sentences with capitalized first letters.

Error messages are in all lower case letters with no periods. This matches the style
of the errors generated by `argparse.ArgumentParser`.


## Make a Release

To make a release and deploy it to [PyPI](https://pypi.python.org/pypi), do the
following:

1. Merge everything to be included in the release into the **develop** branch.

2. Run `pytest` to make sure the tests pass in all the supported python versions.

3. Review and update `CHANGELOG.md`, change the **Unreleased** section name to
   the new release number and add today's date.

4. Push the **develop** branch to github.

5. Update and close the milestone corresponding to the release at
   [https://github.com/kotfu/shell-themer/milestones](https://github.com/kotfu/shell-themer/milestones)

6. Create a pull request on github to merge the **develop** branch into
   **main**. Wait for the checks to pass. Do not merge the pull request
   from the GitHub UI.

7. In your local repo, merge develop into main.

8. If you don't have the same commit at HEAD of main and develop, then in your
   local repo, merge main into develop. You should now have the same commit at
   the HEAD of main and develop

9. Tag the head commit on main with the new release number

10. Push main and develop to GitHub. This will automatically mark the pull request
    as Merged

11. Create a new release on Github with the existing tag you have pushed. Publish the release.

12. Switch to the **main** branch in your local repo.

13. Build distribution and upload it to test.pypi.org.
    This project uses uv-publish, so your credentials will be retrieved from ~/.pypirc
```
$ invoke pypi-test
```

14.  Build distribution and upload it to pypi:
    This project uses uv-publish, so your credentials will be retrieved from ~/.pypirc

```
$ invoke pypi
```

1.  Switch back to the **develop** branch.

2.  Add an **Unreleased** section to the top of `CHANGELOG.md`. Push the
    change to github.

3.  Run `$ uv pip install -e .[dev]` to ensure your venv gets an updated
    development version string
