Turn on henforcer and fourmolu - #7
Draft
onslaughtq wants to merge 7 commits into
Draft
Conversation
Adopts the plugin per the org convention, gated at impl (ghc >= 9.6) like beeline, shrubbery and bounded-text. GHC 9.2 cannot run it at all -- it needs base >= 4.17 -- and 9.4 is left off the gate to match the fleet, though henforcer itself supports 9.4. Pinned from Hackage rather than the git commit every other repo uses. The plugin's README still says it is unreleased, but henforcer-1.0.0.1 is published, and its tested-with reaches GHC 9.14.1 -- newer than the commit the fleet pins. This is also the first repo in the org to run henforcer under 9.12, which works. The config sets allowedOpenUnaliasedImports = 1, not 0. henforcer counts the implicit `import Prelude` as an open import, so 0 is unreachable without NoImplicitPrelude -- which is why every repo in the fleet uses 1. That one slot is Prelude, so every explicit import now carries an alias or an import list. The documentation caps are deliberately left out. Network.FTP.Client exports roughly forty-five names, most undocumented, and enforcing that is a documentation project rather than a tooling change. beeline comments the same two rules out. Imports follow the house style of a qualified alias plus an explicit list for operators: attoparsec as AC, Control.Exception as Exception, Data.Bits as Bits, Network.Connection as Connection, Control.Monad.IO.Class as MIO, with (<=<) and (***) imported by name. Prepositive `import qualified` is kept rather than the postpositive form the codex shows, since these modules are Haskell2010 and would otherwise need ImportQualifiedPost. Module headers gain the Copyright field the config requires. The conduit module's header also named Network.FTP.Client, a copy-paste error.
fourmolu.yaml is copied byte for byte from the rest of the org -- all twelve repos that have it are identical, and it matches the config documented in codex programming_style.md. scripts/format-repo follows the git ls-files variant used by eight of the eleven repos, rather than the find-piped-through-grep one in bounded-text and shrubbery, whose pattern is unanchored and unescaped and so matches any path containing "hs". The safe.directory line matters: the container runs as root against a checkout owned by the runner, and git otherwise refuses to read it. The three repos that omit it are exactly the three with no CI job, so it has never been exercised there. The check job needs no stack-root cache because nothing compiles; fourmolu is a plain binary on the image's PATH. This commit only adds the tooling. The repository is not yet formatted, so the new job would fail here -- the reformat is the next commit.
Mechanical only, no functional changes. Verify by re-running ./scripts/format-repo rather than by reading the diff.
The blame ignore file follows purescript-erumu, which does the same for its
purs-tidy sweep. Configure git to use it with
git config blame.ignoreRevsFile .git-blame-ignore-revs
Both packages get a patch bump: the import qualification and the formatting
change no code that a consumer can observe, and henforcer sits behind the
manual ci flag, which defaults off.
henforcer exempts any import carrying a hiding clause, so `import Conduit hiding (MonadResource)` was never reported and got left unqualified while everything around it was qualified. That satisfied the plugin but not the convention. Qualifying it removes the workaround rather than adding to it: with Conduit qualified, MonadResource cannot arrive unqualified from it, so the explicit resourcet import is the only source and the hiding clause is unnecessary. MonadIO and liftIO now come from Control.Monad.IO.Class as MIO, matching Network.FTP.Client, instead of riding in on Conduit's re-export.
The formatting-check job was added after the fork-only pull_request guard, so it lacked the condition and would have run twice for every same-repo pull request -- once from push and once from pull_request. The blame ignore file also still named the pre-rebase format commit. That SHA changes every time this branch is restacked, so it is worth re-checking on each rebase until this lands on main.
There was a problem hiding this comment.
Pull request overview
Adds Henforcer and Fourmolu enforcement while preserving support across the GHC matrix.
Changes:
- Enables Henforcer for CI builds on GHC 9.6+.
- Adds Fourmolu configuration, formatting script, and CI check.
- Reformats Haskell sources and updates package metadata.
Reviewed changes
Copilot reviewed 23 out of 28 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/main.yaml |
Adds formatting CI job. |
.git-blame-ignore-revs |
Excludes mass-format commit from blame. |
fourmolu.yaml |
Defines formatting rules. |
scripts/format-repo |
Runs Fourmolu in check or write mode. |
stack.yaml.lock |
Locks Henforcer dependencies. |
stack-ghc-9.6.yaml |
Adds GHC 9.6 Henforcer dependencies. |
stack-ghc-9.6.yaml.lock |
Locks GHC 9.6 dependencies. |
stack-ghc-9.8.yaml |
Adds GHC 9.8 Henforcer dependencies. |
stack-ghc-9.8.yaml.lock |
Locks GHC 9.8 dependencies. |
stack-ghc-9.10.yaml |
Adds GHC 9.10 Henforcer dependencies. |
stack-ghc-9.10.yaml.lock |
Locks GHC 9.10 dependencies. |
stack-ghc-9.12.yaml |
Adds GHC 9.12 Henforcer dependencies. |
stack-ghc-9.12.yaml.lock |
Locks GHC 9.12 dependencies. |
ftp-client/henforcer.toml |
Configures Henforcer rules. |
ftp-client/package.yaml |
Enables plugin and bumps version. |
ftp-client/ftp-client.cabal |
Regenerates Cabal metadata. |
ftp-client/CHANGELOG.md |
Documents tooling release. |
ftp-client/Setup.hs |
Applies formatting. |
ftp-client/src/Network/FTP/Client.hs |
Qualifies imports and reformats source. |
ftp-client/test/test.hs |
Reformats tests. |
ftp-client-conduit/henforcer.toml |
Configures Henforcer rules. |
ftp-client-conduit/package.yaml |
Enables plugin and bumps version. |
ftp-client-conduit/ftp-client-conduit.cabal |
Regenerates Cabal metadata. |
ftp-client-conduit/CHANGELOG.md |
Documents tooling release. |
ftp-client-conduit/Setup.hs |
Applies formatting. |
ftp-client-conduit/src/Network/FTP/Client/Conduit.hs |
Qualifies imports and reformats source. |
example/Setup.hs |
Applies formatting. |
example/app/Main.hs |
Reformats example application. |
Suppressed comments (2)
ftp-client/src/Network/FTP/Client.hs:134
- This Haddock text was accidentally rewritten with the import qualifier. It should describe the “three-digit response code,” not an
AC.digitresponse code.
-- ^ The three AC.digit response code
ftp-client/src/Network/FTP/Client.hs:143
- The public type documentation now says
AC.digit, which exposes an unrelated internal import alias and makes the sentence incorrect. Restore “First digit of an FTP response.”
-- | First AC.digit of an FTP response
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| } deriving Eq | ||
| data FTPResponse = FTPResponse | ||
| { frStatus :: ResponseStatus | ||
| -- ^ Interpretation of the first AC.digit of an FTP response code |
Comment on lines
+88
to
+90
| - henforcer | ||
| ghc-options: | ||
| - -fplugin Henforcer |
Comment on lines
+87
to
+89
| - henforcer | ||
| ghc-options: | ||
| - -fplugin Henforcer |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Both of these were held back while the CI and
-Werrorwork landed. Three commits: the plugin, then the formatter config and its CI job, then the reformat on its own so it can be checked by re-running the formatter instead of read.Two things a reviewer won't guess.
allowedOpenUnaliasedImportsis 1, not 0. henforcer counts the implicitimport Preludeas an open import, so 0 is unreachable withoutNoImplicitPrelude— which is why every repo in the org uses 1. That one slot is Prelude, and every explicit import now carries an alias or an import list.henforcer is pinned from Hackage rather than the git commit the other repos pin. Its README still says it hasn't been released, but 1.0.0.1 is published and its
tested-withreaches further than the commit the fleet points at. This is also the first repo here to run it under GHC 9.12.The documentation rules (
maximumExportsPlusHeaderUndocumentedand the@sincecaps) are deliberately left off.Network.FTP.Clientexports about forty-five names, most undocumented, so turning those on is a documentation project rather than a tooling change; beeline comments the same two rules out..git-blame-ignore-revsnames the reformat commit. To skip it in blame:Stacked:
add-ci-multi-ghc→fix-response-line-partiality→pr-2-multiline-and-handle-exports→add-ci-flag→add-henforcer-fourmolu→fix-audit-findings. Merge bottom-up.