{"id":13478901,"url":"https://github.com/begriffs/heroku-buildpack-ghc","last_synced_at":"2025-04-07T19:14:48.950Z","repository":{"id":10889579,"uuid":"13180779","full_name":"begriffs/heroku-buildpack-ghc","owner":"begriffs","description":"Deploy Haskell apps to Heroku","archived":false,"fork":false,"pushed_at":"2019-05-27T04:43:55.000Z","size":151,"stargazers_count":274,"open_issues_count":9,"forks_count":53,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-31T16:16:45.099Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/begriffs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-09-28T21:01:45.000Z","updated_at":"2025-03-23T13:09:38.000Z","dependencies_parsed_at":"2022-08-29T14:11:15.739Z","dependency_job_id":null,"html_url":"https://github.com/begriffs/heroku-buildpack-ghc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/begriffs%2Fheroku-buildpack-ghc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/begriffs%2Fheroku-buildpack-ghc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/begriffs%2Fheroku-buildpack-ghc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/begriffs%2Fheroku-buildpack-ghc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/begriffs","download_url":"https://codeload.github.com/begriffs/heroku-buildpack-ghc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247713258,"owners_count":20983683,"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":[],"created_at":"2024-07-31T16:02:05.510Z","updated_at":"2025-04-07T19:14:48.905Z","avatar_url":"https://github.com/begriffs.png","language":"Shell","funding_links":[],"categories":["Shell","CI"],"sub_categories":["Dependencies analysers"],"readme":"\u003cimg src=\"img/haskell.png\" alt=\"Styleguide Rails Logo\" align=\"left\" /\u003e\n\u003cimg src=\"img/heroku.png\" alt=\"Styleguide Rails Logo\" align=\"left\" /\u003e\n\u003cbr /\u003e\n\u003ch2 align=\"center\"\u003eDeploy Haskell apps to Heroku\u003c/h2\u003e\n\n\u003cbr /\u003e\n\nThis buildpack supports frameworks like Yesod, Snap, and Happstack with\nthe latest stable GHC binaries. Putting Haskell web applications online\nshould be easy, and now it is. Try it for yourself.\n\n\u003chr /\u003e\n**Note**, this buildpack does a basic build from scratch. For a\nfaster build, try\n[mietek/haskell-on-heroku](https://github.com/mietek/haskell-on-heroku)\nwhich detects your project dependencies and fetches a custom pre-built\nsandbox.\n\u003chr /\u003e\n\n### Example: deploying a Snap app\n\nHere's how to go from zero to \"hello world\" on Heroku. You'll need to\ninstall the [Haskell Platform](http://www.haskell.org/platform/) and\nthe [Heroku Toolbelt](https://toolbelt.herokuapp.com/) on your local\nmachine, then do this:\n\n```sh\n# Generate a barebones snap app called snapdemo\n\nmkdir snapdemo \u0026\u0026 cd $_\ncabal sandbox init\ncabal install snap\ncabal exec snap init barebones\n\n# Tell Heroku how to start the server\n\necho 'web: cabal run -- -p $PORT' \u003e Procfile\n\n# Create a git repo and deploy!\n\ngit init .\necho \"dist\\n.cabal-sandbox\\ncabal.sandbox.config\" \u003e .gitignore\ngit add *\ngit commit -m 'Initial commit'\n\nheroku create --stack=cedar-14 --buildpack https://github.com/begriffs/heroku-buildpack-ghc.git\ngit push heroku master\n```\n\n**The first deploy is slowest** as the environment downloads and\nbootstraps. Subsequent deploys use cached binaries and cached cabal\npackages to go faster.\n\n### Beating the Fifteen-Minute Build Limit\n\nThe first time you try to deploy a big framework like Yesod the\ncompilation can take so long that Heroku cuts it off. If this happens\nfear not, you can build your app with an Anvil server.\n\n```sh\n# Enable Anvil builds\nheroku plugins:install https://github.com/ddollar/heroku-anvil\n\n# Move big build artifacts out of the way or else the upload\n# to Anvil will be very slow\nmkdir -p /tmp/deploy-stash ; mv .cabal-sandbox /tmp/deploy-stash  ; mv dist /tmp/deploy-stash\n\n# Build your slug and cache without any time limits\nheroku build -r -b https://github.com/begriffs/heroku-buildpack-ghc.git\n\n# Use Anvil-generated cache next time we do a regular git push to Heroku\nheroku config:set EXTERNAL_CACHE=$(cat .anvil/cache)\n\n# Bring your sandbox etc back\nmv /tmp/deploy-stash/.cabal-sandbox . ; mv /tmp/deploy-stash/dist .\n```\n\nAfter the first deploy using Anvil you can go back to the regular\ndeploy process. This is because the cabal sandbox etc are cached\nby Anvil and will be retrieved, making future builds incremental\nand fast.\n\nRemember to `heroku config:unset EXTERNAL_CACHE` after your first\nsuccessful regular (post-Anvil) git push.\n\n### Locking Package Versions\n\nCabal sometimes gets confused on Heroku and tries installing outdated\npackages. If you have your app working locally you can constrain the\nremote package versions to match your local environment. Just do this:\n\n```sh\ncabal freeze\ngit add cabal.config\n\n# commit and push to fix remote build\n```\n\n### Configuring the Build\n\nYou can change build settings through Heroku environment variables.\n\n```sh\n# set the variable of your choice\nheroku config:set VARIABLE=value\n```\n\nHere are the options\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\u003cth\u003ename\u003c/th\u003e\u003cth\u003edescription\u003c/th\u003e\u003cth\u003edefault\u003c/th\u003e\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n  \u003ctd\u003eCLEAR_CACHE\u003c/td\u003e\n  \u003ctd\u003eForce everything to reinstall from scratch by setting to 1.\u003c/td\u003e\n  \u003ctd\u003e0\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003eEXTERNAL_CACHE\u003c/td\u003e\n  \u003ctd\u003eUrl of replacement buildpack cache tarball. Useful for Anvil.\u003c/td\u003e\n  \u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003eGHC_VER\u003c/td\u003e\n  \u003ctd\u003eGHC version to download or build\u003c/td\u003e\n  \u003ctd\u003e7.10.3\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003eCABAL_VER\u003c/td\u003e\n  \u003ctd\u003eVersion of cabal-install\u003c/td\u003e\n  \u003ctd\u003e1.22.8.0\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003ePREBUILT\u003c/td\u003e\n  \u003ctd\u003eBase url for the prebuilt binary cache\u003c/td\u003e\n  \u003ctd\u003ehttps://s3.amazonaws.com/heroku-ghc\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003ePRE_SCRIPT\u003c/td\u003e\n  \u003ctd\u003ePath to an executable, relative to checkout root. If present, this will be chmodded (+x) and ran before anything else.\u003c/td\u003e\n  \u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003ePOST_SCRIPT\u003c/td\u003e\n  \u003ctd\u003ePath to an executable, relative to checkout root. If present, this will be chmodded (+x) and ran after anything else.\u003c/td\u003e\n  \u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n\n### Interacting with a running app\n\n```sh\nheroku run bash         # shell access\nheroku run cabal repl   # Haskell repl with all app modules loaded\n```\n\n### Benefits of this buildpack\n\n* **Latest binaries: GHC 7.10.3, cabal-install 1.22.8.0**\n* Uses cabal \u003e=1.20 features to run the app and repl\n* Exposes Haskell platform binaries to your app and scripts\n* Uses prebuilt binaries for speed but...\n* ...can fall back to building the standard GHC distribution\n\n### Contributing\n\nThere are a number of ways to improve this buildpack. Please see the\nGithub issues for ideas.\n\nIn order to contribute to the build script it will help to understand\nhow Heroku's deployment process works, and how that affects GHC. Heroku\nprovides three areas for storing files during build: a cache directory,\na working directory, and a build directory.\n\nThe cache, called `$CACHE_DIR` in the script, persists between\ndeployments. We use it to avoid building binaries more than once. The\nworking directory, called `$WORKING_HOME`, does not persist between\nbuilds, or even after the build script is done. Seems we should avoid\nthis area, right? Well GHC has some idiosyncracies that make this area\nquite useful as you will see. Finally the build destination directory,\n`$BUILD_DIR`, holds the git repo the user pushes and gets copied into\nwhat will be `/app` in the deployed application. During build it lives\nin a weird nonce filename.\n\nWe want to use GHC binaries at build time to compile the app, and we\nwould also like those binaries to be available in the app environment\nafter deployment (so people can use `runhaskell` or `cabal repl`). Seems\nlike we should install directly to `$BUILD_DIR`. There's one problem:\nGHC breaks if you move it to a new path after installation because many\nof its binaries are just scripts with hard-coded full paths in them to\nother GHC files. And as you remember, Heroku is going to move things in\n`$BUILD_DIR` to `/app`. So the trick will be to install to `/app` in the\nworking directory, use GHC there, then copy that installation to the\nbuild directory which will be renamed in the deployed application and\nnot notice it has been moved.\n\nGHC is also sensitive to having `libgmp` named just right. We don't\nhave privileges to adjust `/usr/lib` in the deployed app so we create a\nsymbolic link in a place we are permitted and set linker variables in\nthe shell so that everything can build.\n\n### External dependencies\n\nSome packages have external dependencies (i.e. non-Haskell dependencies which cannot be satisfied by `cabal`). If you come across such a package, check in `contribs` to see if someone has already created patches for the dependencies. If they have, you should be able to\n```sh\npatch -p0 \u003c contribs/DEP.patch\n```\nto patch the buildpack and proceed. If not, you'll need to modify `bin/compile` yourself. Contributing these changes back as patches is appreciated.\n\n### Building new binaries for Heroku\n\nAs new versions of GHC and Cabal are released we should build them for\nHeroku and put them on S3 to speed up future deploys for everyone. Luckily\nthe buildpack can do the building too.\n\nAdjust the `GHC_VER` and `CABAL_VER` environment vars and then\ndeploy. It will build the new binaries from the standard GHC\ndistribution. Then copy the results to S3 like this:\n\n```sh\nheroku run bash\n# now SSH'd into the server\n\ncd /app/vendor\n\nurl \"https://s3.amazonaws.com/aws-cli/awscli-bundle.zip\" -o \"awscli-bundle.zip\"\nunzip awscli-bundle.zip\nawscli-bundle/install\n\n~/.local/lib/aws/bin/aws configure\n# ^^^ answer the configuration questions\n\ntar zcf heroku-ghc-[VERSION].tar.gz ghc-[VERSION]/\ntar zcf heroku-cabal-install-[VERSION].tar.gz cabal-install-[VERSION]/\n\n~/.local/lib/aws/bin/aws s3 cp heroku-ghc-[VERSION].tar.gz s3://[BUCKET]\n~/.local/lib/aws/bin/aws s3 cp heroku-cabal-install-[VERSION].tar.gz s3://[BUCKET]\n```\n\n### Thanks\n\nThanks to Brian McKenna and others for their work on\n[heroku-buildpack-haskell](https://github.com/puffnfresh/heroku-buildpack-haskell)\nwhich inspired and informed this buildpack. For a history of that project's\ncontributions and ideas see [this article]\n(http://blog.begriffs.com/2013/08/haskell-on-heroku-omg-lets-get-this.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbegriffs%2Fheroku-buildpack-ghc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbegriffs%2Fheroku-buildpack-ghc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbegriffs%2Fheroku-buildpack-ghc/lists"}