brainsteam.co.uk/brainsteam/content/posts/2024/01/20/Gitea_Forgejo Actions and P...

5.1 KiB

categories date draft preview tags title type url
Software Development
2024-01-20 14:05:07 false /social/90570600f411b5753ef9dc31b3c46e57c552fc5719219edce9bc16d5c16d0153.png
ci
django
docker
gitea
Gitea/Forgejo Actions and PostgreSQL Tests posts /2024/01/20/gitea-forgejo-actions-and-postgresql-tests/

I am building a recipe app in django and I want to be able to test the app within the CI pipelines when I push to my self-hosted gitea repository.

The Problem

Github actions already has a postgresql action but this crashes when you run Gitea's Action runner via docker:

initdb: error: cannot be run as root
Please log in (using, e.g., "su") as the (unprivileged) user that will own the server process.

This is because, by default, docker containers don't really enforce users and permissions in the same way that systems installed in the operating system usually do and the action tries to run a load of stuff with the root user that should probably be run under the postgres system user account.

Finding Another Approach

In gitea we can specify the underlying container that we want the action to run in (which is different to github where actions typically run in full VMs rather than containers). Although the vanilla gitea container is reasonably good, I replaced it with catthehacker/ubuntu:act-latest so that I could get the setup pdm action to work. This container effectively contains a basic set of stuff you'd find in a default ubuntu install including apt for managing packages. Ubuntu ships with a PostgreSQL server package so I went ahead and installed it which also initialises the relevant data files and service user accounts inside the container.

Then, I started the service with service postgresql start. Normally this would be a weird thing to do inside a docker container since best practice is typically to have a separate container per service. However, for testing purposes it's probably ok.

The next step is to set a password for the postgres user which is used by the django app to log in and do the tests. We can use the psql command to do this and we use sudo -u postgres to authenticate against the postgres user before the password is set.

Our final gitea actions yaml looks something like this:

name: Run Tests
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
on: [push]

jobs:
  run_tests:
    runs-on: ubuntu-latest
    container: catthehacker/ubuntu:act-latest
    steps:
      - name: Checkout Codebase
        uses: actions/checkout@v3


      - name: Configure and install postgres
        run: |
         apt update
         apt install -y postgresql
         service postgresql start
         sudo -u postgres -s psql -U postgres -d postgres -c "alter user postgres with password 'test123';"


      - uses: pdm-project/setup-pdm@v3
        with:
          python-version: 3.10
          token: ${{ secrets.GH_TOKEN }}


      - name: Install dependencies
        run: cd ${{ gitea.workspace }} && pdm install 
    

      - name: Run Django tests
        env:
          DB_HOST: 127.0.0.1
          DB_NAME: gastronaut
          DB_USER: postgres
          DB_PASSWORD: test123

        run: |
          cd ${{ gitea.workspace }} && pdm run manage.py test
      

Hopefully this will work out of the box. The whole thing is pretty efficient with a good internet connection, my run taks just under 2 minutes with about 25 seconds needed to install and configure the postgres db:

a screenshot of the gitea actions CI log for the flow set out above and with indicative timings. The whole run takes 1m 47s and the postgres config step takes 25s