Skip to content

Commit 05592a4

Browse files
committed
add github actions
1 parent ceb70a9 commit 05592a4

26 files changed

Lines changed: 497 additions & 12 deletions

.github/workflows/main.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Continuous Integration and Delivery
2+
3+
on: [push]
4+
5+
env:
6+
IMAGE: docker.pkg.github.com/$GITHUB_REPOSITORY/web
7+
8+
jobs:
9+
10+
build:
11+
name: Build Docker Image
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout master
15+
uses: actions/checkout@v1
16+
- name: Log in to GitHub Packages
17+
run: echo ${GITHUB_TOKEN} | docker login -u ${GITHUB_ACTOR} --password-stdin docker.pkg.github.com
18+
env:
19+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20+
- name: Pull image
21+
run: |
22+
docker pull ${{ env.IMAGE }}:latest || true
23+
- name: Build image
24+
run: |
25+
docker build \
26+
--cache-from ${{ env.IMAGE }}:latest \
27+
--tag ${{ env.IMAGE }}:latest \
28+
--file ./project/Dockerfile.prod \
29+
"./project"
30+
- name: Push image
31+
run: |
32+
docker push ${{ env.IMAGE }}:latest
33+
34+
test:
35+
name: Test Docker Image
36+
runs-on: ubuntu-latest
37+
needs: build
38+
steps:
39+
- name: Checkout master
40+
uses: actions/checkout@v1
41+
- name: Log in to GitHub Packages
42+
run: echo ${GITHUB_TOKEN} | docker login -u ${GITHUB_ACTOR} --password-stdin docker.pkg.github.com
43+
env:
44+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45+
- name: Pull image
46+
run: |
47+
docker pull ${{ env.IMAGE }}:latest || true
48+
- name: Build image
49+
run: |
50+
docker build \
51+
--cache-from ${{ env.IMAGE }}:latest \
52+
--tag ${{ env.IMAGE }}:latest \
53+
--file ./project/Dockerfile.prod \
54+
"./project"
55+
- name: Run container
56+
run: |
57+
docker run \
58+
-d \
59+
--name fastapi-tdd \
60+
-e PORT=8765 \
61+
-e ENVIRONMENT=dev \
62+
-e DATABASE_TEST_URL=sqlite://sqlite.db \
63+
-p 5003:8765 \
64+
${{ env.IMAGE }}:latest
65+
- name: Pytest
66+
run: docker exec fastapi-tdd python -m pytest .
67+
- name: Flake8
68+
run: docker exec fastapi-tdd python -m flake8 .
69+
- name: Black
70+
run: docker exec fastapi-tdd python -m black . --check
71+
- name: isort
72+
run: docker exec fastapi-tdd /bin/sh -c "python -m isort ./*/*.py --check-only"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
__pycache__
22
env
3+
.coverage
4+
htmlcov

docker-compose.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
version: '3.7'
2+
3+
services:
4+
5+
web:
6+
build: ./project
7+
command: uvicorn app.main:app --reload --workers 1 --host 0.0.0.0 --port 8000
8+
volumes:
9+
- ./project:/usr/src/app
10+
ports:
11+
- 8002:8000
12+
environment:
13+
- ENVIRONMENT=dev
14+
- TESTING=0
15+
- DATABASE_URL=postgres://postgres:postgres@web-db:5432/web_dev
16+
- DATABASE_TEST_URL=postgres://postgres:postgres@web-db:5432/web_test
17+
depends_on:
18+
- web-db
19+
20+
21+
web-db:
22+
build:
23+
context: ./project/db
24+
dockerfile: Dockerfile
25+
expose:
26+
- 5432
27+
environment:
28+
- POSTGRES_USER=postgres
29+
- POSTGRES_PASSWORD=postgres

project/.coveragerc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[run]
2+
omit = tests/*
3+
branch = True

project/.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
env
2+
.dockerignore
3+
Dockerfile
4+
Dockerfile.prod
5+
.coverage
6+
htmlcov

project/Dockerfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# pull official base image
2+
FROM python:3.8.3-slim-buster
3+
4+
# set working directory
5+
WORKDIR /usr/src/app
6+
7+
# set environment varibles
8+
ENV PYTHONDONTWRITEBYTECODE 1
9+
ENV PYTHONUNBUFFERED 1
10+
11+
# install system dependencies
12+
RUN apt-get update \
13+
&& apt-get -y install netcat gcc postgresql \
14+
&& apt-get clean
15+
16+
# install python dependencies
17+
RUN pip install --upgrade pip
18+
COPY ./requirements.txt .
19+
RUN pip install -r requirements.txt
20+
21+
# add app
22+
COPY . .
23+
24+
# run entrypoint.sh
25+
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

project/Dockerfile.prod

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# pull official base image
2+
FROM python:3.8.3-slim-buster
3+
4+
# create directory for the app user
5+
RUN mkdir -p /home/app
6+
7+
# create the app user
8+
RUN addgroup --system app && adduser --system --group app
9+
10+
# create the appropriate directories
11+
ENV HOME=/home/app
12+
ENV APP_HOME=/home/app/web
13+
RUN mkdir $APP_HOME
14+
WORKDIR $APP_HOME
15+
16+
# set environment varibles
17+
ENV PYTHONDONTWRITEBYTECODE 1
18+
ENV PYTHONUNBUFFERED 1
19+
ENV ENVIRONMENT prod
20+
ENV TESTING 0
21+
22+
# install system dependencies
23+
RUN apt-get update \
24+
&& apt-get -y install netcat gcc postgresql \
25+
&& apt-get clean
26+
27+
# install python dependencies
28+
RUN pip install --upgrade pip
29+
COPY ./requirements.txt .
30+
RUN pip install -r requirements.txt
31+
32+
# add app
33+
COPY . .
34+
35+
# chown all the files to the app user
36+
RUN chown -R app:app $APP_HOME
37+
38+
# change to the app user
39+
USER app
40+
41+
# run gunicorn
42+
CMD gunicorn --bind 0.0.0.0:$PORT app.main:app -k uvicorn.workers.UvicornWorker

project/app/api/__init__.py

Whitespace-only changes.

project/app/api/crud.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# project/app/api/crud.py
2+
3+
4+
from typing import Union, List
5+
6+
from app.models.pydantic import SummaryPayloadSchema
7+
from app.models.tortoise import TextSummary
8+
9+
10+
async def post(payload: SummaryPayloadSchema) -> int:
11+
summary = TextSummary(url=payload.url, summary="dummy summary",)
12+
await summary.save()
13+
return summary.id
14+
15+
16+
async def get(id: int) -> Union[dict, None]:
17+
summary = await TextSummary.filter(id=id).first().values()
18+
if summary:
19+
return summary[0]
20+
return None
21+
22+
23+
async def get_all() -> List:
24+
summaries = await TextSummary.all().values()
25+
return summaries

project/app/api/ping.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# project/app/api/ping.py
2+
3+
4+
from fastapi import APIRouter, Depends
5+
6+
from app.config import get_settings, Settings
7+
8+
9+
router = APIRouter()
10+
11+
12+
@router.get("/ping")
13+
async def pong(settings: Settings = Depends(get_settings)):
14+
return {
15+
"ping": "pong!",
16+
"environment": settings.environment,
17+
"testing": settings.testing,
18+
}

0 commit comments

Comments
 (0)