# 在你的 Github Actions 中添加一个 PostgreSQL 用于测试

- Link: https://www.ixiqin.com/2024/03/25/add-a-postgresql-to-your-github-actions-for-testing/
- Published: 2024-03-25T06:00:00+08:00
- Author: 白宦成

在开发应用的时候，我们会选择使用 PostgreSQL 作为数据库进行开发，但在 Github Actions
环境下，默认是没有 PostgreSQL 作为数据库后端的，这个时候如果你想要测试一些和数据
库相关的逻辑，就不得不面临两个选择：

 1. 使用一个和生产环境无关的数据库，比如 SQLite。
 2. 在 Github Actions 当中添加一个 PostgreSQL。

前者是大多数常规的做法，大概率也不会出现什么问题（毕竟作为 CURD 仔，我们用的大部分
时候都是一些 ORM，很少裸写 SQL），不过依然存在一些概率是你写了一些 PostgreSQL Only
的 Query 无法覆盖到测试。

另外就是本文的核心了：**在你的 Github Actions 当中添加一个 PostgreSQL**。

## Github Actions Service

想要实现这个效果，我们依赖了 [Github Actions Service Containers](https://docs.github.com/en/actions/using-containerized-services/about-service-containers)
这个能力。

> 服务容器是 Docker 容器，以简便、可携带的方式托管您可能需要在工作流程中测试或操作
> 应用程序的服务。 例如，您的工作流程可能必须运行需要访问数据库和内存缓存的集成测试。
> 您可以为工作流程中的每个作业配置服务容器。 GitHub 为工作流中配置的每个服务创建
> 一个新的 Docker 容器，并在作业完成后销毁该服务容器。 作业中的步骤可与属于同一作业
> 的所有服务容器通信。 但是，你不能在组合操作中创建和使用服务容器。
>  GitHub

你可以选择你需要运行测试的环境中，找到对应的 Job，并在 Job 下新增一个 services ，
即可为你的 job 设定一个依赖的服务容器，它可能是数据库 、 缓存之类的。比如我这里用
的就是 PostgreSQL。

我的 Github Actions 完整参考：

 * services 是我运行的服务容器。
 * steps 是我的真正的测试流程。

    ```php
    name: Django CI

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

    env:
      DEBUG: true
      SECRET_KEY: django-insecure-github-actions
      DB_NAME: postgres
      DB_USER: postgres
      DB_PASSWORD: postgres
      DB_HOST: localhost
      DB_PORT: 5432

    jobs:
      build:
        runs-on: ubuntu-latest
        services:
          postgres:
            image: postgres
            env:
              POSTGRES_PASSWORD: postgres
            # Set health checks to wait until postgres has started
            options: >-
              --health-cmd pg_isready
              --health-interval 10s
              --health-timeout 5s
              --health-retries 5
            ports:
              - 5432:5432

        strategy:
          max-parallel: 4
          matrix:
            python-version: [3.12]

        steps:
        - uses: actions/checkout@v3
        - name: Set up Python ${{ matrix.python-version }}
          uses: actions/setup-python@v3
          with:
            python-version: ${{ matrix.python-version }}
        - name: Install Dependencies
          run: |
            python -m pip install --upgrade pip
            pip install -r requirements.txt
        - name: Run Tests
          run: |
            python manage.py test
    Code language: PHP (php)
    ```
