Hakyll is awesome

Congratulations on the release, on getting Cabal-install-3.12.1.0 (and accompanying libraries) released.

For a limited time, while the preview is up, you can also browse and read the release notes for this and other releases at https://cabal.blockscope.com/releases/.

I’ve been using Hakyll since 2013 and am very happy with it but wow am I impressed with how easy it was to include Cabal’s own release notes from github/haskell/cabal.

Cabal’s Web Site

I’m taking a break from contributing to Cabal itself and have picked up the relay baton on a pull request for updating Cabal’s own website:

Sadly, the GitHub web view of the folder with these markdown files is not sortable.

The cabal-install-3.12.1.0 changelog is rendered on Hackage as a non-clickable URL to the markdown file on GitHub.

The releases page of the preview I’m hosting for the work-in-progress for Cabal’s new website shows cabal-install and Cabal release notes in separate sections.

Add Release Notes, Group and Sort by Version

To add that page to the website involved:

  1. Adding a short Makefile to download the release note *.md and ignoring these files in .gitignore.
CABAL_VERSION ?= e7657ad319b9a5b50718262488d17aad915aad90
CABAL_URL := https://github.com/haskell/cabal/archive/${CABAL_VERSION}.tar.gz

all: .cabal-archive/cabal-${CABAL_VERSION}/README.md

.cabal-archive/cabal-${CABAL_VERSION}/README.md:
	rm -rf release-notes
	curl -sSL ${CABAL_URL} | tar -xz
	mkdir -p .cabal-archive
	mv cabal-*/release-notes -T release-notes
	mv cabal-*/ -t .cabal-archive
  1. Adding a rule to process the release notes, all *.md files.
    match "release-notes/*" $ do
        route $ setExtension "html"
        compile $
            pandocCompiler
                >>= loadAndApplyTemplate "templates/post.html" dateCtx
                >>= loadAndApplyTemplate "templates/default.html" dateCtx
                >>= relativizeUrls

Compilation for this rule is exactly the same as for the existing posts/* rule.

  1. Creating a releases index page for the release notes and sorting the release notes into groups and order within the groups by the version, descending.
main :: IO ()
main = hakyll $ do

    create ["releases/index.html"] $ do
        route idRoute
        compile $ do
            versions <- loadAll "release-notes/*"
            let
                title = takeBaseName . toFilePath . itemIdentifier
                filterOn s = filter ((s `isPrefixOf`) . title) versions
                order = sortBy (compare `on` (Down . versionOf . title))

                libs = order $ filterOn "Cabal-"
                exes = order $ filterOn "cabal-install-"
                wips = order $ filterOn "WIP-"

                ctx =
                    fold
                        [ listField "libs" defaultContext (return libs)
                        , listField "exes" defaultContext (return exes)
                        , listField "wips" defaultContext (return wips)
                        , defaultContext
                        ]

            makeItem ""
                >>= loadAndApplyTemplate "templates/releases.html" ctx
                >>= loadAndApplyTemplate "templates/default.html" ctx
                >>= relativizeUrls

When hakyll is used for a blog, the list is typically sorted by date with the date encoded as a prefix in each post’s filename.

posts <- recentFirst =<< loadAll "posts/*"

For the release notes, the version is encoded in the suffix of the filename so we
can decode the version and use that for sorting.

versionOf :: String -> Maybe Version
versionOf s = runReadP parseVersion version
    where
        version :: String
        version = filter (\x -> isDigit x || x == '.') s

-- SEE: hspec's BumpVersion.hs
runReadP :: ReadP a -> String -> Maybe a
runReadP p input = case reverse $ readP_to_S p input of
    (v, "") : _ -> Just v
    _ -> Nothing
  1. Adding an index page template:
<section class="header">
    <h2 class="display-4">Releases</h1>
    <p class="lead">The latest releases of the <samp>Cabal</samp>and <samp>cabal-install</samp>.</p>
</section>
<hr>
<section>

    <h2>Tool Releases</h2>
    Released versions of <samp>cabal-install</samp>, the package that includes the build tool <code>cabal</code>:
    <ul>
        $for(exes)$
        <li>
            <a href="$url$">$title$</a>
        </li>
        $endfor$
    </ul>

    <h2>Library Releases</h2>
    Released versions of <samp>Cabal</samp> the library package:
    <ul>
        $for(libs)$
        <li>
            <a href="$url$">$title$</a>
        </li>
        $endfor$
    </ul>

    <h2>Work in Progress</h2>
    Upcoming releases, if any:
    <ul>
        $for(wips)$
        <li>
            <a href="$url$">$title$</a>
        </li>
        $endfor$
    </ul>

</section>
14 Likes

I used to use Hakyll for my blog and frankly speaking for most use cases I’ve seen you could just delete the Hakyll import and use Pandoc (which does all the heavy lifting like templating out of the box) and plain Haskell, and not really notice a difference. For such an arcane API, that you have to work around often, I’m no longer convinced it brings much to the table.

Html templates; build rules differentiated for date/file type/etc.; link validation; preview server (with autocompilation when you change files); examples similar to the one highighted by Phil (generating an html page from a folder of files); easy RSS/Atom feeds…

There is a lot of convenience that Hakyll brings to the table.

4 Likes

One issue with these release notes is that it interprets -- as an mdash which you can see in “Make –(test-)show-details=direct” on https://cabal.blockscope.com/release-notes/cabal-install-3.12.1.0.html

1 Like

Thanks for reporting that issue @janus. I’ve set up issues for this fork but will also keep an eye on the upstream issue.

this looks amazing!!!

Uhmmm, something wrong with the certificate of cabal.blockscope.com it seems? :thinking:

I’m not using a wildcard cert, that I’d need here, but see that they’re now available from letsencrypt.

Thanks for the report @Vlix.

The preview is temporary and I’m hoping we’ll be able to have previews for Cabal’s website on another domain (maybe haskell.org?) sometime in the future. Local preview is available too but that is more hassle.

1 Like