Skip to content

Commit

Permalink
Update workflows
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Natalenko committed Nov 23, 2023
1 parent c61bf72 commit 3c0f96b
Show file tree
Hide file tree
Showing 22 changed files with 209 additions and 92 deletions.
30 changes: 8 additions & 22 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ env:
POSTGRES_PORT: 5432
POSTGRES_DB: inclusive_dance_bot

REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: 389jf928fhf10
REDIS_DB: '3'

PROJECT_PATH: ./inclusive_dance_bot/
TEST_PATH: ./tests/

jobs:
checking:
runs-on: ubuntu-22.04
Expand All @@ -38,27 +30,24 @@ jobs:
python-version: '3.11'

- name: Install dependencies
run: |
python -m pip install -U pip poetry
poetry config virtualenvs.create false
poetry install
run: make develop

- name: Run flake8
run: flake8 --max-line-length 88 --format=default ${{ env.PROJECT_PATH }} 2>&1 | tee flake8.txt
run: make flake

- name: Run black
run: black ${{ env.PROJECT_PATH }} --check
run: make black

- name: Run bandit
run: bandit -r -ll -iii ${{ env.PROJECT_PATH }} -f json -o ./bandit.json
run: make bandit

- name: Run mypy
run: mypy --config-file ./pyproject.toml ${{ env.PROJECT_PATH }}
run: make mypy

test:
name: Run service tests with pytest
runs-on: ubuntu-22.04
container: python:3.11-slim
container: python:3.11
needs: checking
services:
postgres:
Expand All @@ -78,10 +67,7 @@ jobs:
uses: actions/checkout@v3

- name: Install dependencies
run: |
python -m pip install -U pip poetry
poetry config virtualenvs.create false
poetry install
run: make develop

- name: Run pytest
run: python -m pytest ${{ env.TEST_PATH }} --junitxml=./junit.xml --cov=${{ env.PROJECT_PATH }} --cov-report=xml
run: make test-ci
42 changes: 42 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Make release

env:
PROJECT_NAME: inclusive_dance_bot

on:
workflow_dispatch:
push:
branches:
- master

jobs:
checking:
name: Check repository
uses: ./.github/workflows/check.yml

build_and_push:
name: Build and push AMD64 and ARM64 images
needs: checking
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v4
with:
push: true
platforms: linux/amd64,linux/arm64
tags: andytakker/${{ env.PROJECT_NAME }}:latest
15 changes: 10 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,31 @@ help: ##@Help Show this help
lint-ci: flake black bandit mypy ##@Linting Run all linters in CI

flake: ##@Linting Run flake8
flake8 --max-line-length 88 --format=default $(PROJECT_PATH) 2>&1 | tee flake8.txt
.venv/bin/flake8 --max-line-length 88 --format=default $(PROJECT_PATH) 2>&1 | tee flake8.txt

black: ##@Linting Run black
black $(PROJECT_PATH) --check
.venv/bin/black $(PROJECT_PATH) --check

bandit: ##@Linting Run bandit
bandit -r -ll -iii $(PROJECT_PATH) -f json -o ./bandit.json
.venv/bin/bandit -r -ll -iii $(PROJECT_PATH) -f json -o ./bandit.json

mypy: ##@Linting Run mypy
mypy --config-file ./pyproject.toml $(PROJECT_PATH)
.venv/bin/mypy --config-file ./pyproject.toml $(PROJECT_PATH)

test: ##@Test Run tests with pytest
pytest -vvx $(TEST_PATH)

test-ci: ##@Test Run tests with pytest and coverage in CI
pytest $(TEST_PATH) --junitxml=./junit.xml --cov=$(PROJECT_PATH) --cov-report=xml

develop: #
python -m venv .venv
.venv/bin/pip install -U pip poetry
.venv/bin/poetry config virtualenvs.create false
.venv/bin/poetry install

local: ##@Develop Run db and redis containers
docker-compose -f docker-compose.dev.yaml up db redis -d
docker-compose -f docker-compose.dev.yaml up --force-recreate --renew-anon-volumes --build

local_down: ##@Develop Stop containers with delete volumes
docker-compose -f docker-compose.dev.yaml down -v
1 change: 1 addition & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ services:
POSTGRES_USER: $POSTGRES_USER
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_DB: $POSTGRES_DB
POSTGRES_URL: postgresql+asyncpg://$POSTGRES_USER:$POSTGRES_PASSWORD@db:5432/$POSTGRES_DB

REDIS_HOST: redis
REDIS_PORT: 6379
Expand Down
2 changes: 1 addition & 1 deletion docker/pre-start.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
alembic -c /app/inclusive_dance_bot/alembic.ini upgrade head
python -m inclusive_dance_bot.db

python /app/inclusive_dance_bot/init_data.py
2 changes: 0 additions & 2 deletions inclusive_dance_bot/bot/dialogs/admins/url/update/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Any

from aiogram_dialog import Dialog

from inclusive_dance_bot.bot.dialogs.admins.url.update import change_slug, change_value
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from textwrap import dedent

from aiogram_dialog import Dialog

