ci: add GitHub Actions

Change-Id: I586ea4dd76e5f4b3a9effc65402b6b4285a30faf
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..e7188d2
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,57 @@
+name: CI
+on:
+  push:
+  pull_request:
+  workflow_dispatch:
+
+jobs:
+  linux:
+    name: ${{ matrix.compiler }} on ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        compiler: [g++-8, g++-9, g++-10, g++-11,
+                   clang++-7, clang++-8, clang++-9, clang++-10, clang++-11, clang++-12]
+        os: [ubuntu-20.04]
+        include:
+          - compiler: g++-7
+            os: ubuntu-18.04
+          - compiler: clang++-5.0
+            os: ubuntu-18.04
+          - compiler: clang++-6.0
+            os: ubuntu-18.04
+    runs-on: ${{ matrix.os }}
+    env:
+      CXX: ${{ matrix.compiler }}
+      NODE_LABELS: Linux Ubuntu
+      WAF_JOBS: 2
+    steps:
+      - name: Install C++ compiler
+        run: |
+          sudo apt-get -qy install ${CXX/clang++/clang}
+          ${CXX} --version
+      - name: Checkout
+        uses: actions/checkout@v2
+      - name: Build and test
+        run: ./.jenkins
+
+  macos:
+    name: Xcode ${{ matrix.xcode }} on ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        xcode: ['11.3', '11.7', '12.4']
+        os: [macos-10.15]
+    runs-on: ${{ matrix.os }}
+    env:
+      NODE_LABELS: OSX OSX-10.15
+      WAF_JOBS: 3
+    steps:
+      - name: Set up Xcode
+        uses: maxim-lobanov/setup-xcode@v1
+        with:
+          xcode-version: ${{ matrix.xcode }}
+      - name: Checkout
+        uses: actions/checkout@v2
+      - name: Build and test
+        run: ./.jenkins
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000..ea32653
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,33 @@
+name: Docs
+on:
+  push:
+  pull_request:
+  workflow_dispatch:
+
+jobs:
+  build:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [macos-10.15, ubuntu-20.04]
+    runs-on: ${{ matrix.os }}
+    env:
+      JOB_NAME: Docs
+      WAF_JOBS: 3
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v2
+      - name: Install dependencies
+        run: |
+          case ${RUNNER_OS} in
+            Linux) export NODE_LABELS="Linux Ubuntu Ubuntu-20.04" ;;
+            macOS) export NODE_LABELS="OSX OSX-10.15" ;;
+          esac
+          find .jenkins.d/ -type f -name '[1-9]*.sh' -exec chmod -x '{}' +
+          ./.jenkins
+      - name: Build documentation
+        run: |
+          ./waf --color=yes configure
+          ./waf --color=yes build --targets=version.hpp
+          ./waf --color=yes build --targets=manpages
+          ./waf --color=yes docs
diff --git a/.jenkins b/.jenkins
index bc1c847..1a12b6c 100755
--- a/.jenkins
+++ b/.jenkins
@@ -14,8 +14,10 @@
 for file in .jenkins.d/*; do
     [[ -f $file && -x $file ]] || continue
 
-    if [[ -n $TRAVIS ]]; then
-        label=$(basename "$file" | sed -E 's/[[:digit:]]+-(.*)\..*/\1/')
+    label=$(basename "$file" | sed -E 's/[[:digit:]]+-(.*)\..*/\1/')
+    if [[ -n $GITHUB_ACTIONS ]]; then
+        echo "::group::${label}"
+    elif [[ -n $TRAVIS ]]; then
         echo -ne "travis_fold:start:${label}\r"
         echo -ne "travis_time:start:${label}\r"
         start=$(nanos)
@@ -24,7 +26,9 @@
     echo "\$ $file"
     "$file"
 
-    if [[ -n $TRAVIS ]]; then
+    if [[ -n $GITHUB_ACTIONS ]]; then
+        echo "::endgroup::"
+    elif [[ -n $TRAVIS ]]; then
         finish=$(nanos)
         echo -ne "travis_time:end:${label}:start=${start},finish=${finish},duration=$((finish-start)),event=${label}\r"
         echo -ne "travis_fold:end:${label}\r"
diff --git a/.jenkins.d/00-deps.sh b/.jenkins.d/00-deps.sh
index 1f004f5..c021e54 100755
--- a/.jenkins.d/00-deps.sh
+++ b/.jenkins.d/00-deps.sh
@@ -6,10 +6,13 @@
     if has OSX-10.13 $NODE_LABELS || has OSX-10.14 $NODE_LABELS; then
         FORMULAE+=(python)
     fi
+    if [[ $JOB_NAME == *"Docs" ]]; then
+        FORMULAE+=(doxygen graphviz)
+    fi
 
-    if [[ -n $TRAVIS ]]; then
-        # Travis images come with a large number of pre-installed
-        # brew packages, don't waste time upgrading all of them
+    if [[ -n $GITHUB_ACTIONS || -n $TRAVIS ]]; then
+        # GitHub Actions and Travis images come with a large number of
+        # pre-installed packages. Don't waste time upgrading all of them.
         brew list --versions "${FORMULAE[@]}" || brew update
         for FORMULA in "${FORMULAE[@]}"; do
             brew list --versions "$FORMULA" || brew install "$FORMULA"
@@ -23,14 +26,24 @@
         brew cleanup
     fi
 
+    if [[ $JOB_NAME == *"Docs" ]]; then
+        pip3 install --upgrade --upgrade-strategy=eager sphinx sphinxcontrib-doxylink
+    fi
+
 elif has Ubuntu $NODE_LABELS; then
     sudo apt-get -qq update
-    sudo apt-get -qy install g++ pkg-config python3-minimal \
+    sudo apt-get -qy install build-essential pkg-config python3-minimal \
                              libboost-all-dev libssl-dev libsqlite3-dev
 
-    if [[ $JOB_NAME == *"code-coverage" ]]; then
-        sudo apt-get -qy install gcovr lcov
-    fi
+    case $JOB_NAME in
+        *code-coverage)
+            sudo apt-get -qy install gcovr lcov
+            ;;
+        *Docs)
+            sudo apt-get -qy install doxygen graphviz python3-pip
+            pip3 install --user --upgrade --upgrade-strategy=eager sphinx sphinxcontrib-doxylink
+            ;;
+    esac
 
 elif has CentOS-8 $NODE_LABELS; then
     sudo dnf -y install gcc-c++ libasan pkgconf-pkg-config python3 \
diff --git a/docs/INSTALL.rst b/docs/INSTALL.rst
index dda1924..bedf609 100644
--- a/docs/INSTALL.rst
+++ b/docs/INSTALL.rst
@@ -44,7 +44,7 @@
 
     In a terminal, enter::
 
-        sudo apt install g++ pkg-config python3-minimal libboost-all-dev libssl-dev libsqlite3-dev
+        sudo apt install build-essential pkg-config python3-minimal libboost-all-dev libssl-dev libsqlite3-dev
 
 - On **CentOS** and **Fedora**
 
@@ -93,7 +93,7 @@
   .. code-block:: sh
 
     sudo apt install doxygen graphviz python3-pip
-    sudo pip3 install sphinx sphinxcontrib-doxylink
+    pip3 install --user sphinx sphinxcontrib-doxylink
 
 - On **CentOS** and **Fedora**:
 
@@ -108,7 +108,7 @@
   .. code-block:: sh
 
     brew install doxygen graphviz
-    sudo pip install sphinx sphinxcontrib-doxylink
+    sudo pip3 install sphinx sphinxcontrib-doxylink
 
 - On **FreeBSD**: