MyNixOS website logo
Description

Simple Hackage release workflow for package maintainers.

Hkgr (Hackager) is a tool to help make new releases of Haskell packages, with commands for git tagging, pristine sdist, and uploading to Hackage. There is also a command for creating a new local project.

Hkgr

Hackage GPL-3 license GitHub CI

hkgr (pronounced "hackager") is a tool for making releases of Haskell packages on Hackage.

It uses a cautious stepped iterative approach to releases.

Example usage

Here is an example of doing a release of hkgr itself.

After committing the latest changes for the release, create a tag and tarball:

$ hkgr tagdist
v0.4
No errors or warnings could be found in the package.
Running hlint
src/Main.hs:(407,9)-(408,55): Warning: Eta reduce
Found:
  replaceHolder lbl val file
    = sed ["s/@" ++ lbl ++ "@/" ++ val ++ "/"] file
Perhaps:
  replaceHolder lbl val = sed ["s/@" ++ lbl ++ "@/" ++ val ++ "/"]

[]
["src/Main.hs","data/template.cabal.tmpl","README.md","CHANGELOG.md","LICENSE","hkgr.cabal"]
[(NoExec,"CHANGELOG.md"),(NoExec,"LICENSE"),(NoExec,"README.md"),(NoExec,"data/template.cabal.tmpl"),(NoExec,"hkgr.cabal"),(NoExec,"src/Main.hs")]
Wrote tarball sdist to /home/petersen/github/hkgr/.hkgr/hkgr-0.4.tar.gz

After fixing up, retag a new tarball with --force and upload candidate, in one go:

$ hkgr upload -f
Updated tag 'v0.4' (was f6d72ba)
No errors or warnings could be found in the package.
Running hlint
[]
["src/Main.hs","data/template.cabal.tmpl","README.md","CHANGELOG.md","LICENSE","hkgr.cabal"]
[(NoExec,"CHANGELOG.md"),(NoExec,"LICENSE"),(NoExec,"README.md"),(NoExec,"data/template.cabal.tmpl"),(NoExec,"hkgr.cabal"),(NoExec,"src/Main.hs")]
Wrote tarball sdist to /home/petersen/github/hkgr/.hkgr/hkgr-0.4.tar.gz
hackage.haskell.org password:
Uploaded to https://hackage.haskell.org/package/hkgr-0.4/candidate

Alternatively if you had manually tagged the release with v0.4 you can use hkgr tagdist --existing-tag to create a dist tarball.

One can continue to tagdist -f and/or upload -f until everything looks good and CI passed etc.

Then it is time to push the final tag and publish the release:

$ hkgr publish
git pushing... done
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:juhp/hkgr.git
 * [new tag]         v0.4 -> v0.4
hackage.haskell.org password:
Published at https://hackage.haskell.org/package/hkgr-0.4

Help

$ hkgr --version

0.4.6

$ hkgr --help

Hackage Release tool

Usage: hkgr [--version] COMMAND

  'Hackager' is a package release tool for easy Hackage workflow

Available options:
  -h,--help                Show this help text
  --version                Show version

Available commands:
  new                      setup a new project
  tagdist                  'git tag' version and 'cabal sdist' tarball
  upload                   'cabal upload' candidate tarball to Hackage
  publish                  git push and cabal upload --publish
  upload-haddock           Upload candidate documentation to Hackage
  publish-haddock          Publish documentation to Hackage
  build                    Do a local pristine build from the tarball
  version                  Show the package version from .cabal file
  rename                   Rename the Cabal package
  github                   Add github repo

Details

tagdist

hkgr tagdist makes a dist tarball from a git tag:

The tagdist command first reads the current package version (from the .cabal file in the current directory), and uses that to git tag. It then runs cabal sdist from a temporary pristine checkout of the tag to generate the dist tarball.

Note that hkgr is lenient: it allows making a release with uncommitted changes in the working tree, but it will show the uncommitted changes. However the version must be committed.

If the tag already exists (eg if you already ran tagdist earlier), and you need to add commits to the release you can use --force to move the tag to the latest commit and generate a new tarball off that, otherwise tagdist refuses to run again to prevent accidently overwriting the tag and dist tarball.

One should not be able to tagdist on an already published (ie released) version made with hkgr, until the version is bumped.

If sdist fails for some reason then hkgr tries to reset the tag.

Alternatively if you have already manually tagged a release with 'v' prefix you can use --existing-tag to create a dist tarball.

upload

hkgr upload uploads the tarball to Hackage as a candidate release. Like hkgr tagdist -f, hkgr upload -f can be repeated.

Haddock draft documentation can also be uploaded once if desired with hkgr upload-haddock.

If you have an existing version tag (starting with v) you can use the --existing-tag option to skip the tagging step (like for tagdist).

publish

hkgr publish releases the tarball to Hackage, after doing a pristine local build and git pushing the tag and its commits to origin.

If it succeeds, then hkgr creates a "published lockfile" in .hkgr/.

(Then hkgr will refuse to do further commands on the released version.)

Optionally one can publish haddock docs with hkgr publish-haddock.

build

hkgr build will try to do a pristine build of the latest created tarball for the tag. This is useful for catching missing files from the tarball, preventing brownbag releases.

new

hkgr new creates a new project.

If you don't pass a name it will try to check the current directory.

It uses cabal init to setup various files but replaces the .cabal file with a template stored in ~/.config/hkgr/template.cabal which the user can freely customize.

A stack.yaml file and git repo is also set up.

github

(One can use gh repo create etc to create the project repo on Github) and then hkgr github to add the github remote to your project.

Requirements

hkgr uses cabal-install >=2, git, and also hlint if available.

Contribute

hkgr is licensed and distributed under the GPL version 3 or later.

Reports and contributions are welcome at https://github.com/juhp/hkgr.

Metadata

Version

0.4.6

Executables (1)

  • bin/hkgr

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows