Skip to content

Instantly share code, notes, and snippets.

@jefftriplett
Last active March 27, 2024 04:27
Show Gist options
  • Star 42 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save jefftriplett/d35e120ef9884bcff61c5ade0740f52d to your computer and use it in GitHub Desktop.
Save jefftriplett/d35e120ef9884bcff61c5ade0740f52d to your computer and use it in GitHub Desktop.
This is a good starting point for getting Python, Django, Postgres running as a service, pytest, black, and pip caching rolling with GitHub Actions.
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports: ['5432:5432']
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
python-version: 3.7
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
if: steps.cache.outputs.cache-hit != 'true'
- name: Test with black
run: |
python -m black --check .
- name: Test with pytest
env:
DATABASE_URL: 'postgres://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/postgres'
run: |
python -m pytest
name: docker-publish
on:
push:
branches:
- master
jobs:
docker:
name: Build and Publish Docker image
runs-on: ubuntu-latest
steps:
- name: Git - Get Sources
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Docker - Build
run: |
docker build . --file .docker/Dockerfile --tag changeme-web
- name: Docker - Login
run: |
echo ${{ secrets.GITHUB_TOKEN }} | docker login docker.pkg.github.com --username ${{ github.actor }} --password-stdin
- name: Docker - Tag
run: |
docker tag changeme-web docker.pkg.github.com/${{ github.repository }}/changeme-web:latest
- name: Docker - Push
run: |
docker push docker.pkg.github.com/${{ github.repository }}/changeme-web:latest
@sburns
Copy link

sburns commented Nov 15, 2019

I believe that 5432 may not always be available on the host. https://github.com/actions/example-services/blob/master/.github/workflows/postgres-service.yml shows how to bind it to a random TCP port on local host and then pass that as an env var in later steps. Using services in these jobs is awesome though!

@jefftriplett
Copy link
Author

@sburns thanks for the tip. I updated the config and can confirm that it just worked.

@sburns
Copy link

sburns commented Nov 15, 2019

Also ymmv on this one, but we install pyscopg2 from source so I needed to apt-get install -y libpq-dev for Postgres headers to be nearby.

@arnaudlimbourg
Copy link

For people looking for Pipenv support, here is what I ended up with after a lots of fiddling, the import bit is setting up the WORKON and PIPENV_CACHE_DIR to the same directory as the whole directory will be cached.

      - name: Install pipenv
        uses: dschep/install-pipenv-action@v1

      - name: Cache Pipenv virtualenv
        uses: actions/cache@v1
        id: pipenv-cache
        with:
          path: ~/.pipenv
          key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-pipenv-v2-

      - name: Install Dependencies
        env:
          PIPENV_NOSPIN: 'true'
          WORKON_HOME: ~/.pipenv/virtualenvs
          PIPENV_CACHE_DIR: ~/.pipenv/pipcache
        run: pipenv install --dev
        if: steps.pipenv-cache.outputs.cache-hit != 'true'

      - name: Test with pytest
        env:
          PIPENV_NOSPIN: 'true'
          WORKON_HOME: ~/.pipenv/virtualenvs
          REDIS_HOST: localhost
          REDIS_PORT: ${{ job.services.redis.ports[6379] }}
          DATABASE_URL: 'postgres://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/test_db'
          DJANGO_SECRET_KEY: 'KEY'
          DJANGO_SETTINGS_MODULE: CONFIG'
          PYTHONPATH: '.'
          DJANGO_DEBUG: 'False'
        run: |
          pipenv run python manage.py migrate --noinput
          pipenv run pytest 

@jefftriplett
Copy link
Author

@arnaudlimbourg that's great!

@AdrienHorgnies
Copy link

It was indeed a great starting point.

Though I had some problems with the URL string overwriting Heroku configuration. I've solved that problem by forwarding database related settings as environment variables (same as you do with database URL) and using the values in the DATABASES setting:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('PG_NAME', 'pgdb'),
        'USER': os.environ.get('PG_USER', 'pguser'),
        'PASSWORD': os.environ.get('PG_PWD', 'pgpwd'),
        'HOST': os.environ.get('PG_HOST', 'localhost'),
        'PORT': os.environ.get('PG_PORT', '5432'),
    }
}

@opethe1st
Copy link

thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment