Refactor build matrix (#43)

Rework and simplify the build through the following enhancements:

* Build against multiple Erlang/OTP versions

* Merge Ubuntu and Windows into a matrix build

* Simplify config by using default fdb.cluster

The last one is a bit obvious in hindsight. We don't need to be passing
around custom overrides for the fdb.cluster file location; all we really
need to do is just trust FDB to figure it out on each platform. To do this
we allow for setting the test_cluster_file env to `system_default` instead
of a path to a specific cluster file.
diff --git a/.devcontainer/docker-compose.yaml b/.devcontainer/docker-compose.yaml
index 1199af7..79a310b 100644
--- a/.devcontainer/docker-compose.yaml
+++ b/.devcontainer/docker-compose.yaml
@@ -13,16 +13,9 @@
       # This needs to match the name of the FoundationDB service below
       FDB_COORDINATOR: fdb
 
-      # The location where the Dockerfile installs the FDB cluster file
-      # retrieved from the `fdb` image. CouchDB looks for the cluster file in
-      # this location by default. If you want to install it somewhere else you
-      # you need to change "[erlfdb] cluster_file" and ERL_ZFLAGS to match.
-      FDB_CLUSTER_FILE: /usr/local/etc/foundationdb/fdb.cluster
-
-      # The test suite will default to trying to start its own fdbserver
-      # process. This environment variable tells it to use the fdbserver
-      # running in the `fdb` image instead. Quite a hacky solution.
-      ERL_ZFLAGS: "-erlfdb test_cluster_file <<\\\"/usr/local/etc/foundationdb/fdb.cluster\\\">>"
+      # This profile ensures we use the FDB server in the sibling container
+      # for the EUnit test suite
+      REBAR_PROFILE: devcontainer
 
     volumes:
       # Mounts the project folder to '/usr/src/erlfdb'. The target path inside
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 844f9a7..239dce7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,49 +10,14 @@
 
 jobs:
 
-  build_on_linux:
+  otp_fdb_matrix:
     strategy:
       matrix:
-        fdb-version: ['6.2.30', '6.3.22']
+        otp-version: ['22', '23', '24']
+        fdb-version: ['6.3.22']
     runs-on: ubuntu-latest
-    steps:
-      - name: Check out repository code
-        uses: actions/checkout@v2
-        with:
-          persist-credentials: false
-          submodules: recursive
-      - name: Install FoundationDB
-        env:
-          FDB_VERSION: ${{ matrix.fdb-version }}
-        run: |
-          wget https://www.foundationdb.org/downloads/${FDB_VERSION}/ubuntu/installers/foundationdb-clients_${FDB_VERSION}-1_amd64.deb
-          wget https://www.foundationdb.org/downloads/${FDB_VERSION}/ubuntu/installers/foundationdb-server_${FDB_VERSION}-1_amd64.deb
-          sudo dpkg -i foundationdb-clients_${FDB_VERSION}-1_amd64.deb
-          sudo dpkg -i foundationdb-server_${FDB_VERSION}-1_amd64.deb
-      - name: Setup Erlang
-        uses: ./.github/actions/setup-beam
-        with:
-          otp-version: '24'
-          rebar3-version: '3.17'
-      - name: Enforce coding style
-        run: rebar3 fmt --check
-      - name: Compile
-        run: rebar3 compile
-      - name: EUnit tests
-        run: rebar3 eunit
-      - name: Setup tmate session on job failure
-        uses: ./.github/actions/tmate
-        if: ${{ failure() }}
-        with:
-          limit-access-to-actor: true
-
-  build_on_windows:
-    strategy:
-      matrix:
-        # Windows builds are not being published beyond 6.3.9 right now
-        fdb-version: ['6.2.30', '6.3.9']
-    runs-on: windows-latest
     env:
+      FDB_VERSION: ${{ matrix.fdb-version }}
       # Set to 1 for verbose rebar3 logging
       DEBUG: 0
       # Set to 1 for even more verbose rebar3 logging
@@ -63,30 +28,87 @@
         with:
           persist-credentials: false
           submodules: recursive
+      - name: Setup Erlang
+        uses: ./.github/actions/setup-beam
+        with:
+          otp-version: ${{ matrix.otp-version }}
+          rebar3-version: '3.17'
       - name: Install FoundationDB
-        env:
-          FDB_VERSION: ${{ matrix.fdb-version }}
-        # Download FDB .msi, install it, and add FDB to the $env:Path for all future steps
         run: |
-          Set-PSDebug -Trace 1
-          Invoke-WebRequest -Uri https://www.foundationdb.org/downloads/$env:FDB_VERSION/windows/installers/foundationdb-$env:FDB_VERSION-x64.msi -OutFile foundationdb-$env:FDB_VERSION-x64.msi
-          msiexec /i foundationdb-$env:FDB_VERSION-x64.msi /passive
-          echo "c:/Program Files/foundationdb/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+          wget https://www.foundationdb.org/downloads/${FDB_VERSION}/ubuntu/installers/foundationdb-clients_${FDB_VERSION}-1_amd64.deb
+          wget https://www.foundationdb.org/downloads/${FDB_VERSION}/ubuntu/installers/foundationdb-server_${FDB_VERSION}-1_amd64.deb
+          sudo dpkg -i foundationdb-clients_${FDB_VERSION}-1_amd64.deb
+          sudo dpkg -i foundationdb-server_${FDB_VERSION}-1_amd64.deb
+      - name: Compile
+        run: rebar3 compile
+      - name: EUnit tests
+        run: rebar3 eunit
+      - name: Setup tmate session on job failure
+        uses: ./.github/actions/tmate
+        if: ${{ failure() }}
+        with:
+          limit-access-to-actor: true
+
+  os_fdb_matrix:
+    strategy:
+      matrix:
+        # erlef/setup-beam action does not support macos yet
+        os: [ubuntu-latest, windows-latest]
+        fdb-version: ['6.2.30', '6.3.22']
+        # Windows builds are not being published beyond 6.3.9 right now
+        exclude:
+          - os: windows-latest
+            fdb-version: '6.3.22'
+        include:
+          - os: windows-latest
+            fdb-version: '6.3.9'
+    runs-on: ${{ matrix.os }}
+    env:
+      FDB_VERSION: ${{ matrix.fdb-version }}
+      # This profile uses the FDB server started in the "Install FoundationDB" step
+      # instead of starting another one (the code that manages the "local" FDB in the
+      # test suite is not designed with x-platform compatibility in mind)
+      REBAR_PROFILE: devcontainer
+      # Set to 1 for verbose rebar3 logging
+      DEBUG: 0
+      # Set to 1 for even more verbose rebar3 logging
+      DIAGNOSTIC: 0
+    steps:
+      - name: Check out repository code
+        uses: actions/checkout@v2
+        with:
+          persist-credentials: false
+          submodules: recursive
       - name: Setup Erlang
         uses: ./.github/actions/setup-beam
         with:
           otp-version: '24'
           rebar3-version: '3.17'
       - name: Setup MSVC toolchain
+        if: ${{ matrix.os == 'windows-latest' }}
         uses: ./.github/actions/msvc-dev-cmd
+      - name: Install FoundationDB (Ubuntu)
+        if: ${{ matrix.os == 'ubuntu-latest' }}
+        run: |
+          wget https://www.foundationdb.org/downloads/${FDB_VERSION}/ubuntu/installers/foundationdb-clients_${FDB_VERSION}-1_amd64.deb
+          wget https://www.foundationdb.org/downloads/${FDB_VERSION}/ubuntu/installers/foundationdb-server_${FDB_VERSION}-1_amd64.deb
+          sudo dpkg -i foundationdb-clients_${FDB_VERSION}-1_amd64.deb
+          sudo dpkg -i foundationdb-server_${FDB_VERSION}-1_amd64.deb
+      - name: Install FoundationDB (Windows)
+        if: ${{ matrix.os == 'windows-latest' }}
+        run: |
+          Set-PSDebug -Trace 1
+          Invoke-WebRequest -Uri https://www.foundationdb.org/downloads/$env:FDB_VERSION/windows/installers/foundationdb-$env:FDB_VERSION-x64.msi -OutFile foundationdb-$env:FDB_VERSION-x64.msi
+          msiexec /i foundationdb-$env:FDB_VERSION-x64.msi /passive
+          echo "c:/Program Files/foundationdb/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+      - name: Install FoundationDB (macOS)
+        if: ${{ matrix.os == 'macos-latest' }}
+        run: |
+          wget https://www.foundationdb.org/downloads/${FDB_VERSION}/macOS/installers/FoundationDB-${FDB_VERSION}.pkg
+          sudo installer -allowUntrusted -verboseR -pkg FoundationDB-${FDB_VERSION}.pkg -target /
       - name: Compile
         run: rebar3 compile
       - name: EUnit tests
-        env:
-          # This profile uses the FDB server started in the "Install FoundationDB" step
-          # instead of starting another one (the code that manages the "local" FDB in the
-          # test suite is not designed with x-platform compatibility in mind)
-          REBAR_PROFILE: win32_external_fdbserver
         run: rebar3 eunit
       - name: Setup tmate session on job failure
         uses: ./.github/actions/tmate
@@ -110,13 +132,8 @@
       foundationdb:
         image: foundationdb/foundationdb:6.3.18
     env:
-      # We could create a different profile that looks for fdb.cluster in the
-      # default /etc/foundationdb/ location, but for now we can just specify the
-      # custom location here
-      FDB_CLUSTER_FILE: /usr/local/etc/foundationdb/fdb.cluster
       # This profile just ensures we use the FDB server in the service container
       REBAR_PROFILE: devcontainer
-      DIAGNOSTIC: 1
     steps:
       - name: Create FDB cluster file
         env:
@@ -155,9 +172,8 @@
           COVERALLS_FLAG_NAME: bindingtest-${{ matrix.test-name }}-${{ matrix.api-version }}
         run: rebar3 as test coveralls send
 
-
-  finish:
-    needs: [build_on_linux, build_on_windows, binding_tester]
+  finalize_coverage_report:
+    needs: [binding_tester]
     runs-on: ubuntu-latest
     steps:
       - name: Finalize Coveralls report
diff --git a/devcontainer.config b/devcontainer.config
index d9356aa..b621b28 100644
--- a/devcontainer.config
+++ b/devcontainer.config
@@ -1,5 +1,5 @@
 [
     {erlfdb, [
-        {test_cluster_file, <<"/usr/local/etc/foundationdb/fdb.cluster">>}
+        {test_cluster_file, system_default}
     ]}
 ].
diff --git a/rebar.config b/rebar.config
index 34d277d..13baf96 100644
--- a/rebar.config
+++ b/rebar.config
@@ -25,11 +25,6 @@
         {eunit_opts, [
             {sys_config, "devcontainer.config"}
         ]}
-    ]},
-    {win32_external_fdbserver, [
-        {eunit_opts, [
-            {sys_config, "win32_external_fdbserver.config"}
-        ]}
     ]}
 ]}.
 
diff --git a/src/erlfdb_util.erl b/src/erlfdb_util.erl
index f0b8ff8..08ed4ff 100644
--- a/src/erlfdb_util.erl
+++ b/src/erlfdb_util.erl
@@ -47,6 +47,8 @@
     % Hack to ensure erlfdb app environment is loaded during unit tests
     ok = application:ensure_started(erlfdb),
     case application:get_env(erlfdb, test_cluster_file) of
+        {ok, system_default} ->
+            {ok, <<>>};
         {ok, ClusterFile} ->
             {ok, ClusterFile};
         undefined ->
diff --git a/win32_external_fdbserver.config b/win32_external_fdbserver.config
deleted file mode 100644
index 3ca1c6f..0000000
--- a/win32_external_fdbserver.config
+++ /dev/null
@@ -1,5 +0,0 @@
-[
-    {erlfdb, [
-        {test_cluster_file, <<"c:/ProgramData/foundationdb/fdb.cluster">>}
-    ]}
-].