{"id":13702306,"url":"https://github.com/composewell/packcheck","last_synced_at":"2025-04-13T00:42:22.075Z","repository":{"id":12214460,"uuid":"68154905","full_name":"composewell/packcheck","owner":"composewell","description":"Universal build and CI testing for Haskell packages","archived":false,"fork":false,"pushed_at":"2025-03-20T20:23:29.000Z","size":4011,"stargazers_count":92,"open_issues_count":16,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-13T00:42:13.294Z","etag":null,"topics":["build","continuous-integration","haskell","test"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/composewell.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-13T23:12:43.000Z","updated_at":"2025-03-20T20:23:37.000Z","dependencies_parsed_at":"2024-01-14T19:22:28.890Z","dependency_job_id":"adc2595d-e4b6-425a-8604-c52e8cd1c327","html_url":"https://github.com/composewell/packcheck","commit_stats":{"total_commits":365,"total_committers":9,"mean_commits":40.55555555555556,"dds":"0.23561643835616441","last_synced_commit":"a68b7b9c7c21eef8ed273e67030efb1d4fec027c"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composewell%2Fpackcheck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composewell%2Fpackcheck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composewell%2Fpackcheck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composewell%2Fpackcheck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/composewell","download_url":"https://codeload.github.com/composewell/packcheck/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650417,"owners_count":21139672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build","continuous-integration","haskell","test"],"created_at":"2024-08-02T21:00:33.571Z","updated_at":"2025-04-13T00:42:22.049Z","avatar_url":"https://github.com/composewell.png","language":"Shell","funding_links":[],"categories":["CI"],"sub_categories":["Dependencies analysers"],"readme":"# packcheck\n\n[![Hackage](https://img.shields.io/hackage/v/packcheck.svg?style=flat)](https://hackage.haskell.org/package/packcheck)\n[![Gitter chat](https://badges.gitter.im/composewell/gitter.svg)](https://gitter.im/composewell/streamly)\n[![Windows Build status](https://ci.appveyor.com/api/projects/status/f7c0ncy84cxp8lbe?svg=true)](https://ci.appveyor.com/project/harendra-kumar/packcheck)\n[![CircleCI](https://circleci.com/gh/composewell/packcheck/tree/master.svg?style=svg)](https://circleci.com/gh/composewell/packcheck/tree/master)\n\n## Quick Start\n\n\u003c!--\nPlease use `cabal` version 2.4 or later.\n--\u003e\n\n### Build on CI\n\nTo use packcheck for CI testing of your repo:\n\n\u003c!--\n#### Travis\n* Add your package repo to Travis as necessary (See\n  https://docs.travis-ci.com/user/tutorial/)\n* Copy\n[.travis.yml](https://github.com/composewell/packcheck/blob/master/.travis.yml),\nto your package repo\n--\u003e\n\n#### CircleCI\n* Add your package repo to CircleCI as necessary (See\n  https://circleci.com/docs/2.0/getting-started/)\n* Copy\n  [.circleci/config.yml](https://github.com/composewell/packcheck/blob/master/.circleci/config.yml)\n  to your package repo\n\n#### Appveyor (Windows)\n* Add your package repo to Appveyor as necessary (See\n  https://www.appveyor.com/docs/server/)\n* Copy\n  [appveyor.yml](https://github.com/composewell/packcheck/blob/master/appveyor.yml)\n  to your package repo\n\n#### Github Actions\n* Add your package repo to Github as necessary (See\n  https://docs.github.com/en/actions/quickstart)\n* Copy\n  [.github/workflows/packcheck.yml](https://github.com/composewell/packcheck/blob/master/.github/workflows/packcheck.yml)\n  to your package repo\n\n#### Cirrus (FreeBSD)\n* Add your package repo to Cirrus as necessary (See\n  https://cirrus-ci.org/)\n* Copy\n  [.cirrus.yml](https://github.com/composewell/packcheck/blob/master/.cirrus.yml)\n  to your package repo\n\nCI should work out of the box for most packages. Uncomment the relevant lines\nin the CI config files or change the values of the environment variables for\nfine grained control or custom configuration.\n\n### Build on Local Machine\n\nYou can use packcheck to build or CI test a package on your local machine as\nwell.  For local use, copy\n[packcheck.sh](https://github.com/composewell/packcheck/blob/master/packcheck.sh)\nto your local machine (Linux/OSX/Windows), put it in your PATH, and run it\nfrom your package directory. You can pass the same environment variables that\nare used in CI files to run the exact same tests locally. Usage is as simple\nas:\n```\n$ packcheck.sh cabal\n$ packcheck.sh cabal GHCUP_VERSION=0.1.20.0 GHCVER=9.8.1\n$ packcheck.sh stack GHCVER=9.4\n```\n\n`packcheck` can automatically pick the requested version of GHC from:\n\n* multiple GHC path components in your PATH environment variable\n* stack installed ghc binaries\n\n### Out of the box support\n\n| cabal         | stack     |\n|---------------|-----------|\n\n| Linux         | OSX       | Windows       | FreeBSD |\n|---------------|-----------|---------------|---------|\n\n| Github        | Appveyor  | CircleCI      | Local Machine |\n|---------------|-----------|---------------|---------------|\n\nThe script can be easily adapted to any CI with a single line build command.\n\n## Key Features\n\n* _Error messages:_ A lot of emphasis has been put on providing precise and\n  detailed error messages when something fails so that the user can easily fix\n  things.\n* _Informational:_ The output provides all the information that you may want to\n  know, tool paths being used, their versions, how they are invoked, build\n  options, time taken by each build step etc. You can even copy the commands\n  from the output and paste them on your local host to reproduce the build or\n  failure and debug quickly.\n* _Same tests everywhere:_ You can run exact same tests with same options or\n  flags, in the same way, on all CI platforms.\n* _Choose options:_ Conveniently control all aspects of build through command\n  line or environment variables, including tool options or whether to enable\n  benchmarks, haddock, coverage, test etc.\n* _Picking GHC:_ Right GHC is picked up automatically from PATH or installed\n  using ghcup by specifying GHCUP_VERSION and GHCVER env vars.  Stack\n  installed GHC binaries can be picked automatically when available.\n* _Test source distribution:_ `packcheck` creates the source distribution and\n  builds the package from the generated tarball to make sure that you build\n  what you release and don't miss adding a file to the distribution. Also,\n  checks if any file in the git repo is missing in the source distribution.\n\u003c!--\n* _Upload coverage:_ To send coverage info to\n  [coveralls.io](https://coveralls.io) just uncomment a line in your respective\n  ci config file.\n--\u003e\n* _Non-destructive_: By default the script does not change any config or\n  upgrade any tools on the host machine.\n* _Auto tool install_: `stack` and `ghc` can be installed automatically\n\n## Introduction\n\nThe package `packcheck` includes a script called `packcheck.sh`, it is a high\nlevel universal super build script to uniformly, consistently build and\ncomprehensively sanity test a Haskell package across build tools (stack/cabal)\nand across all platforms (Linux/MacOS/Windows).  You do not need to be familiar\nwith any of the build tools to use it.\n\nTo make sure that it works everywhere without installing anything it is\ndeliberately written using the `bash` shell scripting language. Any of the\nparameters to control the builds can either be passed on the script command\nline or as environment variables for convenient use on CI systems.\n\n`packcheck` is also a minimal yet complete \"hello world\" Haskell package with\nmodel config files that can be used unmodified in any Haskell package. The CI\nconfigs can be modified **declaratively**, using environment variables, to adapt\nto **any** kind of build scenario you can imagine.\n\nThis model package has everything that a Haskell package usually has; including\ntests, benchmarks and Linux/MacOS/Windows CI already working. It can be used as\na starting point to develop a new package. Beginners can use it to learn about\nHaskell package metadata structure.\n\n## What all does it do?\n\nAn invocation of `packcheck.sh` performs a whole battery of tests, all aspects\ncan be controlled via environment variables, command line. The flow goes\nroughly as follows:\n\n* Pick or install the requested version of GHC/cabal/stack\n* create source distribution package, unpack and test from it\n* Check the differences in git repo and source distribution\n* perform distribution checks\n* build source\n* build benchmarks\n* build haddock docs\n* run tests\n* run `hlint`\n* generate coverage report\n\n## Usage Examples\n\nYou can run these commands on your local machine as well as inside a CI script.\nYou can try these commands in the `packcheck` package itself:\n```\n$ cd packcheck\n$ ./packcheck.sh cabal GHCUP_VERSION=0.1.20.0 GHCVER=9.8.1\n```\n\n```\n$ ./packcheck.sh stack RESOLVER=lts-21\n$ ./packcheck.sh stack GHCVER=8.6.5\n$ ./packcheck.sh stack RESOLVER=lts-21.24 STACK_YAML=stack-8.0.yaml STACK_BUILD_OPTIONS=\"--flag streamly:examples-sdl\" CABALVER=3.10\n# You can also do a cabal build using stack installed ghc:\n$ stack exec ./packcheck.sh cabal RESOLVER=lts-21\n```\n\nRun hlint commands on the directories `src` and `test`:\n```\n$ ./packcheck.sh hlint HLINT_OPTIONS=\"lint\" HLINT_TARGETS=\"src test\"\n```\n\n\u003c!--\nSend coverage info of the testsuites named `test1` and `test2` to coveralls.io\nusing `hpc-coveralls`.\n```\n$ ./packcheck.sh cabal GHCVER=8.8.3 COVERALLS_OPTIONS=\"test1 test2\"\n```\n--\u003e\n\n## Picking GHC versions\n\nWhen `GHCVER` parameter is not specified, `packcheck` looks for a binary named\n`ghc` in your `PATH` environment variable. It uses first such binary found in\n`PATH`.\n\nWhen `GHCVER` parameter is specified and is not set to `head`, it looks\nfor `ghc` in the `PATH` and if `GHCVER` is a PREFIX of the actual\nversion of `ghc` binary found then that `ghc` binary is used. Otherwise,\n`packcheck` tries to look for another `ghc` binary in the next PATH\ncomponents until it finds a matching `ghc` version.\n\nIf `GHCVER` is set to `head`, packcheck looks for `ghc-head` as the\ncompiler and does not check the numeric version of the compiler.\n\nIf `GHCUP_VERSION` is specified packcheck tries to use the existing `ghcup`\nto install the ghc, if `ghcup` is not found it installs the requested\nversion and then installs the `GHCVER` using it.\n\n\u003c!--\nWhen both `GHCVER` and `TOOLS_DIR` are specified then in addition to searching\nin `PATH` environment variable, `packcheck` also looks for ghc in\n`${TOOLS_DIR}/ghc/${GHCVER}*/bin`. This is to facilitate selecting any GHC\nversion from an `hvr/ghc` ubuntu PPA installation without putting all the\nmyriad GHC version directories explicitly in your `PATH`.\n--\u003e\n\nIf all of the above fails `packcheck` looks for ghc in the `stack` install\nlocations.\n\n## packcheck-safe\n\n`packcheck-safe.sh` is a more robust wrapper over `packcheck.sh`, it does not\ntrust or use any environment variables, all environment needs to be specified\nexplicitly on the command line. Therefore, it ensures better reproducibility.\n\nIt also catches any misspelled command line parameter names. For example,\n`packcheck.sh` won't catch it if you typed `GHCVWR=9.8` instead of\n`GHCVER=9.8`, it just assumes that `GHCVER` is not specified.\n`packcheck-safe.sh` would generate an error saying that `GHCVWR` is not\nrecognized. Since it uses a clean environment you will have to specify PATH as\nwell on the command line. For example,\n\n```\n$ ./packcheck-safe.sh cabal PATH=/bin:/usr/bin:/opt/ghc/bin\n```\n\n## packcheck-remote\n\n`packcheck-remote.sh` is a wrapper over `packcheck.sh`. It allows you to run\npackcheck on a remote repository by cloning it locally and optionally merging a\nbranch into another branch (e.g. merging a PR branch into master).\n\n```\n$ ./packcheck-remote.sh --force \\\n    --remote=https://github.com/user/repo \\\n    --checkout=origin/master \\\n    --merge=origin/branch \\\n    --directory=./repo.packcheck \\\n    -- cabal GHCVER=9.8.1\n```\n\nUse `./packcheck-remote.sh --help` for more information.\n\n## Full Reference\n\nPlease use `cabal` version 2.4 or later.\n\nNOTE: Any of the parameters described below can either be passed on command\nline or as an environment variable. Passing options on command line is more\nconvenient when running interactively, while environment variables are more\nconvenient when running on a CI system.\n\n```\n$ ./packcheck.sh --help\n\n--------------------------------------------------\nUsage\n--------------------------------------------------\npackcheck.sh COMMAND [PARAMETER=VALUE ...]\n\nFor example:\npackcheck.sh cabal GHCVER=9.8.1\npackcheck.sh stack RESOLVER=lts GHC_OPTIONS=\"-O0 -Werror\"\npackcheck.sh hlint\n\nAsk questions: https://app.gitter.im/#/room/#composewell_streamly:gitter.im\nReport issues: https://github.com/composewell/packcheck/issues/new\n\nControl parameters can either be passed on command line or exported\nas environment variables. Parameters marked DESTRUCTIVE may modify\nyour global user config or state.\n\nBoolean parameters can be specified as\ny|Y|yes|Yes|YES|true|True|TRUE|on|On|ON for an affirmative value and as\nn|N|no|No|NO|false|False|FALSE|off|Off|OFF or empty for a negative value.\n\n--------------------------------------------------\nCommands and flags\n--------------------------------------------------\ncabal                   : build using cabal\nstack                   : build using stack\nhlint                   : run hlint\nclean                   : remove the .packcheck directory\ncleanall                : remove .packcheck, .stack-work directories\nhelp | --help | -h      : show this help message\n--version               : show packcheck version\n\n--------------------------------------------------\nSelecting tool versions\n--------------------------------------------------\nGHCUP_VERSION           : [a.b.c.d] ghcup version to install at $HOME/.ghcup/bin/ghcup (see https://downloads.haskell.org/~ghcup)\nGHCVER                  : [a.b.c | head] GHC version prefix (may not be enforced when using stack)\nCABALVER                : [a.b.c.d] Cabal version (prefix) to use\nSTACKVER                : [a.b.c.d] Stack version (prefix) to use\nSTACK_UPGRADE           : [y] DESTRUCTIVE! Upgrades stack to latest version\nRESOLVER                : Stack resolver to use for stack builds or cabal builds using stack\nHLINT_VERSION           : hlint version to install at $HOME/.local/bin/hlint (see https://github.com/ndmitchell/hlint/releases)\nDOCSPEC_URL             : cabal-docspec release URL to install at $HOME/.local/bin/cabal-docspec (see https://github.com/phadej/cabal-extras/releases/)\n\n--------------------------------------------------\nWhere to find the required tools\n--------------------------------------------------\nPATH                    : [path] Set PATH explicitly for predictable builds\n\n--------------------------------------------------\nSpecifying common tool options\n--------------------------------------------------\nGHCUP_GHC_OPTIONS       : Used as in \"ghcup install ghc \u003cGHCUP_GHC_OPTIONS\u003e \u003cversion\u003e\"\nGHC_OPTIONS             : Specify GHC options to use\nSDIST_OPTIONS           : Arguments to stack/cabal sdist command\n\n--------------------------------------------------\nSpecifying what to build\n--------------------------------------------------\nDISABLE_BENCH           : [y] Do not build benchmarks, default is to build but not run\nDISABLE_TEST            : [y] Do not run tests, default is to run tests\nDISABLE_DOCS            : [y] Do not build haddocks, default is to build docs\nENABLE_DOCSPEC          : [y] Run cabal-docspec after the cabal build\nDISABLE_SDIST_BUILD     : [y] Do not build from source distribution\nDISABLE_SDIST_PROJECT_CHECK: [y] Ignore project file and continue\nDISABLE_SDIST_GIT_CHECK : [y] Do not compare source distribution with git repo\nDISABLE_DIST_CHECKS     : [y] Do not perform source distribution checks\n\n--------------------------------------------------\ncabal options\n--------------------------------------------------\nCABAL_REINIT_CONFIG     : [y] DESTRUCTIVE! Remove old config to avoid incompatibility issues\nCABAL_PROJECT           : Alternative cabal project file, path relative to project root\nCABAL_BUILD_OPTIONS     : ADDITIONAL cabal build options to append to defaults\nCABAL_TEST_OPTIONS      : ADDITIONAL cabal test options to append to defaults\nCABAL_DISABLE_DEPS      : [y] Do not install dependencies, do not do cabal update\nCABAL_BUILD_TARGETS     : cabal build targets, default is 'all'\nCABAL_CHECK_RELAX       : [y] Do not fail if cabal check fails on the package.\nCABAL_HACKAGE_MIRROR    : DESTRUCTIVE! Specify an alternative mirror, modifies the cabal config file.\n\n--------------------------------------------------\nstack options\n--------------------------------------------------\nSTACK_YAML              : Alternative stack config file path relative to project root\nSTACK_OPTIONS           : ADDITIONAL stack global options (e.g. -v) to append\nSTACK_BUILD_OPTIONS     : ADDITIONAL stack build command options to append\n\n--------------------------------------------------\nhlint options\n--------------------------------------------------\nHLINT_OPTIONS           : hlint arguments e.g.'--datadir=. lint'\nHLINT_TARGETS           : target directories to run hlint on e.g. 'src test'\n\n--------------------------------------------------\nCoverage options\n--------------------------------------------------\nCOVERAGE                : [y] Just generate coverage information\n\n--------------------------------------------------\nDiagnostics options\n--------------------------------------------------\nCHECK_ENV               : [y] Treat unknown env variables as error, used with env -i\nBASE_TIME               : System time to be used as base for timeline reporting\n```\n\nBuild fails if `DISABLE_SDIST_BUILD` is not set and the contents\nof the source distribution tar ball do not match the git repository\ncontents. Either add any exceptions to `.packcheck.ignore` file or use\n`DISABLE_SDIST_GIT_CHECK=y` to disable this feature. Currently this check is\ndone only if `git` and `tar` commands are available in the `PATH`.\n\nOptions marked `DESTRUCTIVE!` are fine in a CI environment. But on a\nlocal machine sometimes it may not be desirable as it will change the\nstate of your global cabal config, so consider that before using these options.\n\nBy default cabal builds are done using sandboxes. It creates any temporary\nfiles or build artifacts inside `.packcheck` directory. See the `clean` and\n`cleanall` commands to release the temporary space.\n\n`stack` is automatically installed and can be used to do cabal builds as well.\nIf you specify `BUILD=cabal` and `RESOLVER` at the same time then the cabal\nbuild uses stack installed `cabal` and `ghc`, both are installed automatically\nwhen needed.\n\nFor pure cabal builds i.e. when `BUILD=cabal` and `RESOLVER` is not\nspecified, `cabal` and `ghc` must be pre-installed on the system before\nbuilding.\n\n\u003c!--\n## Coveralls\n\nPlease pick the updated version of `hpc-coveralls` from\n[here](https://github.com/composewell/hpc-coveralls). You can create a\n`cabal.project.coveralls` file, and use that as project file using\nthe `CABAL_PROJECT=cabal.project.coveralls` option/env var.\n\n```\npackages: .\n\nsource-repository-package\n  type: git\n  location: https://github.com/composewell/hpc-coveralls\n  tag: d9e20179579f0638f6e978816355d18568e6a1f0\n```\n--\u003e\n\n## Diagnostics\n\nSometimes you may run into issues due to some environment variables unknowingly\nset or some command line parameters or env variables being misspelled and\ntherefore silently ignored. To avoid any such issues the robust way to invoke\n`packcheck` is to use a clean environment using `env -i` and passing\n`CHECK_ENV=y` parameter. When this parameter is set unwanted/misspelled\nvariables are detected and reported.\n\n```\n$ env -i CHECK_ENV=y ./packcheck.sh stack\n```\n\nFor performance diagnostics `packcheck` prints the time elapsed from the\nbeginning at each build step performed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomposewell%2Fpackcheck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomposewell%2Fpackcheck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomposewell%2Fpackcheck/lists"}