ghcup-hs/docs/dev.md

143 lines
7.1 KiB
Markdown
Raw Normal View History

2024-03-16 10:46:38 +00:00
# Development and contribution
2021-10-02 18:21:51 +00:00
2021-10-06 08:20:08 +00:00
All you wanted to know about GHCup development.
2020-04-12 17:48:26 +00:00
2024-03-16 10:46:38 +00:00
## Building
GHCup supports development via cabal and stack. E.g.:
* build via stack: `stack build`
* build via cabal (with whatever GHC version): `cabal build`
* build via cabal reproducibly with a specific GHC version
- GHC 8.10.7: `cabal build --project-file=cabal.ghc8107.project`
- GHC 9.0.2: `cabal build --project-file=cabal.ghc902.project`
- and so on (check supported versions via `ls cabal.ghc+([0-9]).project`)
* build the release binaries: `cabal build --project-file=cabal.project.release`
## Contribution process and expectations
* discuss your idea first before implementing anything
* GHCup is a dictatorship, so the final decisions are made by the author
* we don't manage contributors... you can work on anything you like
* reviews focus on logic and design, not on style and formatting
* remember that features, decisions and bugs are high impact, since GHCup is used in CIs, github workflows, etc.
2021-10-05 19:36:50 +00:00
## Module graph
[![Module graph](./modules_small.svg){: .center style="width:900px"}](./modules_wide.svg)
2021-10-06 08:20:08 +00:00
Main functionality is in `GHCup` module. Utility functions are
organised tree-ish in `GHCup.Utils` and `GHCup.Utils.*`.
Anything dealing with ghcup specific directories is in
`GHCup.Utils.Dirs`.
2021-12-06 19:00:41 +00:00
Download information on where to fetch bindists from is in the [ghcup-metadata](https://github.com/haskell/ghcup-metadata) repository.
2021-10-06 08:20:08 +00:00
2020-04-12 17:48:26 +00:00
## Design decisions
2021-10-04 19:40:48 +00:00
### Using [Excepts](https://hackage.haskell.org/package/haskus-utils-variant-3.0/docs/Haskus-Utils-Variant-Excepts.html) as a beefed up ExceptT
2020-04-12 17:48:26 +00:00
This is an open variant, similar to [plucky](https://hackage.haskell.org/package/plucky) or [oops](https://github.com/i-am-tom/oops) and allows us to combine different error types. Maybe it is too much and it's a little bit [unergonomic](https://github.com/haskus/packages/issues/32) at times. If it really hurts maintenance, it will be removed. It was more of an experiment.
2021-10-04 19:40:48 +00:00
### No use of haskell-TLS
2020-04-12 17:48:26 +00:00
2021-10-06 08:20:08 +00:00
I consider haskell-TLS an interesting experiment, but not a battle-tested and peer-reviewed crypto implementation. There is little to no research about what the intricacies of using haskell for low-level crypto are and how vulnerable such binaries are. Instead, we use either curl the binary or wget. There's also an implementation based on OpenSSL bindings, but it isn't enabled by default, since it would complicate shipping static binaries.
2020-04-12 17:48:26 +00:00
2021-10-04 19:40:48 +00:00
### Optics instead of lens
2020-04-12 17:48:26 +00:00
2021-10-06 08:20:08 +00:00
They're a little safer (less Monoid weirdness with view) and have better error messages. Consider the following with [lens](https://hackage.haskell.org/package/lens):
2020-04-13 13:20:56 +00:00
```
> view (_Just . to (++ "abc")) Nothing
""
```
2021-10-06 08:20:08 +00:00
vs [optics](https://hackage.haskell.org/package/optics):
2020-04-13 13:20:56 +00:00
```
2020-04-13 19:11:00 +00:00
> view (_Just % to (++ "abc")) Nothing
2020-04-13 13:20:56 +00:00
<interactive>:2:1: error:
• An_AffineFold cannot be used as A_Getter
• In the expression: view (_Just % to (++ "abc")) Nothing
In an equation for it: it = view (_Just % to (++ "abc")) Nothing
```
2020-04-12 17:48:26 +00:00
2021-10-06 08:20:08 +00:00
### StrictData on by default
2020-04-12 17:48:26 +00:00
Kazu Yamamoto [explained it in his PR](https://github.com/yesodweb/wai/pull/752#issuecomment-501531386) very well. I like to agree with him. The instances where we need non-strict behavior, we annotate it.
2021-10-06 08:20:08 +00:00
`Strict` is a little more odd as a default, since it depends on how you define your functions as well.
2020-04-28 15:41:08 +00:00
2021-10-06 08:20:08 +00:00
## Code style and formatting
2020-04-28 15:41:08 +00:00
2021-10-06 08:20:08 +00:00
Unfortunately, code formatters are semi-broken on this codebase, due to TH and CPP.
2020-04-28 15:41:08 +00:00
2021-10-06 08:20:08 +00:00
Some light suggestions:
2020-04-28 15:41:08 +00:00
2021-10-06 08:20:08 +00:00
1. mtl-style preferred
2. no overly pointfree style
3. use `where` a lot, so the main function body reads like prose
4. documentation is part of the code
2021-01-02 08:07:41 +00:00
2024-03-16 10:46:38 +00:00
## Common tasks
2021-01-02 08:07:41 +00:00
2021-10-04 19:40:48 +00:00
### Adding a new GHC version
2021-01-02 08:07:41 +00:00
2021-10-25 19:35:14 +00:00
Head over to: [https://github.com/haskell/ghcup-metadata#adding-a-new-ghc-version](https://github.com/haskell/ghcup-metadata#adding-a-new-ghc-version)
2021-10-06 08:20:08 +00:00
### Adding a new CLI command
2022-11-22 11:06:12 +00:00
An example illustration on how to deal with [optparse-applicative](https://hackage.haskell.org/package/optparse-applicative) can be seen here: [https://github.com/haskell/ghcup-hs/commit/c19dd5ee8b2edbaf0336af143f1c75b6f4843e26](https://github.com/haskell/ghcup-hs/commit/c19dd5ee8b2edbaf0336af143f1c75b6f4843e26)
2020-04-28 15:41:08 +00:00
2022-11-22 11:06:12 +00:00
Every subcommand now lives in its own module under [GHCup.OptParse.MyCommand](https://github.com/haskell/ghcup-hs/tree/master/app/ghcup/GHCup/OptParse).
2021-10-25 19:35:14 +00:00
2020-04-25 10:06:41 +00:00
## Major refactors
1. First major refactor included adding cross support. This added
`GHCTargetVersion`, which includes the target in addition to the version.
Most of the `Version` parameters to functions had to be replaced with
that and ensured the logic is consistent for cross and non-cross
installs.
2021-07-09 17:51:21 +00:00
2. This refactor added windows support wrt [#130](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/130).
The major changes here were switching `hpath` library out for `filepath`/`directory` (sadly) and
introducing a non-unix way of handling processes via the `process` library. It also introduced considerable
amounts of CPP wrt file handling, installation etc.
2021-10-25 19:35:14 +00:00
3. This refactor split up the huge `Main.hs` and put every subcommand in its own module: [#212](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/212)
2021-10-02 18:21:51 +00:00
# Releasing
2022-02-26 14:30:16 +00:00
1. Update version in `ghcup.cabal`
2021-10-02 18:21:51 +00:00
2. Update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `GHCupInfo` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version, read from `ghcup.cabal`.
3. Add ChangeLog entry
2022-02-26 17:47:07 +00:00
4. If a new ghcup yaml version is needed, create one at [ghcup-metadata repo](https://github.com/haskell/ghcup-metadata) and push to a temporary release branch, then update the `data/metadata` submodule in ghcup-hs repo to that branch, so CI can pass
2021-10-02 18:21:51 +00:00
2022-02-26 17:47:07 +00:00
5. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.
2021-10-02 18:21:51 +00:00
2022-02-26 17:47:07 +00:00
6. Download release artifacts and upload them `downloads.haskell.org/~ghcup` along with checksum files (also check `scripts/releasing/pull_release_artifacts.sh` and `scripts/releasing/sftp-upload-artifacts.sh`)
2021-10-02 18:21:51 +00:00
2022-02-26 17:47:07 +00:00
7. Add ghcup release artifacts to ALL yaml files, see [ghcup-metadata repo](https://github.com/haskell/ghcup-metadata)
2021-10-02 18:21:51 +00:00
2022-02-26 17:47:07 +00:00
8. Upload the final `ghcup-<ver>.yaml` (and a detached GPG sig of it) to `webhost.haskell.org/ghcup/data/` (for yaml versions <= 0.0.6) as well as [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata) (for all versions).
2021-10-02 18:21:51 +00:00
2022-02-26 17:47:07 +00:00
9. Update version in `scripts/bootstrap/bootstrap-haskell` (`ghver` variable at the top of the script)
2021-10-02 18:21:51 +00:00
2022-02-26 17:47:07 +00:00
10. Upload `scripts/bootstrap/bootstrap-haskell` and `scripts/bootstrap/bootstrap-haskell.ps1` to `webhost.haskell.org/ghcup/sh/`
2022-02-26 14:30:16 +00:00
2022-02-26 17:47:07 +00:00
11. Update the top-level ghcup symlinks at `downloads.haskell.org/~ghcup` (see `scripts/releasing/sftp-symlink-artifacts.sh`)
12. Update the `data/metadata` submodule in ghcup-hs repo to master
2022-02-26 17:50:58 +00:00
13. Do hackage release
14. Post on reddit/discourse/etc. and collect rewards
2021-10-06 08:20:08 +00:00
# Documentation
2021-10-02 18:21:51 +00:00
2021-10-06 08:20:08 +00:00
This documentation page is built via [mkdocs](https://www.mkdocs.org/), see `mkdocs.yml` and `docs/` subfolder.
The module graph needs [graphmod](https://github.com/yav/graphmod) and is generated via `scripts/dev/modgraph.sh`.