CONTRIBUTING.md

  1# Contributing <a name="contributing"></a>
  2
  3:wave: Hey there! Thanks for considering taking the time to contribute to
  4`git-bug`. This page contains some general guidelines, and instructions for
  5getting started as a contributor to this project.
  6
  7<!-- mdformat-toc start --slug=github --maxlevel=4 --minlevel=2 -->
  8
  9- [Get the source code](#get-the-source-code)
 10- [Software requirements](#software-requirements)
 11  - [Install nix](#install-nix)
 12  - [Install and configure `direnv`](#install-and-configure-direnv)
 13- [3.0 | Post-installation tasks](#30--post-installation-tasks)
 14  - [3.1 | Open a new shell](#31--open-a-new-shell)
 15  - [3.2 | Test the development shell](#32--test-the-development-shell)
 16- [Useful development commands](#useful-development-commands)
 17- [Submitting changes](#submitting-changes)
 18  - [Commit messages are the source of truth](#commit-messages-are-the-source-of-truth)
 19  - [Push early, push often](#push-early-push-often)
 20  - [Pull requests are squashed](#pull-requests-are-squashed)
 21  - [Draft vs Ready](#draft-vs-ready)
 22  - [Singular unit of change](#singular-unit-of-change)
 23
 24<!-- mdformat-toc end -->
 25
 26## Get the source code<a name="get-the-source-code"></a>
 27
 28Clone this repository to your system in a way you're comfortable with. Below, we
 29show a command that clones the repository using SSH, and places it in
 30`~/code/git-bug`.
 31
 32```bash
 33git clone git@github.com:git-bug/git-bug ~/code/git-bug
 34```
 35
 36> [!TIP]
 37> If you wish to clone the repository to another location on disk, change
 38> `~/code/git-bug` to your desired path (e.g. your current directory can be used
 39> with `.` or by omitting the path argument). The rest of this documentation
 40> will refer to `~/code/git-bug` in all instances, so make sure you change them
 41> there to match the location you've cloned the repository.
 42
 43## Software requirements<a name="software-requirements"></a>
 44
 45This repository uses `nix` to provide a consistent development environment,
 46ensuring that each contributor has the same revision of each dependency and tool
 47installed. It is **strongly** encouraged to use `nix` when contributing to
 48`git-bug` to remove the "it works on my machine" class of errors, and ensure you
 49have a smoother experience passing the CI pipelines (wrt formatting and such).
 50
 51While you can manually install the [tools and packages we use](./shell.nix) and
 52hack on this project on your own, you will miss out on the hermeticity and
 53standardization that our development shell provides. You may end up fighting
 54with failing CI pipelines more often, or have to figure out how to perform
 55various tasks on your own. Using the development shell ensures you always have
 56every tool you need to contribute to `git-bug`, and that each tool is always
 57configured correctly.
 58
 59Because of this, we encourage all contributors to follow the documentation below
 60to install the dependencies for the development shell.
 61
 62> [!NOTE]
 63> In the future, we will provide a container image with `nix` pre-installed and
 64> everything configured to get you started. This will be able to be pulled like
 65> any other image, and will be made compatible with VSCode's "devcontainer"
 66> feature and GitHub Codespaces.
 67>
 68> For more information, see the [tracking issue][issue/1364].
 69
 70______________________________________________________________________
 71
 72### Install nix<a name="install-nix"></a>
 73
 74To install `nix`, you can follow [the official instructions][install/nix].
 75
 76We recommend following the instructions for `multi-user mode` where applicable.
 77
 78> [!IMPORTANT]
 79> The rest of this document assumes you have successfully installed `nix`.
 80
 81______________________________________________________________________
 82
 83### Install and configure `direnv`<a name="install-and-configure-direnv"></a>
 84
 85[`direnv`][install/direnv] can be used to automatically activate the development
 86shell (using [`//:.envrc`][envrc]). It can be installed either with `nix`, or
 87independently.
 88
 89<details>
 90<summary><strong>With nix-env</strong> <em>(suggested for users new to nix)</em></summary>
 91
 92```bash
 93nix-env -iA direnv
 94```
 95
 96Next, run the following commands to apply the **optional** configuration for
 97direnv. Be sure to change references to `~/code/git-bug` if you have cloned the
 98repository somewhere else.
 99
100> [!NOTE]
101> The above command installs direnv in a non-deterministic way on your host
102> system. To update it, you'll need to run `nix-env -uA direnv`. See
103> `man nix-env-upgrade` for more information, or choose to install `direnv` in
104> another way that is more compatible with the approach you take for your
105> system.
106
107<strong>Create a configuration file for <code>direnv</code></strong>
108
109```bash
110mkdir -p ~/.config/direnv && touch ~/.config/direnv/direnv.toml
111```
112
113<strong>Disable the warning for shells with longer load times</strong>
114
115_This is optional, but recommended, as it helps reduce visual clutter._
116
117```bash
118nix-shell -p dasel --run \
119	'dasel -- -r toml -f ~/.config/direnv/direnv.toml put -t int -v 0 ".global.warn_timeout"'
120```
121
122<strong>Disable printing of the environment variables that change</strong>
123
124_This is optional, but recommended, as it helps reduce visual clutter._
125
126```bash
127nix-shell -p dasel --run \
128	'dasel -- -r toml -f ~/.config/direnv/direnv.toml put -t bool -v true ".global.hide_env_diff"'
129```
130
131<strong>Configure automatic activation of the development shell</strong>
132
133_This is optional, but strongly recommended._
134
135```bash
136nix-shell -p dasel --run \
137	'dasel -- -r toml -f ~/.config/direnv.toml put -v "~/code/git-bug/.envrc" ".whitelist.exact[]"'
138```
139
140Alternatively, simply run `direnv allow` after moving into the repository for
141the first time.
142
143> **IMPORTANT**<br /> If you choose not to allow the shell to be automatically
144> activated, you will need to type `nix-shell` every time you want to activate
145> it, and this will swap you into bash and change your prompt. You'll have a far
146> better experience allowing `direnv` to automatically manage activation and
147> deactivation.
148
149<strong>Configure your shell</strong>
150
151This final step is crucial -- be sure to
152[configure your shell][install/direnv/shell] for direnv, so that it is loaded
153properly on shell initialization.
154
155</details>
156
157<details>
158<summary><strong>Using <code>home-manager</code></strong></summary>
159
160```nix
161{
162  programs.direnv = {
163    enable = true;
164    nix-direnv.enable = true;
165
166    # one of the following, depending on your shell
167    # enableZshIntegration = true;
168    # enableBashIntegration = true;
169    # enableFishIntegration = true;
170    # enableNushellIntegration = true;
171
172    config = {
173      hide_env_diff = true;
174      warn_timeout = 0;
175
176      whitelist.exact = [ "~/code/git-bug/.envrc" ];
177    };
178  };
179}
180```
181
182</details>
183
184______________________________________________________________________
185
186## 3.0 | Post-installation tasks<a name="30--post-installation-tasks"></a>
187
188Congratulations! If you've reached this section of the documentation, chances
189are that you have a working development environment for contributing to this
190repository. Read below for some additional tasks you should complete.
191
192### 3.1 | Open a new shell<a name="31--open-a-new-shell"></a>
193
194In order for the installation to take effect, you will need to open a new shell.
195It is recommended to do this and complete the test (described below) prior to
196closing the shell you ran the installation script in, just in case you run into
197issues and need to refer to any output it provided.
198
199### 3.2 | Test the development shell<a name="32--test-the-development-shell"></a>
200
201To test that the development shell is active, you will need to move to the
202repository's directory. If you installed and properly configured `direnv` for
203automatic activation, the shell should activate upon changing directories.
204
205```bash
206{ test -n "$IN_NIX_SHELL" && echo "ACTIVE"; } || echo "INACTIVE"
207```
208
209If you have activated the development shell, you will see `ACTIVE` printed to
210the console. If you have not, you will see `INACTIVE` printed to the console. If
211you did configure direnv to automatically load the shell, you may need to type
212`direnv allow`. If you chose to not use `direnv`, you will need to manually type
213`nix-shell`.
214
215______________________________________________________________________
216
217## Useful development commands<a name="useful-development-commands"></a>
218
219- `make build` - build `git-bug` and output the binary at `./result/bin/git-bug`
220- `make build/debug` - build a debugger-friendly binary build\` for rapid
221  iteration,
222- `nix-build -A default` - build `git-bug` for your platform and output the
223  binary at `./result/bin/git-bug`. You can optionally tag it with a version by
224  adding
225  `--argstr version $(git describe --match 'v*' --always --dirty --broken)`.
226  - add `--arg debug true` to skip the test suite and build a debugger-friendly
227    binary that fetches the web interface from the filesystem, and contains the
228    symbol table and `DWARF` debug info
229  - optionally tag it with a version by adding the following flag:
230    `--argstr version $(git describe --match 'v*' --always --dirty --broken)`
231- `nix-shell --run treefmt` - format everything
232  - `nix-shell --run 'treefmt <path...>'` to restrict the scope to given
233    directories or files
234  - _see `nix-shell --run 'treefmt --help'` for more information_
235- `make check` to run tests and lint/format checks
236- `make format` to format all files
237- `go generate` - generate cli documentation and shell completion files
238  - this is automatically executed by many `make` targets, e.g. `make build`
239- `go test ./commands -update` - update golden files used in tests
240  - this is _required_ when changing the output of CLI commands, if the files in
241    `//commands/testdata/...` do not match the new output format
242- `pinact` to pin any newly-added github action libraries
243  - `pinact upgrade` to upgrade action libraries
244
245> [!NOTE]
246> There is an ongoing effort to simplify the commands you need to call in our
247> environment, with a trend toward `nix`, while `make` may continue to be
248> supported for common workflows (e.g. building a release binary).
249
250## Submitting changes<a name="submitting-changes"></a>
251
252You can submit your changes in the typical fork-based workflow to this
253repository on GitHub. That is: fork this repository, push to a branch to your
254repository, and create a pull request.
255
256If you are in the development shell, you have the `gh` command line tool
257available for use with github.
258
259### Commit messages are the source of truth<a name="commit-messages-are-the-source-of-truth"></a>
260
261Commit subjects and messages are the source of truth for a variety of things,
262including the public-facing changelog ([`//:CHANGELOG.md`][changelog]) and
263release descriptions. Writing thorough commit messages is beneficial to anyone
264reviewing a commit, including future you!
265
266Please be sure to read the [commit message guidelines][doc/contrib/commit].
267
268### Push early, push often<a name="push-early-push-often"></a>
269
270We encourage pushing small changes. There is no such thing as a contribution
271being "too small". If you're working on a big feature or large refactor, we
272encourage you to think about how to introduce it incrementally, in byte-sized
273chunks, and submit those smaller changes frequently.
274
275### Pull requests are _squashed_<a name="pull-requests-are-squashed"></a>
276
277All Pull Requests in this repository are _squash merged_. The resulting commit's
278subject and body is set as such:
279
280- The subject is set to the PR title, appended with the PR's number
281- The body is set to the contents of the PR description, otherwise known as the
282  first comment in the "Discussion" tab
283
284As such, maintainers may edit your PR title and description (the initial
285comment) before merging. This is to make sure commits that land in `trunk`
286messages have the appropriate context.
287
288### Draft vs Ready<a name="draft-vs-ready"></a>
289
290Pull Requests can be marked as "ready for review", or as a "draft". Drafts are
291less likely to get reviewed, for the simple fact that in English, the word
292"draft" (in relation to a change) implies that the work is not yet ready, or
293still being worked on. That said, we encourage you to iterate locally,
294especially if you are in the earlier stages of a change.
295
296Any PR, even a draft, triggers the pipelines to run our test suite. Note,
297however, that due to the cost (in terms of time and finance) associated with
298running the pipelines, we may, at our discretion, exclude various parts of our
299test suite from draft PRs.
300
301### Singular unit of change<a name="singular-unit-of-change"></a>
302
303Please keep any one PR limited to a singular unit of change. That is, do your
304best to avoid making multiple different changes in the same tree / PR. This
305helps make it simpler to reason about a change during review, and reduces the
306chance that your proposal ends up spawning five different conversations that
307each dig down their own rabbit hole.
308
309Good examples of a singular unit of change:
310
311- Renaming a function (or method or class or interface or...)
312- Adding a new endpoint
313- Deprecating a thing
314- Removing all of one type of thing (e.g. "remove all unused functions")
315
316Aim to make sure that your change does _one_ thing.
317
318Examples of what we _do not_ want to see in a given PR:
319
320- Rename function Foo and add function Bar
321- Update Baz and Foo
322- Move Thing and upgrade Bar
323- Deprecate Zam and add a new function Zoo
324
325Generally speaking, look out for the word "and". If you find yourself needing to
326write this word in a commit message when describing what your change does,
327consider whether it would be best to split those changes up into individual
328trees.
329
330______________________________________________________________________
331
332##### See more
333
334- [View the commit message guidelines][doc/contrib/commit]
335- [An overview of the architecture][doc/design/arch]
336- [Learn about the data model][doc/design/model]
337- [See how to create a new entity][example-entity]
338
339[changelog]: ./CHANGELOG.md
340[doc/contrib/commit]: ./doc/contrib/commit-message-guidelines.md
341[doc/design/arch]: ./doc/design/architecture.md
342[doc/design/model]: ./doc/design/data-model.md
343[envrc]: ./.envrc
344[example-entity]: ./entity/dag/example_test.go
345[install/direnv]: https://github.com/direnv/direnv/blob/trunk/docs/installation.md
346[install/direnv/shell]: https://github.com/direnv/direnv/blob/trunk/docs/hook.md
347[install/nix]: https://nix.dev/install-nix
348[issue/1364]: https://github.com/git-bug/git-bug/issues/1364