#!/usr/bin/env bash # Script to generate and deploy Hackage repository for head.hackage patchset. # The hackage-security keys are stored in a tarball, $KEYS_TARBALL, encrypted # with the key material given in $KEYS_TARBALL_KEY. # # To test under NixOS: nix run nixpkgs.openssl nixpkgs.pwgen set -e cipher=aes-256-cbc if [ -z "$PATCHES" ]; then PATCHES=./patches; fi # For use by administrator. gen_keys_tarball() { hackage-repo-tool create-keys --keys=./keys pass="$(pwgen 32 1)" tar -c keys | openssl enc -$cipher -pbkdf2 -e -k "$pass" > keys.tar.enc echo "Wrote ./keys.tar.enc" echo "$pass" > keys.key echo "KEYS_TARBALL_KEY = $pass" } # Helper to decrypt and extract the keys tarball. extract_keys_tarball() { if [ -z "$KEYS_TARBALL_KEY" ]; then echo "Can't extract keys tarball: KEYS_TARBALL_KEY not set" exit 1 fi if [ -z "$KEYS_TARBALL" ]; then echo "Can't extract keys tarball: KEYS_TARBALL not set" exit 1 fi curl $KEYS_TARBALL | openssl enc -$cipher -pbkdf2 -d -k "$KEYS_TARBALL_KEY" | tar -x if [ ! -d ./keys ]; then echo "Key tarball extraction failed" exit 1 fi } build_repository_blurb() { local keys="$(find keys/root -type f -printf "%f")" local newline=$'\n' if [ -z "$REPO_NAME" ]; then REPO_NAME="head.hackage.ghc.haskell.org" fi if [ -z "$REPO_URL" ]; then REPO_URL="https://ghc.gitlab.haskell.org/head.hackage/" fi sed -e 's/ \+$//' <<EOF repository $REPO_NAME url: $REPO_URL secure: True key-threshold: 3 root-keys: ${keys//.private/$newline } EOF } build_index() { local commit="$CI_COMMIT_SHA" local commit_url="https://gitlab.haskell.org/ghc/head.hackage/commit/$commit" build_repository_blurb >repo/cabal.project.local cat >repo/ci.html <<EOF <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" /> <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" media="screen"> <script type="text/javascript" src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"></script> <script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script> <script src="scripts/imgViewer2.min.js"></script> <title>head.hackage</title> </head> <body> <section class="container"> <h1 class="title">head.hackage build results</h1> <p>This page summarizes the build dependency graph from the continuous integration build of <code>head.hackage</code> commit <a href="$commit_url"><code>$commit</code></a>. <img id="graph" width="80%" height="80%" src="summary.dot.svg"> <script> (function($) { \$("\#graph").imgViewer2(); })($); </script> </body> </html> EOF mkdir -p repo/scripts curl https://raw.githubusercontent.com/waynegm/imgViewer2/master/dist/imgViewer2.min.js \ > repo/scripts/imgViewer2.min.js cat >repo/index.html <<EOF <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <title>head.hackage</title> </head> <body> <section class="container"> <h1 class="title">head.hackage</h1> <p>This is a Haskell package repository containing patched packages from <a href="https://hackage.haskell.org/">Hackage</a> for use with <a href="https://gitlab.haskell.org/ghc/ghc">GHC</a> prereleases. <p>The source of this package repository is at <a href="https://gitlab.haskell.org/ghc/head.hackage">gitlab.haskell.org/ghc/head.hackage</a>. <p>To use package repository with <code>cabal-install</code> add the following to your project's <code>cabal.project.local</code> and run <code>cabal v2-update</code>: (consider using <code>scripts/head.hackage.sh update</code> as <code>v2-update</code> is broken, <a href="https://github.com/haskell/cabal/issues/5952">Cabal bug #5952</a>) <pre><code> $(cat repo/cabal.project.local) </code></pre> <p>Finally, you may want to add the <a href="cabal.constraints">constraints</a> to your project to ensure that cabal chooses the patched releases. <p>If you find a package that doesn't build with a recent GHC pre-release see the <a href="https://gitlab.haskell.org/ghc/head.hackage#adding-a-patch">contributor documentation</a> for instructions on how to contribute a patch. <p>If you encounter other trouble refer to the <a href="https://gitlab.haskell.org/ghc/head.hackage">head.hackage documentation</a> or <a href="https://gitlab.haskell.org/ghc/head.hackage/issues">let us know</a>. <p>You might also be interested in referring to the <a href="ci.html">CI build results</a> of the build that gave rise to this repository. <p><code>head.hackage</code> commit: <a href="$commit_url"><code>$commit</code></a> </section> </body> </html> EOF } build_constraints() { head-hackage-ci make-constraints $PATCHES } # Build the hackage repository build_repo() { # hackage-repo-tool bootstrap fails unless there is at least one package in the # repo. Seed things with acme-box. cabal update cabal fetch acme-box-0.0.0.0 mkdir -p repo/package cp $HOME/.cabal/packages/hackage.haskell.org/acme-box/0.0.0.0/acme-box-0.0.0.0.tar.gz repo/package mkdir -p tmp cp -R $PATCHES tmp/patches hackage-repo-tool bootstrap --keys=./keys --repo=./repo mkdir -p template tmp/patches.cache tool \ --patches=./tmp/patches \ --repo-cache=./cache \ --keys=./keys \ --repo-name=head.hackage \ --template=template \ ./repo build_constraints > repo/cabal.constraints build_index rm -R tmp } case $1 in gen-keys) gen_keys_tarball ;; extract-keys) extract_keys_tarball ;; build-repo) build_repo ;; build-constraints) build_constraints ;; build-repository-blurb) build_repository_blurb ;; build-index) build_constraints > repo/cabal.constraints build_index ;; *) echo "error: Unknown command $1." echo echo "Usage: $0 [command]" echo echo "Commands:" echo " gen-keys" echo " extract-keys" echo " build-repo" echo " build-constraints" echo " build-repository-blurb" echo " build-index" exit 1 ;; esac