Skip to content

Commit

Permalink
Build and deploy documentation to GitHub pages
Browse files Browse the repository at this point in the history
  • Loading branch information
jorisdral committed Aug 28, 2023
1 parent 8ce77e1 commit f5c9115
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 9 deletions.
122 changes: 122 additions & 0 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Build and deploy documentation to pages

on:
push:
branches: [ "main" ]
pull_request:
workflow_dispatch:

permissions:
contents: read

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false

jobs:
# Sources
# * https://github.com/haskell/actions/tree/v2/setup#model-cabal-workflow-with-caching
# * https://haskell-haddock.readthedocs.io/en/latest/multi-components.html
# * https://github.com/input-output-hk/ouroboros-consensus/blob/b0a6f9148d3c3783cb9980c756162426f8066471/.github/workflows/ci.yml
# * https://github.com/input-output-hk/ouroboros-consensus/blob/4ff9aa5596598bb3681864b830c8a33e294d9bfe/scripts/docs/haddocks.sh
build-documentation:
name: Build documentation

runs-on: ubuntu-latest

strategy:
fail-fast: false

env:
ghc: "9.2.8"
cabal: "3.10.1.0"
os: ubuntu-latest"

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Setup Haskell
id: setup-haskell
uses: haskell/actions/setup@v2
with:
ghc-version: ${{ env.ghc }}
cabal-version: ${{ env.cabal }}
cabal-update: true

- name: Configure the build
run: |
cabal configure --disable-tests --disable-benchmarks --enable-documentation
cabal build all --dry-run
# The last step generates dist-newstyle/cache/plan.json for the cache key.

