Akatama's Slice of the Internet

The Puzzle of Pull Requests: Testing Calibre-Web in IIAB with GitHub Actions Contexts

By Jimmy Lindsey

Sept. 3, 2025 | Categories: devops, IIAB, open-source, ci-cd

Back in July, I got a message from Adam over at Internet-in-a-Box. There were some new developers who started work on iiab/calibre-web and he asked if I could set up a GitHub Actions workflow to automatically test the installation inside IIAB. If you are not familiar, IIAB is an offline server for educational resources and Calibre-Web is a web application for browsing and reading eBooks and videos. At first it seemed simple, but we quickly ran into a tricky problem. How do you make sure a workflow actually tests the pull requests branch instead of quietly defaulting back to master? What followed was a mix of trial, error and learning how GitHub Actions contexts really behave.

Setting up the Smoke Test

The goal is to smoke test Calibre-Web changes inside of IIAB, which requires:

  1. A way to tell IIAB which repo and branch to grab for the PR
  2. Grab the current branch if the test is being run directly on a branch

Luckily, Adam let me know that IIAB could already be configured to install Calibre-Web from a different repo and branch. Normally to install Calibre-Web, you would provide the first two lines below, with the additional configuration being the two lines after.

calibreweb_install: True

calibreweb_enabled: True

# works out to https://github.com/Akatama/calibre-web, which is my fork
calibreweb_repo_url: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY

# works out to: smoke_test
calibreweb_version: $GITHUB_REF_NAME

This satisfied requirement 2 by running the smoke_test branch of my fork, but PR runs still defaulted to iiab/calibre-web’s master branch. This meant PR changes weren’t actually tested, giving a false sense that everything was fine.

Adam and I tried a lot of things that didn’t help. In the end, Adam did more research into GitHub Actions contexts. With this, Adam was able to come up with a workable solution that solved both requirements.

      - name: Set up /etc/iiab/local_vars.yml
        run: |
          echo "calibreweb_install: True" > local_vars.yml

          echo "calibreweb_enabled: True" >> local_vars.yml

          # Solves requirement 1
          # Here's where we make sure PRs use the right repo and branch instead of the master branch of iiab/calibre-web
          if [ "${{ github.event_name }}" == "pull_request" ]; then
            echo "calibreweb_repo_url: $GITHUB_SERVER_URL/${{ github.event.pull_request.head.repo.owner.login }}/${{ github.event.repository.name }}" >> local_vars.yml
            echo "calibreweb_version: $GITHUB_HEAD_REF" >> local_vars.yml

          # Solves requirement 2
          # works for both push and workflow_dispatch
          else
            echo "calibreweb_repo_url: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY" >> local_vars.yml
            echo "calibreweb_version: $GITHUB_REF_NAME" >> local_vars.yml
          fi

The first two lines are the same as what I showed above.

The if statement checks whether the workflow is running on a pull request. If it is, then append the following to the local_vars.yml file:

  1. The $GITHUB_SERVER_URL (which is always https://github.com) with the creator of the pull request's username and the repository name. The result is the URL of the repo for the fork, like https://github.com/Akatama/calibre-web.
  2. It takes the $GITHUB_HEAD_REF, which in this case would be the name of the branch on the fork, like smoke_test

This resolves requirement 1.

If it isn't a pull request, then it grabs the URL of the repo and the branch name as shown in the original code block, which as I already stated resolves requirement 2.

The Full Workflow

After the install was done, we wanted to run any Calibre-Web tests so we could verify the application was working appropriately. Here is the complete workflow broken up into chunks. You can also see the full version here.

First we clone the repo and move it to the /opt/iiab/iiab directory.

      - name: Clean clone to /opt/iiab/iiab (chmod permissions preserved)
        run: |
          sudo git clone <https://github.com/iiab/iiab>    # in $GITHUB_WORKSPACE == /home/runner/work/calibre-web/calibre-web
          sudo mkdir /opt/iiab
          sudo mv iiab /opt/iiab

Here we're setting up the local_vars.yml configuration file, which tells IIAB what to install. We configure it to install only Calibre-Web, then move it to /etc/iiab.

      # PR logic: use fork + branch from PR, otherwise fall back to current repo + branch
      - name: Set up /etc/iiab/local_vars.yml
        run: |
          echo "calibreweb_install: True" > local_vars.yml    # in $GITHUB_WORKSPACE == /home/runner/work/calibre-web/calibre-web
          echo "calibreweb_enabled: True" >> local_vars.yml

          if [ "${{ github.event_name }}" == "pull_request" ]; then
            echo "calibreweb_repo_url: $GITHUB_SERVER_URL/${{ github.event.pull_request.head.repo.owner.login }}/${{ github.event.repository.name }}" >> local_vars.yml
            echo "calibreweb_version: $GITHUB_HEAD_REF" >> local_vars.yml

          else # works for both push and workflow_dispatch
            echo "calibreweb_repo_url: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY" >> local_vars.yml
            echo "calibreweb_version: $GITHUB_REF_NAME" >> local_vars.yml
          fi

          cat >> local_vars.yml << EOF
          nodocs: True
          kolibri_install: False
          kolibri_enabled: False
          kiwix_install: False
          kiwix_enabled: False
          # ...all other services are not enabled or installed, cut for length 
          EOF

          sudo mkdir /etc/iiab
          sudo mv local_vars.yml /etc/iiab
          cat /etc/iiab/local_vars.yml

Next install Ansible and then IIAB.

      - run: sudo /opt/iiab/iiab/scripts/ansible    # Install Ansible

      - run: sudo ./iiab-install                    # Install IIAB!
        working-directory: /opt/iiab/iiab/

Next, preparation for integration tests:

  1. Install Firefox
  2. Activate the already existing Python virtual environment
  3. Install the dependencies in integration-tests-requirements.txt. Note that the dependencies in requirements.txt were already installed in this virtual environment by IIAB.
      # Install Firefox, activate venv, and install test dependencies
      - name: Install Firefox
        uses: browser-actions/setup-firefox@v1

      - run: firefox --version

      - name: Activate virtual environment
        run: source bin/activate
        working-directory: /usr/local/calibre-web-py3

      - name: Install Python dependencies for testing
        uses: py-actions/py-dependency-install@v4
        with:
          path: /usr/local/calibre-web-py3/integration-tests-requirements.txt

Last, we run the integration tests. Note that I added the -p no:cacheprovider argument to Pytest to suppress a harmless cache warning. Since this is a fresh install, there is nothing useful for Pytest to cache anyway.

      - name: Execute Integration Tests for Firefox
        # Suppress Pytest cache warning with -p no:cacheprovider
        run: pytest -p no:cacheprovider -s --splinter-webdriver firefox --splinter-headless
        working-directory: /usr/local/calibre-web-py3

As mentioned before, we have only two integration tests. When we add more tests, we'll need to decide if they're worth running in this smoke test. At the moment, both tests take less than 30 seconds, so it's not an issue.

Conclusion

In the end, we were able to get a proper smoke test set up for any future changes to Calibre-Web. While I have some experience with GitHub Actions, I was not familiar with the context variables. Normally, pull requests run tests on the PR branch by default, but the complexity of this workflow made it necessary to use contexts. If nothing else, this little adventure proves that sometimes the simplest requests make for the best deep dives. Who knew smoke tests could spark so much smoke?