from inclusive_dance_bot.bot.dialogs.users.registration import (
Expand Down
34 changes: 34 additions & 0 deletions inclusive_dance_bot/db/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import argparse
import logging
import os

from alembic.config import CommandLine

from inclusive_dance_bot.db.utils import make_alembic_config

DEFAULT_PG_URL = "postgresql://user:secret@localhost/inclusive_dance_bot"


def main() -> None:
logging.basicConfig(level=logging.DEBUG)

alembic = CommandLine()
alembic.parser.formatter_class = argparse.ArgumentDefaultsHelpFormatter
alembic.parser.add_argument(
"--pg-url",
default=os.getenv("POSTGRES_URL", DEFAULT_PG_URL),
help="Database URL [env var: POSTGRES_URL]",
)

options = alembic.parser.parse_args()
if "cmd" not in options:
alembic.parser.error("too few arguments")
exit(128)
else:
config = make_alembic_config(options)
alembic.run_cmd(config, options)
exit()


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[alembic]
script_location = %(here)s/db/migrations
script_location = %(here)s/migrations
file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(rev)s_%%(slug)s
prepend_sys_path = .
version_path_separator = os
Expand Down
25 changes: 23 additions & 2 deletions inclusive_dance_bot/db/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import re
from datetime import datetime

from sqlalchemy import MetaData
from sqlalchemy.orm import as_declarative, declared_attr
import pytz
from sqlalchemy import DateTime, MetaData, text
from sqlalchemy.orm import Mapped, as_declarative, declared_attr, mapped_column

convention = {
"all_column_names": lambda constraint, table: "_".join(
Expand All @@ -25,3 +27,22 @@ class Base:
def __tablename__(cls) -> str:
name_list = re.findall(r"[A-Z][a-z\d]*", cls.__name__)
return "_".join(name_list).lower()


def now_with_tz() -> datetime:
return datetime.now(tz=pytz.UTC)


class TimestampMixin:
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=now_with_tz,
server_default=text("TIMEZONE('utc', now())"),
nullable=False,
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=now_with_tz,
onupdate=now_with_tz,
server_default=text("TIMEZONE('utc', now())"),
)
20 changes: 0 additions & 20 deletions inclusive_dance_bot/db/factory.py

This file was deleted.

3 changes: 0 additions & 3 deletions inclusive_dance_bot/db/migrations/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from sqlalchemy.engine import Connection
from sqlalchemy.ext.asyncio import async_engine_from_config

from inclusive_dance_bot.config import Settings
from inclusive_dance_bot.db.models import Base

config = context.config
Expand All @@ -16,8 +15,6 @@
fileConfig(config.config_file_name)


settings = Settings()
config.set_main_option("sqlalchemy.url", settings.build_db_connection_uri())
target_metadata = Base.metadata


Expand Down
24 changes: 0 additions & 24 deletions inclusive_dance_bot/db/mixins.py

This file was deleted.

3 changes: 1 addition & 2 deletions inclusive_dance_bot/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy_utils import ChoiceType

from inclusive_dance_bot.db.base import Base
from inclusive_dance_bot.db.mixins import TimestampMixin
from inclusive_dance_bot.db.base import Base, TimestampMixin
from inclusive_dance_bot.enums import FeedbackType, MailingStatus, SubmenuType


Expand Down
53 changes: 53 additions & 0 deletions inclusive_dance_bot/db/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import os
from argparse import Namespace
from pathlib import Path
from typing import Any

from alembic.config import Config
from sqlalchemy.ext.asyncio import (
AsyncEngine,
AsyncSession,
async_sessionmaker,
create_async_engine,
)

import inclusive_dance_bot

PROJECT_PATH = Path(inclusive_dance_bot.__file__).parent.parent.resolve()


def create_engine(connection_uri: str, **engine_kwargs: Any) -> AsyncEngine:
return create_async_engine(url=connection_uri, **engine_kwargs, pool_pre_ping=True)


def create_session_factory(engine: AsyncEngine) -> async_sessionmaker[AsyncSession]:
return async_sessionmaker(
bind=engine,
class_=AsyncSession,
expire_on_commit=False,
)


def make_alembic_config(cmd_opts: Namespace, base_path: Path = PROJECT_PATH) -> Config:
if not os.path.isabs(cmd_opts.config):
cmd_opts.config = str(base_path / "inclusive_dance_bot/db" / cmd_opts.config)

config = Config(
file_=cmd_opts.config,
ini_section=cmd_opts.name,
cmd_opts=cmd_opts,
)

alembic_location = config.get_main_option("script_location")
if not alembic_location:
raise ValueError
print(alembic_location)
if not os.path.isabs(alembic_location):
config.set_main_option("script_location", str(base_path / alembic_location))

if cmd_opts.pg_url:
config.set_main_option("sqlalchemy.url", cmd_opts.pg_url)

config.attributes["configure_logger"] = False

return config
2 changes: 1 addition & 1 deletion inclusive_dance_bot/deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

from inclusive_dance_bot.bot.factory import get_bot
from inclusive_dance_bot.config import Settings
from inclusive_dance_bot.db.factory import create_engine, create_session_factory
from inclusive_dance_bot.db.uow.main import UnitOfWork
from inclusive_dance_bot.db.utils import create_engine, create_session_factory


def config_deps(app_settings: Settings) -> None:
Expand Down
1 change: 0 additions & 1 deletion inclusive_dance_bot/dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from datetime import datetime
from typing import TYPE_CHECKING

from inclusive_dance_bot.db.models import Mailing
from inclusive_dance_bot.enums import FeedbackType, MailingStatus, SubmenuType

if TYPE_CHECKING:
Expand Down
Loading

0 comments on commit 3c0f96b

Please sign in to comment.