# Contributing

All contributors should become familiar with this guide. It outlines the expectations
and practices for participating in the project.

## Review the project expectations

Before you start working on the project, there are three documents for you to digest.

### Ubuntu Code of Conduct

Projects governed by Canonical expect good conduct and excellence from every member. The
specific principles are laid out in the [Ubuntu Code of
Conduct](https://ubuntu.com/community/ethos/code-of-conduct).

### Canonical Contributor License Agreement

As a contributor, you retain your copyright and attribution rights, provided you sign
the [Canonical Contributor Licence Agreement](http://www.ubuntu.com/legal/contributors).
Before committing any code, review its terms. If you agree and sign it, your code can be
incorporated into the repository.

### Open source license

This project is licensed under [GPL-3.0](LICENSE).

## Report an issue or open a request

If you find a bug or feature gap in the project, look for it in the [project's GitHub
issues](https://github.com/canonical/youtube-links/issues) first. If you have
fresh input, add your voice to the issue.

If the bug or feature doesn't have an issue, we invite you to [open
one](https://github.com/canonical/youtube-links/issues/new/choose).

## Set up for development

This project uses a forking, feature-based workflow. Most work occurs on people's local
systems and is heavily terminal-dependent. Remote testing and building is provided on
GitHub for continuous integration and delivery.

Start by [creating a personal
fork](https://github.com/canonical/youtube-links/fork) of the repository on
GitHub.

Next, on your host system, clone your fork and sync it with the upstream repository:

```bash
git clone git@github.com:<username>/sphinx-youtube-links
cd sphinx-youtube-links
git remote add upstream git@github.com:canonical/sphinx-youtube-links
git fetch upstream
```

If you don't authenticate with SSH, clone with
[HTTPS](https://docs.github.com/en/get-started/git-basics/about-remote-repositories#cloning-with-https-urls)
instead:

```bash
git clone https://github.com/<username>/sphinx-youtube-links
cd sphinx-youtube-links
git remote add upstream https://github.com/canonical/youtube-links
git fetch upstream
```

Inside the project directory, set up the virtual development environment and install all
dependencies, linters, and testers:

```bash
make install
make lint
make test
```

If all linting and testing completes without errors, your local environment is ready.

## Contribute a change

With the prerequisites out of the way, let's walk through how to make a contribution to
the project.

### Research the topic

All significant work should be tied to an existing issue or ticket.

If you'd like to add a small feature or fix, check the project's GitHub issues to see if
others have reported it. If they have, look into the current status of the topic. If no
one else is working on it, add a comment stating that you'd like to take it on, and a
maintainer will assign it to you.

If you're ever in doubt about developments in the project, ask!

### Create a development branch

Once you've settled on a topic to work on, it's time to set up a local branch.

Always start by syncing against the branch and the dependencies you're basing your
changes on.

```bash
git checkout main
git pull upstream main
git checkout -b <new-branch-name>
make setup
```

The new branch name should be brief, at no more than 80 characters. Format your branch
name as `<ticket-id>-<description>`. For example, if you're working on GitHub issue
\#235, and it's about adding a string sanitizer, you'd name your branch
`issue-235-add-string-sanitizer-method`.

### Commit a change

Once you've made the changes to the code and you're ready to test it, start by
committing:

```bash
git add -A
git commit
```

Format the commit message according to the [Conventional
Commits](https://www.conventionalcommits.org/en/v1.0.0/) style. For the sanitizer
example, an appropriate commit title would be:

```
feat: add text sanitizer
```

If you need help determining the type of conventional commit for your change, look at
the history of the file in question with `git log --oneline <filename>` . When you're
done browsing, press `Q` to exit the interactive log.

> **Tip**
>
> With complex changes, you might get stuck choosing a conventional commit type.
>
> This may signal that a commit is doing more than one thing and should be broken into
> multiple smaller commits. A commit should not, for example, refactor code and fix a
> bug. That should be two separate commits.
>
> In other scenarios, multiple types could be appropriate because of the nature of the
> commit. This can happen with `test` and `docs`, which can be used as either types
> or scopes.
>
> Run down the following list and select the highest-ranked type that fits your change:
>
> - ci
> - build
> - feat
> - fix
> - perf
> - refactor
> - style
> - test
> - docs
> - chore

Committing triggers the [pre-commit](https://pre-commit.com/) hook, which runs the
automatic code formatter and the fast linters.

If the linters reformatted any of the files, the commit was cancelled. To make the
changes stick, restage the modified files with `git add -A` and commit again.

### Test the change

All nontrivial code changes should be accompanied by a reasonable set of tests.

This project's test suite includes both unit and integration tests. If you're not
sure which tests you should add, go with your best judgement – additional tests can be
added during the review process.

Once you've made your changes, run the test suite:

```bash
make test
```

When iterating and testing, it's a good practice to clean the local temporary files that
the tests generate:

```bash
make clean
```

In rare instances, tests can fail in unpredictable ways, regardless of the state of your
code. In such cases, it's best to delete your virtual environment and start over:

```bash
rm -rf .venv
make clean
make setup
```

### Push the branch and open a PR

Once your work is committed to your branch, push it to your fork:

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

Finally, [open a PR](https://github.com/canonical/youtube-links/compare) for it on
GitHub. If your branch has one commit, GitHub will title the PR after it. If your branch
has more than one commit, name the PR after the most significant. Once open, reviewers
are assigned automatically to your work.

### Follow up for the review

When a maintainer reviews your PR, they typically leave inline comments and suggestions
on the code.

If the comment is a request, accommodate it by pushing one or more additional commits to
the branch. It's simplest to add the commits locally and push, rather than in the GitHub
interface, as it leads to fewer potential conflicts with syncs.

Don't force-push changes to the branch. It destroys the history of the review and makes
it harder for maintainers to see code changes.
