Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
export AWS_ACCESS_KEY_ID="<key-id>"
export AWS_SECRET_ACCESS_KEY="<secret-key>"

export FLASK_APP=lightsoff_api
export DATABASE_URI=postgresql://username:password@host:port/database_name
export CORS_ALLOWED_ORIGINS="*"
FLASK_HOST=0.0.0.0
FLASK_PORT=5000
FLASK_APP=lightsoff_api
FLASK_DEBUG=True
DATABASE_URI=postgresql://username:password@host:port/database_name
CORS_ALLOWED_ORIGINS="*"
28 changes: 24 additions & 4 deletions .github/workflows/zappa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,31 @@ jobs:
tests:
name: "Tests"
runs-on: ubuntu-latest
container: python:3.9
needs: [lint]

defaults:
run:
shell: bash
shell:
bash
#

services:
# Label used to access the service container
postgres:
# Docker Hub image
image: postgres:15-alpine
# Provide the password for postgres
env:
POSTGRES_USER: lightsoff
POSTGRES_PASSWORD: lightsoff
POSTGRES_DB: lightsoff
# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- name: Checkout
Expand All @@ -46,7 +66,7 @@ jobs:
run: |
curl -sSL https://install.python-poetry.org | python3 -
poetry install
poetry run pytest
DATABASE_URI=postgresql://lightsoff:lightsoff@postgres:5432/lightsoff poetry run pytest

zappa-staging:
name: "Zappa Staging"
Expand All @@ -71,7 +91,7 @@ jobs:
- name: Zappa deploy
run: |
curl -sSL https://install.python-poetry.org | python3 -
poetry install --no-dev --no-root
poetry install --no-dev --no-root --with=zappa
cp zappa_settings.template.json zappa_settings.json
echo $(jq '.ENVIRONMENT.s3_bucket = "${{ secrets.S3_BUCKET }}"' zappa_settings.json) > zappa_settings.json
echo $(jq '.ENVIRONMENT.aws_environment_variables.DATABASE_URI = "${{ secrets.DATABASE_URI }}"' zappa_settings.json) > zappa_settings.json
Expand Down Expand Up @@ -107,7 +127,7 @@ jobs:
- name: Zappa deploy
run: |
curl -sSL https://install.python-poetry.org | python3 -
poetry install --no-dev --no-root
poetry install --no-dev --no-root --with=zappa
cp zappa_settings.template.json zappa_settings.json
echo $(jq '.ENVIRONMENT.s3_bucket = "${{ secrets.S3_BUCKET }}"' zappa_settings.json) > zappa_settings.json
echo $(jq '.ENVIRONMENT.aws_environment_variables.DATABASE_URI = "${{ secrets.DATABASE_URI }}"' zappa_settings.json) > zappa_settings.json
Expand Down
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM python:3.9

RUN mkdir /app
WORKDIR /app
ENV PYTHONPATH=${PYTHONPATH}:${PWD}

RUN pip3 install poetry
COPY ./pyproject.toml .
COPY ./poetry.lock .
RUN poetry config virtualenvs.create false
RUN poetry install

COPY ./ .
25 changes: 25 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.PHONY: start stop clean run_migrations create_migration run_tests

start:
@docker compose up --build --detach --remove-orphans

stop:
@docker compose stop

watch:
@docker compose logs --tail 100 --follow

clean:
@docker compose stop
@docker compose rm --volumes --force

run_migrations:
@docker compose run -d database
@docker compose run --rm --entrypoint '' api flask db upgrade

create_migration: run_migrations
@docker compose run --rm --entrypoint '' api flask db migrate -m "Reword me"

run_tests:
@docker compose run -d database
@docker compose run -e DATABASE_NAME=lightsoff_test --rm --entrypoint '' api pytest
46 changes: 35 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
# Development setup

- [Install poetry](https://python-poetry.org/docs/#installation)
- Install python 3.9
- Create a virtual `python -m venv venv`
- Activate `source venv/bin/activate`
- Install dependencies `poetry install`
- Copy environment file: `cp .env.template .env`
- Replace environment variables with yours
- Run migrations `flask db upgrade`
- Launch the app `flask run`
# LightsOff API

## Built With

- [Python3](https://www.python.org/)
- [Poetry](https://python-poetry.org/)
- [Flask](https://flask.palletsprojects.com/)
- [Docker](https://www.docker.com/) & [Docker Composer](https://docs.docker.com/compose/)

## Get Started

Copy environment file: `cp .env.template .env`

```console
make start
make run_migrations
```

Go to http://localhost:5000/openapi/

## Running tests

```console
make run_tests
```

## Generating a migration file

```console
make create_migration
```

## Deployment

This is handled by [Zappa](https://github.com/zappa/Zappa) in the `zappa.yml` github workflow
24 changes: 24 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
services:
api:
build: .
working_dir: /app
volumes:
- ./:/app
ports:
- 5000:5000
depends_on:
- database
entrypoint: python lightsoff_api/__init__.py
environment:
- DATABASE_URI=postgresql://lightsoff:lightsoff@database:5432/lightsoff

database:
image: postgres:15-alpine
environment:
- POSTGRES_USER=lightsoff
- POSTGRES_PASSWORD=lightsoff
- POSTGRES_DB=lightsoff
ports:
- 5054:5432
volumes:
- ./db-init-scripts:/docker-entrypoint-initdb.d
1 change: 1 addition & 0 deletions db-init-scripts/add-test-database.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE DATABASE lightsoff_test;
19 changes: 18 additions & 1 deletion lightsoff_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
from flask_sqlalchemy import SQLAlchemy
from pydantic import BaseModel, Field, root_validator

from dotenv import load_dotenv

load_dotenv()

servers = (
[
Server(url=f"/{os.environ.get('STAGE')}"),
Expand All @@ -23,6 +27,15 @@
app = OpenAPI(__name__, servers=servers)
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("DATABASE_URI")

if os.environ.get("DATABASE_NAME"):
app.config["SQLALCHEMY_DATABASE_URI"] = (
app.config["SQLALCHEMY_DATABASE_URI"].removesuffix(
app.config["SQLALCHEMY_DATABASE_URI"].split("/")[-1],
)
+ os.environ["DATABASE_NAME"]
)


CORS(app, origins=os.environ.get("CORS_ALLOWED_ORIGINS", "").split(","))
db = SQLAlchemy(app)
migrate = Migrate(app, db)
Expand Down Expand Up @@ -215,4 +228,8 @@ def increase_place_contacted_count(path: PlacePath):


if __name__ == "__main__":
app.run()
app.run(
host=os.environ.get("FLASK_HOST"),
port=os.environ.get("FLASK_PORT"),
debug=os.environ.get("FLASK_DEBUG"),
)
Loading