Announcing Stack Lint Extra Deps
by @pbrisbin on December 17, 2021
Freckle is happy to announce a new command-line tool for linting a
Stack-based Haskell application. If you make heavy use of extra-deps, this
tool may be useful to you.
Context & Motivation
At Freckle, we publish a custom snapshot for use across all
our Haskell applications. This brings a minor bit of supply-chain security, but
we primarily do it out of convenience. As a team, we no longer manage disparate,
app-specific resolvers or extra-deps; we just use the canonical snapshot and
assume the same versions of all dependencies when we move from project to
project. extra-deps require maintaining (as I’ll describe soon), so
centralizing them has been a big boost to efficiency.
There exists a priority order of extra-deps sources:
- Using the latest Hackage release
- Using any Hackage release
- Using the latest gitversion tag
- Using any gitversion tag
- Using the latest gitcommit
- Using any gitcommit
Whenever we release a new snapshot (roughly every two weeks), we re-evaluate
every extra dependency to see if we can now move it up on this list. We used to
do this cumbersome series of checks by hand for every dependency: referencing
the new resolver’s Stackage page, checking against Hackage, and possibly
browsing git tags. With any reasonably-sized list of extra-deps this takes
ages.
We built lint-extra-deps to do it for us:

Features
Checks
lint-extra-deps asks the following for each extra dependency and suggests changes depending on the answers:
If it’s a Hackage dependency,
- Is there a same-or-newer version in the resolver?
- Is there a newer version on Hackage?
If it’s a Git dependency,
- Is there a newer commit with a version-like tag that exists in Hackage?
- Is there a newer commit with a version-like tag at all?
- Are there newer commits?
The Git checks are somewhat heuristics-based. We assume the base name of the
repository is the package name on Hackage, and we take any tag that parses as a
Version to represent a possibly-released version. This may result in
false-positives or false-negatives.
Which checks are performed can be changed through the --checks option.
Exclude/Include
lint-extra-deps will operate on the extra-deps or packages key of the input
Yaml file. This means it supports stack.yaml or snapshot.yaml use-cases. By
default, it processes all dependencies, but you can:
- Pass multiple --exclude PATTERNoptions to not operate on the given dependencies, and/or
- Pass a PATTERNargument to operate on only matching dependencies
PATTERN is a glob matched against the Hackage package name or the owner/repo
portion of a git dependency.
For example,
stack lint-extra-deps --exclude 'freckle/*'
Would skip any git dependencies from our own organization, and
stack lint-extra-deps 'hspec*'
Would check only the handful of Hspec packages we’re using right now.
Exit
By default, lint-extra-deps exits non-zero if suggestions were made, but this
can be disabled by passing --no-exit.
Installation
We’re shipping binaries from CI and you can find instructions for installing them in the README, or head right to the Releases.
stack will look for any executables named stack-{subcommand} and support
calling them as, well, a sub-command. So with this installed, you can run (e.g.)
stack lint-extra-deps --help for complete usage.
At Freckle, we rarely let an annoying and manual task go un-automated. If you
are are performing similar extra-deps maintenance for your projects, we hope
this tool can get you back some time.
If you would enjoy working on tools like this, or the projects it enables, we’re hiring. And as always, patches welcome.