- name: Cache cabal store
uses: actions/cache@v3
env:
cache-name: documentation-cabal-store
with:
path: ${{ steps.setup-haskell.outputs.cabal-store }}
key: ${{ runner.os }}-${{ env.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
restore-keys: |
${{ runner.os }}-${{ env.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
${{ runner.os }}-${{ env.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-
${{ runner.os }}-${{ env.ghc }}-${{ env.cache-name }}-
- name: Build haddocks
run: |
./scripts/haddocks.sh
tar vzcf haddocks.tgz ./docs/haddocks
- name: Upload haddocks as an artifact
uses: actions/upload-artifact@v3
with:
name: haddocks
path: haddocks.tgz
retention-days: 1


deploy-documentation:
name: Deploy documentation to GitHub Pages

needs: build-documentation

runs-on: ubuntu-latest

strategy:
fail-fast: false

# https://github.com/actions/deploy-pages
permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Setup Pages
uses: actions/configure-pages@v3

- name: Download haddocks artifact
uses: actions/download-artifact@v3
with:
name: haddocks

- name: Unpack haddocks artifact
run: |
tar vzxf haddocks.tgz
- name: Upload haddocks artifact to pages
uses: actions/upload-pages-artifact@v2
with:
path: ./docs

- name: Deploy to GitHub pages
id: deployment
uses: actions/deploy-pages@v2
12 changes: 6 additions & 6 deletions .github/workflows/haskell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ jobs:
path: ${{ steps.setup-haskell.outputs.cabal-store }}
key: ${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
restore-keys: |
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-
${{ runner.os }}-${{ matrix.ghc }}-
${{ runner.os }}-
- name: Install cabal dependencies
run: cabal build --only-dependencies --enable-tests --enable-benchmarks all
Expand Down Expand Up @@ -107,9 +107,9 @@ jobs:
path: ${{ steps.setup-haskell.outputs.cabal-store }}
key: ${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
restore-keys: |
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-
${{ runner.os }}-${{ matrix.ghc }}-
${{ runner.os }}-
- name: Install stylish-haskell
run: cabal install stylish-haskell --constraint 'stylish-haskell == 0.14.4.0'
Expand Down Expand Up @@ -166,9 +166,9 @@ jobs:
path: ${{ steps.setup-haskell.outputs.cabal-store }}
key: ${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
restore-keys: |
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-
${{ runner.os }}-${{ matrix.ghc }}-${{ env.cache-name }}-
${{ runner.os }}-${{ matrix.ghc }}-
${{ runner.os }}-
- name: Install cabal-fmt
run: cabal install cabal-fmt --constraint 'cabal-fmt == 0.1.6'
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ cabal.project.local
cabal.project.local~
.HTF/
.ghc.environment.*

# Documentation
./docs/haddocks
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
[![Haskell CI](https://img.shields.io/github/actions/workflow/status/input-output-hk/fs-sim/haskell.yml?label=Build&style=for-the-badge)](https://github.com/input-output-hk/fs-sim/actions/workflows/haskell.yml)
[![handbook](https://img.shields.io/badge/policy-Cardano%20Engineering%20Handbook-informational?style=for-the-badge)](https://input-output-hk.github.io/cardano-engineering-handbook)

# fs-sim

[![handbook](https://img.shields.io/badge/policy-Cardano%20Engineering%20Handbook-informational)](https://input-output-hk.github.io/cardano-engineering-handbook)
[![Haskell CI](https://img.shields.io/github/actions/workflow/status/input-output-hk/fs-sim/haskell.yml?label=Build)](https://github.com/input-output-hk/fs-sim/actions/workflows/haskell.yml)
[![Documentation](https://img.shields.io/github/actions/workflow/status/input-output-hk/fs-sim/documentation.yml?label=Documentation%20build)](https://github.com/input-output-hk/fs-sim/actions/workflows/documentation.yml)


The [`fs-sim`](./fs-sim/README.md) package provides a filesystem simulator that
facilitates simulation of errors and file corruption. This simulator is
specially useful for testing purposes, and works well in conjunction with
Expand Down
117 changes: 117 additions & 0 deletions scripts/haddocks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/bin/bash
#
# This script is based on https://github.com/input-output-hk/ouroboros-consensus/blob/4ff9aa5596598bb3681864b830c8a33e294d9bfe/scripts/docs/haddocks.sh
#
# Build haddock documentation and an index for all projects in
# `fs-sim` repository.
#
# usage:
# ./scripts/docs/haddocks.sh directory [true|false]
#
# $1 - where to put the generated pages, this directory contents will be wiped
# out (so don't pass `/` or `./` - the latter will delete your 'dist-newstyle')
# (the default is './haddocks')
# $2 - whether to re-build haddocks with `cabal haddock` command or a component name
# (the default is true)
# $3 - cabal build directory
# (the default is "dist-newstyle")

set -euo pipefail

OUTPUT_DIR=${1:-"./docs/haddocks"}
REGENERATE=${2:-"true"}
BUILD_DIR=${3:-"dist-newstyle"}

# the directory containing this script
SCRIPTS_DIR=$(realpath $(dirname $(realpath $0)))

GHC_VERSION=$(ghc --numeric-version)
OS_ARCH="$(cat dist-newstyle/cache/plan.json | jq -r '.arch + "-" + .os' | head -n 1 | xargs)"

# we don't include `--use-index` option, because then quickjump data is not
# generated. This is not ideal, but there is no way to generate only top level
# `doc-index.html` file. With this approach we get:
# * `doc-index.json` and `doc-index.html` per package
# * we can generate top level `doc-index.json` (which will only work at the top
# level).
# * we could ammend package level `doc-index.json` files, but it's enough ...
# this should be fixed upstream.
HADDOCK_OPTS=(
--builddir "${BUILD_DIR}"
--disable-optimization
--haddock-all
--haddock-internal
--haddock-html
--haddock-quickjump
--haddock-hyperlink-source
--haddock-option "--show-all"
--haddock-option "--use-unicode"
)

# build documentation of all modules
if [ ${REGENERATE} == "true" ]; then
cabal haddock "${HADDOCK_OPTS[@]}" all
elif [ ${REGENERATE} != "false" ]; then
cabal haddock "${HADDOCK_OPTS[@]}" ${REGENERATE}
fi

if [[ !( -d ${OUTPUT_DIR} ) ]]; then
mkdir -p ${OUTPUT_DIR}
fi

# make all files user writable
chmod -R u+w "${OUTPUT_DIR}"

# copy the new docs
for dir in $(ls "${BUILD_DIR}/build/${OS_ARCH}/ghc-${GHC_VERSION}"); do
package=$(echo "${dir}" | sed 's/-[0-9]\+\(\.[0-9]\+\)*//')
cp -r "${BUILD_DIR}/build/${OS_ARCH}/ghc-${GHC_VERSION}/${dir}/noopt/doc/html/${package}" ${OUTPUT_DIR}
# copy test packages documentation when it exists
if [ -d "${BUILD_DIR}/build/${OS_ARCH}/ghc-${GHC_VERSION}/${dir}/t" ]; then
for test_package in $(ls "${BUILD_DIR}/build/${OS_ARCH}/ghc-${GHC_VERSION}/${dir}/t"); do
if [ -d "${BUILD_DIR}/build/${OS_ARCH}/ghc-${GHC_VERSION}/${dir}/t/${test_package}/noopt/doc/html/${package}/${test_package}" ]; then
cp -r "${BUILD_DIR}/build/${OS_ARCH}/ghc-${GHC_VERSION}/${dir}/t/${test_package}/noopt/doc/html/${package}/${test_package}" "${OUTPUT_DIR}/${package}-${test_package}"
fi
done
fi
done


# --read-interface options
interface_options () {
for package in $(ls "${OUTPUT_DIR}"); do
if [[ -d "${OUTPUT_DIR}/${package}" ]]; then
# take the first haddock file found.
# there should be only one but the filename is the name of the main pacakage
# and can differ from the name of the enclosing directory
haddock_file=$(ls -1 ${OUTPUT_DIR}/${package}/*.haddock | head -1)
echo "--read-interface=${package},${haddock_file}"
fi
done
}

# Generate top level index using interface files
#
haddock \
-o ${OUTPUT_DIR} \
--title "fs-api and fs-sim" \
--package-name "fs-api and fs-sim" \
--gen-index \
--gen-contents \
--quickjump \
$(interface_options)

# Assemble a toplevel `doc-index.json` from package level ones.
#
echo "[]" > "${OUTPUT_DIR}/doc-index.json"
for file in $(ls $OUTPUT_DIR/*/doc-index.json); do
project=$(basename $(dirname $file));
jq -s \
".[0] + [.[1][] | (. + {link: (\"${project}/\" + .link)}) ]" \
"${OUTPUT_DIR}/doc-index.json" \
${file} \
> /tmp/doc-index.json
mv /tmp/doc-index.json "${OUTPUT_DIR}/doc-index.json"
done

echo "Generated documentation in ${OUTPUT_DIR}"

0 comments on commit f5c9115

Please sign in to comment.