commit 656c13b40fb87ca437fefca7ddd3da0d55799e0e Author: Kurbanov Bulat Date: Sun Nov 14 00:25:25 2021 +0300 Init diff --git a/.github/workflows/build_docker_image.yml b/.github/workflows/build_docker_image.yml new file mode 100644 index 0000000..fd94750 --- /dev/null +++ b/.github/workflows/build_docker_image.yml @@ -0,0 +1,49 @@ +name: Build docker image + +on: + push: + branches: + - 'main' + +jobs: + Build-Docker-Image: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v2 + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - id: repository_name + uses: ASzc/change-string-case-action@v1 + with: + string: ${{ github.repository }} + + - + name: Login to ghcr.io + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - + name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + env: + IMAGE: ${{ steps.repository_name.outputs.lowercase }} + with: + push: true + tags: ghcr.io/${{ env.IMAGE }}:latest + context: . + file: ./docker/production.dockerfile + + - + name: Invoke deployment hook + uses: joelwmale/webhook-action@master + with: + url: ${{ secrets.WEBHOOK_URL }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f5e96db --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv \ No newline at end of file diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..c586982 --- /dev/null +++ b/app/main.py @@ -0,0 +1,53 @@ +import uuid +import asyncio +import os + +from fastapi import FastAPI, APIRouter, File, UploadFile, Form, HTTPException, BackgroundTasks, status +from fastapi.responses import FileResponse +from starlette.background import BackgroundTask + +import aiofiles + + +router = APIRouter( + tags=["converter"] +) + + +@router.post("/") +async def convert(background_tasks: BackgroundTasks, file: UploadFile = File({}), format: str = Form({})): + temp_uuid = uuid.uuid1() + + temp_filename = str(temp_uuid) + '.fb2' + converted_temp_filename = str(temp_uuid) + '.' + format + + async with aiofiles.open(temp_filename, 'wb') as f: + content = await file.read() + + if isinstance(content, str): + content = content.encode() + + await f.write(content) + + proc = await asyncio.create_subprocess_exec( + './bin/fb2c', 'convert', '--to', format, temp_filename, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE + ) + + await proc.communicate() + + background_tasks.add_task(os.remove, temp_filename) + + if proc.returncode != 0: + return HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Can't convert!") + + return FileResponse( + converted_temp_filename, + background=BackgroundTask(lambda: os.remove(converted_temp_filename)) + ) + + +app = FastAPI() + +app.include_router(router) diff --git a/docker/build.dockerfile b/docker/build.dockerfile new file mode 100644 index 0000000..828d7b4 --- /dev/null +++ b/docker/build.dockerfile @@ -0,0 +1,35 @@ +FROM python:3.10-slim as build-image + +RUN apt-get update \ + && apt-get install --no-install-recommends -y unzip \ + && rm -rf /var/lib/apt/lists/* + +# Get converter bin +WORKDIR /root/fb2converter +ADD https://github.com/rupor-github/fb2converter/releases/download/v1.59.0/fb2c_linux_amd64.zip ./ +RUN unzip fb2c_linux_amd64.zip + +# Install requirements +WORKDIR /root/temp +ENV VENV_PATH=/opt/venv +COPY ./requirements.txt ./ +RUN python -m venv $VENV_PATH \ + && . /opt/venv/bin/activate \ + && pip install -r requirements.txt --no-cache-dir + + +FROM python:3.10-slim as runtime-image + +WORKDIR /app + +COPY ./app/ ./ + +ENV VENV_PATH=/opt/venv +ENV PATH="$VENV_PATH/bin:$PATH" + +COPY --from=build-image /root/fb2converter/ /app/bin/ +COPY --from=build-image $VENV_PATH $VENV_PATH + +EXPOSE 8080 + +CMD uvicorn main:app --host="0.0.0.0" --port="8080" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e128f1e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +fastapi +python-multipart +aiofiles +uvicorn