# Contributors Guide Thank you for considering contributing to the maintenance or development of pantry! We hope that the following information will encourage and assist you. We start with some advice about pantry's governance. ## pantry's governance People involved in maintaining or developing pantry with rights to make commits to the repository can be classified into two groups: 'committers' and 'maintainers'. ### pantry's committers We encourages a wide range of people to be granted rights to make commits to the repository. People are encouraged to take initiative to make non-controversial changes, such as documentation improvements, bug fixes, performance improvements, and feature enhancements. Maintainers should be included in discussions of controversial changes and tricky code changes. Our general approach is **"it's easier to ask forgiveness than permission"**. If there is ever a bad change, it can always be rolled back. ### pantry's maintainers pantry's maintainers are long-term contributors to the project. Michael Snoyman (@snoyberg) was the founder of pantry, and its initial maintainer - and he has added others. Michael's current interests and priorities mean that he is no longer actively involved in adding new features to pantry. Maintainers are recognized for their contributions including: * Direct code contribution * Review of pull requests * Interactions on the GitHub issue tracker The maintainer team make certain decisions when that is necessary, specifically: * How to proceed, if there is disagreement on how to do so on a specific topic * Whether to add or remove (see further below) a maintainer Generally, maintainers are only removed due to non-participation or actions unhealthy to the project. Removal due to non-participation is not a punishment, simply a recognition that maintainership is for active participants only. We hope that removal due to unhealthy actions will never be necessary, but would include protection for cases of: * Disruptive behavior in public channels related to pantry * Impairing the codebase through bad commits/merges Like committers, maintainers are broadly encouraged to make autonomous decisions. Each maintainer is empowered to make a unilateral decision. However, maintainers should favor getting consensus first if: * They are uncertain what is the best course of action * They anticipate that other maintainers or users of pantry will disagree on the decision ## Bug Reports Please [open an issue](https://github.com/commercialhaskell/pantry/issues/new) and use the provided template to include all necessary details. The more detailed your report, the faster it can be resolved and will ensure it is resolved in the right way. Once your bug has been resolved, the responsible person will tag the issue as _Needs confirmation_ and assign the issue back to you. Once you have tested and confirmed that the issue is resolved, close the issue. If you are not a member of the project, you will be asked for confirmation and we will close it. ## Error messages To support the Haskell Foundation's [Haskell Error Index](https://errors.haskell.org/) initiative, all pantry error messages generated by pantry itself should have a unique initial line: ~~~text Error: [S-nnn] ~~~ where `nnn` is a three-digit number in the range 100 to 999. If you create a new pantry error, select a number using a random number generator (see, for example, [RANDOM.ORG](https://www.random.org/)) and check that number is not already in use in pantry's code. If it is, pick another until the number is unique. All exceptions generated by pantry itself are implemented using data constructors of closed sum types. Typically, there is one such type for each module that exports functions that throw exceptions. ## Code If you would like to contribute code to fix a bug, add a new feature, or otherwise improve pantry, pull requests are most welcome. It's a good idea to [submit an issue](https://github.com/commercialhaskell/pantry/issues/new) to discuss the change before plowing into writing code. Please include a [ChangeLog](https://github.com/commercialhaskell/pantry/blob/master/ChangeLog.md) entry with your pull request. ## Code Quality The pantry project uses [yamllint](https://github.com/adrienverge/yamllint) as a YAML file quality tool and [HLint](https://github.com/ndmitchell/hlint) as a code quality tool. ### Linting of YAML files The yamllint configuration extends the tools default and is set out in `.yamllint.yaml`. In particular, indentation is set at 2 spaces and `- ` in sequences is treated as part of the indentation. ### Linting of Haskell source code The HLint configurations is set out in `.hlint.yaml`. pantry contributors need not follow dogmatically the suggested HLint hints but are encouraged to debate their usefulness. If you find a HLint hint is not useful and detracts from readability of code, consider marking it in the [configuration file](https://github.com/commercialhaskell/pantry/blob/master/.hlint.yaml) to be ignored. Please refer to the [HLint manual](https://github.com/ndmitchell/hlint#readme) for configuration syntax. We are optimizing for code clarity, not code concision or what HLint thinks. You can install HLint with Stack. You might want to install it in the global project in case you run into dependency conflicts. HLint can report hints in your favourite text editor. Refer to the HLint repository for more details. To install, command: ~~~text stack install hlint ~~~ ## Code Style A single code style is not applied consistently to pantry's code and pantry is not Procrustean about matters of style. Rules of thumb, however, are: * keep pull requests that simply reformat code separate from those that make other changes to code; and * when making changes to code other than reformatting, follow the existing style of the function(s) or module(s) in question. That said, the following may help: * pantry's code generally avoids the use of C preprocessor (CPP) directives. Windows and non-Windows code is separated in separate source code directories and distinguished in pantry's Cabal file. Multi-line strings are generally formatted on the assumption that GHC's `CPP` language pragma is not being used. * Language pragmas usually start with `NoImplictPrelude`, where applicable, and then all others are listed alphabetically. The closing `#-}` are aligned, for purely aesthetic reasons. * pantry is compiled with GHC's `-Wall` enabled, which includes `-Wtabs` (no tabs in source code). Most modules are based on two spaces (with one space for a `where`) for indentation but older and larger modules are still based on four spaces. * pantry's code and documentation tends to be based on lines of no more than 80 characters or, if longer, no longer than necessary. * pantry uses export lists. * pantry's imports are listed alphabetically. The module names are left aligned, with space left for `qualified` where it is absent. * pantry's code is sufficiently stable that explict import lists can sensibly be used. Not all modules have comprehensive explicit import lists. * Short explicit import lists follow the module name. Longer lists start on the line below the module name. Spaces are used to separate listed items from their enclosing parentheses. * In function type signatures, the `::` is kept on the same line as the function's name. This format is Haskell syntax highlighter-friendly. * If `where` is used, the declarations follow on a separate line. ## Continuous integration (CI) We use [GitHub Actions](https://docs.github.com/en/actions) to do CI on pantry. The configuration of the workflows is in the YAML files in `.github/workflows`. The current active workflows are: ### Linting - `lint.yml` This workflow will run if: * there is a pull request * commits are pushed to this branch: `master` The workflow has one job (`style`). It runs on `ubuntu` only and applies yamllint and Hlint. ### Stan tool - `stan.yml` [Stan](https://hackage.haskell.org/package/stan) is a Haskell static analysis tool. As of `stan-0.1.0.1`, it supports GHC >= 9.6.3. The tool is configured by the contents of the `.stan.toml` file. This workflow will run if: * there is a pull request * requested ## Haskell Language Server You may be using [Visual Studio Code](https://code.visualstudio.com/) (VS Code) with its [Haskell extension](https://marketplace.visualstudio.com/items?itemName=haskell.haskell), which is powered by the [Haskell Language Server](https://github.com/haskell/haskell-language-server) (HLS). pantry can be built with Stack (which is recommended) or with Cabal (the tool). === "Stack" If you use Stack to build Stack, command `stack ghci` in the root directory of the pantry project should work as expected, if you have first commanded `stack build` once. `ghc` should be on the PATH if you run VS Code itself in the Stack environment: ~~~text stack exec -- code . ~~~ The following [cradle (`hie.yaml`)](https://github.com/haskell/hie-bios) should suffice to configure Haskell Language Server (HLS) explicitly for each of the buildable components in pantry's Cabal file: ~~~yaml cradle: stack: - path: "./src" component: "pantry:lib" - path: "./int" component: "pantry:lib" - path: "./app" component: "pantry:exe:test-pretty-exceptions" - path: "./test" component: "pantry:test:spec" ~~~ === "Cabal (the tool)" If you use Cabal (the tool) to build Stack, command `cabal repl` in the root directory of the Stack project should work as expected, if you have GHC and (on Windows) MSYS2 on the PATH. `ghc` and (on Windows) MSYS2 should be on the PATH if you run commands (including `cabal`) in the Stack environment: ~~~text stack exec --no-ghc-package-path -- cabal repl ~~~ or ~~~text stack exec --no-ghc-package-path -- code . ~~~ Use of GHC's environment variable `GHC_PACKAGE_PATH` is not compatible with Cabal (the tool). That is why the `--no-ghc-package-path` flag must be specified with `stack exec` when relying on Cabal (the tool). The following [cradle (`hie.yaml`)](https://github.com/haskell/hie-bios) should suffice to configure Haskell Language Server (HLS) explicitly for each of the buildable components in pantry's Cabal file: ~~~yaml cradle: cabal: - path: "./src" component: "lib:pantry" - path: "./int" component: "lib:pantry" - path: "./app" component: "exe:test-pretty-exceptions" - path: "./test" component: "test:spec" ~~~ A cradle is not committed to pantry's repository because it imposes a choice of build tool. ## Slack channel If you're making deep changes and real-time communication with the pantry team would be helpful, we have a `#stack-collaborators` Slack channel in the Haskell Foundation workspace. To join the workspace, follow this [link](https://haskell-foundation.slack.com/join/shared_invite/zt-z45o9x38-8L55P27r12YO0YeEufcO2w#/shared-invite/email). ## Matrix room There is also a [Stack and Stackage room](https://matrix.to/#/#haskell-stack:matrix.org) at address `#haskell-stack:matrix.org` on [Matrix](https://matrix.org/).