mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-19 05:09:40 +02:00
dev: Create a Python package, build Docker images from it (#4551)
Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com> Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com> Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
This commit is contained in:
parent
abf73e08ec
commit
c0ab7673ba
19 changed files with 357 additions and 91 deletions
|
@ -6,7 +6,7 @@
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
__pycache__/
|
**/__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
*$py.class
|
||||||
*.so
|
*.so
|
||||||
|
@ -25,9 +25,11 @@ venv
|
||||||
|
|
||||||
*/node_modules
|
*/node_modules
|
||||||
*/dist
|
*/dist
|
||||||
|
/dist/
|
||||||
*/data/db
|
*/data/db
|
||||||
*/mealie/test
|
*/mealie/test
|
||||||
*/mealie/.temp
|
*/mealie/.temp
|
||||||
|
/mealie/frontend/
|
||||||
|
|
||||||
model.crfmodel
|
model.crfmodel
|
||||||
|
|
||||||
|
|
14
.github/workflows/e2e.yml
vendored
14
.github/workflows/e2e.yml
vendored
|
@ -3,8 +3,15 @@ on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
build-package:
|
||||||
|
name: "Build Python package"
|
||||||
|
uses: ./.github/workflows/partial-package.yml
|
||||||
|
with:
|
||||||
|
tag: e2e
|
||||||
|
|
||||||
test:
|
test:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
|
needs: build-package
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
|
@ -18,11 +25,18 @@ jobs:
|
||||||
cache-dependency-path: ./tests/e2e/yarn.lock
|
cache-dependency-path: ./tests/e2e/yarn.lock
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Retrieve Python package
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: backend-dist
|
||||||
|
path: dist
|
||||||
- name: Build Image
|
- name: Build Image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
file: ./docker/Dockerfile
|
file: ./docker/Dockerfile
|
||||||
context: .
|
context: .
|
||||||
|
build-contexts: |
|
||||||
|
packages=dist
|
||||||
push: false
|
push: false
|
||||||
load: true
|
load: true
|
||||||
tags: mealie:e2e
|
tags: mealie:e2e
|
||||||
|
|
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
|
@ -21,7 +21,7 @@ jobs:
|
||||||
uses: ./.github/workflows/partial-backend.yml
|
uses: ./.github/workflows/partial-backend.yml
|
||||||
|
|
||||||
frontend-tests:
|
frontend-tests:
|
||||||
name: "Frontend and End-to-End Tests"
|
name: "Frontend Tests"
|
||||||
uses: ./.github/workflows/partial-frontend.yml
|
uses: ./.github/workflows/partial-frontend.yml
|
||||||
|
|
||||||
build-release:
|
build-release:
|
||||||
|
|
2
.github/workflows/partial-backend.yml
vendored
2
.github/workflows/partial-backend.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: Backend Test/Lint
|
name: Backend Lint and Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
|
|
19
.github/workflows/partial-builder.yml
vendored
19
.github/workflows/partial-builder.yml
vendored
|
@ -16,7 +16,14 @@ on:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
build-package:
|
||||||
|
name: "Build Python package"
|
||||||
|
uses: ./.github/workflows/partial-package.yml
|
||||||
|
with:
|
||||||
|
tag: ${{ inputs.tag }}
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
|
needs: build-package
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
|
@ -35,18 +42,22 @@ jobs:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Override __init__.py
|
|
||||||
run: |
|
|
||||||
echo "__version__ = \"${{ inputs.tag }}\"" > ./mealie/__init__.py
|
|
||||||
|
|
||||||
- uses: depot/setup-action@v1
|
- uses: depot/setup-action@v1
|
||||||
|
|
||||||
|
- name: Retrieve Python package
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: backend-dist
|
||||||
|
path: dist
|
||||||
|
|
||||||
- name: Build and push Docker image, via Depot.dev
|
- name: Build and push Docker image, via Depot.dev
|
||||||
uses: depot/build-push-action@v1
|
uses: depot/build-push-action@v1
|
||||||
with:
|
with:
|
||||||
project: srzjb6mhzm
|
project: srzjb6mhzm
|
||||||
file: ./docker/Dockerfile
|
file: ./docker/Dockerfile
|
||||||
context: .
|
context: .
|
||||||
|
build-contexts: |
|
||||||
|
packages=dist
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
|
|
36
.github/workflows/partial-frontend.yml
vendored
36
.github/workflows/partial-frontend.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
name: Frontend Build/Lin
|
name: Frontend Lint and Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
|
@ -41,37 +41,3 @@ jobs:
|
||||||
- name: Run tests 🧪
|
- name: Run tests 🧪
|
||||||
run: yarn test:ci
|
run: yarn test:ci
|
||||||
working-directory: "frontend"
|
working-directory: "frontend"
|
||||||
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout 🛎
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup node env 🏗
|
|
||||||
uses: actions/setup-node@v4.0.0
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
check-latest: true
|
|
||||||
|
|
||||||
- name: Get yarn cache directory path 🛠
|
|
||||||
id: yarn-cache-dir-path
|
|
||||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Cache node_modules 📦
|
|
||||||
uses: actions/cache@v4
|
|
||||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
|
||||||
with:
|
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
||||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-yarn-
|
|
||||||
|
|
||||||
- name: Install dependencies 👨🏻💻
|
|
||||||
run: yarn
|
|
||||||
working-directory: "frontend"
|
|
||||||
|
|
||||||
- name: Run Build 🚚
|
|
||||||
run: yarn build
|
|
||||||
working-directory: "frontend"
|
|
||||||
|
|
102
.github/workflows/partial-package.yml
vendored
Normal file
102
.github/workflows/partial-package.yml
vendored
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
name: Package build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-frontend:
|
||||||
|
name: Build frontend
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout 🛎
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup node env 🏗
|
||||||
|
uses: actions/setup-node@v4.0.0
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
|
- name: Get yarn cache directory path 🛠
|
||||||
|
id: yarn-cache-dir-path
|
||||||
|
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Cache node_modules 📦
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||||
|
with:
|
||||||
|
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-yarn-
|
||||||
|
|
||||||
|
- name: Install dependencies 👨🏻💻
|
||||||
|
run: yarn
|
||||||
|
working-directory: "frontend"
|
||||||
|
|
||||||
|
- name: Run Build 🚚
|
||||||
|
run: yarn generate
|
||||||
|
working-directory: "frontend"
|
||||||
|
|
||||||
|
- name: Archive built frontend
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: frontend-dist
|
||||||
|
path: frontend/dist
|
||||||
|
retention-days: 5
|
||||||
|
|
||||||
|
build-package:
|
||||||
|
name: Build Python package
|
||||||
|
needs: build-frontend
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install Task
|
||||||
|
uses: arduino/setup-task@v2
|
||||||
|
with:
|
||||||
|
version: 3.x
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
|
||||||
|
- name: Install Poetry
|
||||||
|
uses: snok/install-poetry@v1
|
||||||
|
with:
|
||||||
|
virtualenvs-create: true
|
||||||
|
virtualenvs-in-project: true
|
||||||
|
plugins: |
|
||||||
|
poetry-plugin-export
|
||||||
|
|
||||||
|
- name: Retrieve built frontend
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: frontend-dist
|
||||||
|
path: mealie/frontend
|
||||||
|
|
||||||
|
- name: Override __init__.py
|
||||||
|
run: |
|
||||||
|
echo "__version__ = \"${{ inputs.tag }}\"" > ./mealie/__init__.py
|
||||||
|
|
||||||
|
- name: Build package and requirements.txt
|
||||||
|
env:
|
||||||
|
SKIP_PACKAGE_DEPS: true
|
||||||
|
run: |
|
||||||
|
task py:package
|
||||||
|
|
||||||
|
- name: Archive built package
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: backend-dist
|
||||||
|
path: dist
|
||||||
|
retention-days: 5
|
2
.github/workflows/pull-requests.yml
vendored
2
.github/workflows/pull-requests.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
||||||
uses: ./.github/workflows/partial-backend.yml
|
uses: ./.github/workflows/partial-backend.yml
|
||||||
|
|
||||||
frontend-tests:
|
frontend-tests:
|
||||||
name: "Frontend and End-to-End Tests"
|
name: "Frontend Tests"
|
||||||
uses: ./.github/workflows/partial-frontend.yml
|
uses: ./.github/workflows/partial-frontend.yml
|
||||||
|
|
||||||
container-scanning:
|
container-scanning:
|
||||||
|
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
||||||
uses: ./.github/workflows/partial-backend.yml
|
uses: ./.github/workflows/partial-backend.yml
|
||||||
|
|
||||||
frontend-tests:
|
frontend-tests:
|
||||||
name: "Frontend and End-to-End Tests"
|
name: "Frontend Tests"
|
||||||
uses: ./.github/workflows/partial-frontend.yml
|
uses: ./.github/workflows/partial-frontend.yml
|
||||||
|
|
||||||
build-release:
|
build-release:
|
||||||
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -52,7 +52,7 @@ pnpm-debug.log*
|
||||||
env/
|
env/
|
||||||
build/
|
build/
|
||||||
develop-eggs/
|
develop-eggs/
|
||||||
|
/dist/
|
||||||
downloads/
|
downloads/
|
||||||
eggs/
|
eggs/
|
||||||
.eggs/
|
.eggs/
|
||||||
|
@ -66,6 +66,9 @@ wheels/
|
||||||
.installed.cfg
|
.installed.cfg
|
||||||
*.egg
|
*.egg
|
||||||
|
|
||||||
|
# frontend copied into Python module for packaging purposes
|
||||||
|
/mealie/frontend/
|
||||||
|
|
||||||
# PyInstaller
|
# PyInstaller
|
||||||
# Usually these files are written by a python script from a template
|
# Usually these files are written by a python script from a template
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
|
86
Taskfile.yml
86
Taskfile.yml
|
@ -41,14 +41,25 @@ tasks:
|
||||||
setup:ui:
|
setup:ui:
|
||||||
desc: setup frontend dependencies
|
desc: setup frontend dependencies
|
||||||
dir: frontend
|
dir: frontend
|
||||||
|
run: once
|
||||||
cmds:
|
cmds:
|
||||||
- yarn install
|
- yarn install
|
||||||
|
sources:
|
||||||
|
- package.json
|
||||||
|
- yarn.lock
|
||||||
|
generates:
|
||||||
|
- node_modules/**
|
||||||
|
|
||||||
setup:py:
|
setup:py:
|
||||||
desc: setup python dependencies
|
desc: setup python dependencies
|
||||||
|
run: once
|
||||||
cmds:
|
cmds:
|
||||||
- poetry install --with main,dev,postgres
|
- poetry install --with main,dev,postgres
|
||||||
- poetry run pre-commit install
|
- poetry run pre-commit install
|
||||||
|
sources:
|
||||||
|
- poetry.lock
|
||||||
|
- pyproject.toml
|
||||||
|
- .pre-commit-config.yaml
|
||||||
|
|
||||||
setup:model:
|
setup:model:
|
||||||
desc: setup nlp model
|
desc: setup nlp model
|
||||||
|
@ -131,6 +142,63 @@ tasks:
|
||||||
- poetry run coverage html
|
- poetry run coverage html
|
||||||
- open htmlcov/index.html
|
- open htmlcov/index.html
|
||||||
|
|
||||||
|
py:package:copy-frontend:
|
||||||
|
desc: copy the frontend files into the Python package
|
||||||
|
internal: true
|
||||||
|
deps:
|
||||||
|
- ui:generate
|
||||||
|
cmds:
|
||||||
|
- rm -rf mealie/frontend
|
||||||
|
- cp -a frontend/dist mealie/frontend
|
||||||
|
sources:
|
||||||
|
- frontend/dist/**
|
||||||
|
generates:
|
||||||
|
- mealie/frontend/**
|
||||||
|
|
||||||
|
py:package:generate-requirements:
|
||||||
|
desc: Generate requirements file to pin all packages, effectively a "pip freeze" before installation begins
|
||||||
|
internal: true
|
||||||
|
cmds:
|
||||||
|
- poetry export -n --only=main --extras=pgsql --output=dist/requirements.txt
|
||||||
|
# Include mealie in the requirements, hashing the package that was just built to ensure it's the one installed
|
||||||
|
- echo "mealie[pgsql]=={{.MEALIE_VERSION}} \\" >> dist/requirements.txt
|
||||||
|
- poetry run pip hash dist/mealie-{{.MEALIE_VERSION}}-py3-none-any.whl | tail -n1 | tr -d '\n' >> dist/requirements.txt
|
||||||
|
- echo " \\" >> dist/requirements.txt
|
||||||
|
- poetry run pip hash dist/mealie-{{.MEALIE_VERSION}}.tar.gz | tail -n1 >> dist/requirements.txt
|
||||||
|
vars:
|
||||||
|
MEALIE_VERSION:
|
||||||
|
sh: poetry version --short
|
||||||
|
sources:
|
||||||
|
- poetry.lock
|
||||||
|
- pyproject.toml
|
||||||
|
- dist/mealie-*.whl
|
||||||
|
- dist/mealie-*.tar.gz
|
||||||
|
generates:
|
||||||
|
- dist/requirements.txt
|
||||||
|
|
||||||
|
py:package:deps-parallel:
|
||||||
|
desc: Run py:package dependencies in parallel
|
||||||
|
internal: true
|
||||||
|
deps:
|
||||||
|
- setup:py
|
||||||
|
- py:package:copy-frontend
|
||||||
|
|
||||||
|
py:package:deps:
|
||||||
|
desc: Dependencies of py:package, skippable by setting SKIP_PACKAGE_DEPS=true
|
||||||
|
internal: true
|
||||||
|
cmds:
|
||||||
|
- task: py:package:deps-parallel
|
||||||
|
status:
|
||||||
|
- '{{ .SKIP_PACKAGE_DEPS | default "false"}}'
|
||||||
|
|
||||||
|
py:package:
|
||||||
|
desc: builds Python packages (sdist and wheel) in top-level dist directory
|
||||||
|
deps:
|
||||||
|
- py:package:deps
|
||||||
|
cmds:
|
||||||
|
- poetry build -n --output=dist
|
||||||
|
- task: py:package:generate-requirements
|
||||||
|
|
||||||
py:
|
py:
|
||||||
desc: runs the backend server
|
desc: runs the backend server
|
||||||
cmds:
|
cmds:
|
||||||
|
@ -160,6 +228,14 @@ tasks:
|
||||||
cmds:
|
cmds:
|
||||||
- yarn build
|
- yarn build
|
||||||
|
|
||||||
|
ui:generate:
|
||||||
|
desc: generates a static version of the frontend in frontend/dist
|
||||||
|
dir: frontend
|
||||||
|
deps:
|
||||||
|
- setup:ui
|
||||||
|
cmds:
|
||||||
|
- yarn generate
|
||||||
|
|
||||||
ui:lint:
|
ui:lint:
|
||||||
desc: runs the frontend linter
|
desc: runs the frontend linter
|
||||||
dir: frontend
|
dir: frontend
|
||||||
|
@ -184,6 +260,16 @@ tasks:
|
||||||
cmds:
|
cmds:
|
||||||
- yarn run dev
|
- yarn run dev
|
||||||
|
|
||||||
|
docker:build-from-package:
|
||||||
|
desc: Builds the Docker image from the existing Python package in dist/
|
||||||
|
deps:
|
||||||
|
- py:package
|
||||||
|
cmds:
|
||||||
|
- docker build --tag mealie:dev --file docker/Dockerfile --build-arg COMMIT={{.GIT_COMMIT}} --build-context packages=dist .
|
||||||
|
vars:
|
||||||
|
GIT_COMMIT:
|
||||||
|
sh: git rev-parse HEAD
|
||||||
|
|
||||||
docker:prod:
|
docker:prod:
|
||||||
desc: builds and runs the production docker image locally
|
desc: builds and runs the production docker image locally
|
||||||
dir: docker
|
dir: docker
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
FROM node:16 as builder
|
###############################################
|
||||||
|
# Frontend Build
|
||||||
|
###############################################
|
||||||
|
FROM node:16 AS frontend-builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /frontend
|
||||||
|
|
||||||
COPY ./frontend .
|
COPY frontend .
|
||||||
|
|
||||||
RUN yarn install \
|
RUN yarn install \
|
||||||
--prefer-offline \
|
--prefer-offline \
|
||||||
|
@ -26,14 +29,10 @@ ENV PYTHONUNBUFFERED=1 \
|
||||||
PIP_NO_CACHE_DIR=off \
|
PIP_NO_CACHE_DIR=off \
|
||||||
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||||
PIP_DEFAULT_TIMEOUT=100 \
|
PIP_DEFAULT_TIMEOUT=100 \
|
||||||
POETRY_HOME="/opt/poetry" \
|
VENV_PATH="/opt/mealie"
|
||||||
POETRY_VIRTUALENVS_IN_PROJECT=true \
|
|
||||||
POETRY_NO_INTERACTION=1 \
|
|
||||||
PYSETUP_PATH="/opt/pysetup" \
|
|
||||||
VENV_PATH="/opt/pysetup/.venv"
|
|
||||||
|
|
||||||
# prepend poetry and venv to path
|
# prepend venv to path
|
||||||
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"
|
ENV PATH="$VENV_PATH/bin:$PATH"
|
||||||
|
|
||||||
# create user account
|
# create user account
|
||||||
RUN useradd -u 911 -U -d $MEALIE_HOME -s /bin/bash abc \
|
RUN useradd -u 911 -U -d $MEALIE_HOME -s /bin/bash abc \
|
||||||
|
@ -41,31 +40,81 @@ RUN useradd -u 911 -U -d $MEALIE_HOME -s /bin/bash abc \
|
||||||
&& mkdir $MEALIE_HOME
|
&& mkdir $MEALIE_HOME
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
# Builder Image
|
# Backend Package Build
|
||||||
###############################################
|
###############################################
|
||||||
FROM python-base as builder-base
|
FROM python-base AS backend-builder
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install --no-install-recommends -y \
|
&& apt-get install --no-install-recommends -y \
|
||||||
curl \
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
ENV POETRY_HOME="/opt/poetry" \
|
||||||
|
POETRY_NO_INTERACTION=1
|
||||||
|
|
||||||
|
# prepend poetry to path
|
||||||
|
ENV PATH="$POETRY_HOME/bin:$PATH"
|
||||||
|
|
||||||
|
# install poetry - respects $POETRY_VERSION & $POETRY_HOME
|
||||||
|
ENV POETRY_VERSION=2.0.1
|
||||||
|
RUN curl -sSL https://install.python-poetry.org | python3 -
|
||||||
|
|
||||||
|
# install poetry plugins needed to build the package
|
||||||
|
RUN poetry self add "poetry-plugin-export>=1.9"
|
||||||
|
|
||||||
|
WORKDIR /mealie
|
||||||
|
|
||||||
|
# copy project files here to ensure they will be cached.
|
||||||
|
COPY poetry.lock pyproject.toml ./
|
||||||
|
COPY mealie ./mealie
|
||||||
|
|
||||||
|
# Copy frontend to package it into the wheel
|
||||||
|
COPY --from=frontend-builder /frontend/dist ./mealie/frontend
|
||||||
|
|
||||||
|
# Build the source and binary package
|
||||||
|
RUN poetry build --output=dist
|
||||||
|
|
||||||
|
# Create the requirements file, which is used to install the built package and
|
||||||
|
# its pinned dependencies later. mealie is included to ensure the built one is
|
||||||
|
# what's installed.
|
||||||
|
RUN export MEALIE_VERSION=$(poetry version --short) \
|
||||||
|
&& poetry export --only=main --extras=pgsql --output=dist/requirements.txt \
|
||||||
|
&& echo "mealie[pgsql]==$MEALIE_VERSION \\" >> dist/requirements.txt \
|
||||||
|
&& poetry run pip hash dist/mealie-$MEALIE_VERSION-py3-none-any.whl | tail -n1 | tr -d '\n' >> dist/requirements.txt \
|
||||||
|
&& echo " \\" >> dist/requirements.txt \
|
||||||
|
&& poetry run pip hash dist/mealie-$MEALIE_VERSION.tar.gz | tail -n1 >> dist/requirements.txt
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
# Package Container
|
||||||
|
# Only role is to hold the packages, or be overriden by a --build-context flag.
|
||||||
|
###############################################
|
||||||
|
FROM scratch AS packages
|
||||||
|
COPY --from=backend-builder /mealie/dist /
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
# Python Virtual Environment Build
|
||||||
|
###############################################
|
||||||
|
# Install packages required to build the venv, in parallel to building the wheel
|
||||||
|
FROM python-base AS venv-builder-base
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install --no-install-recommends -y \
|
||||||
build-essential \
|
build-essential \
|
||||||
libpq-dev \
|
libpq-dev \
|
||||||
libwebp-dev \
|
libwebp-dev \
|
||||||
# LDAP Dependencies
|
# LDAP Dependencies
|
||||||
libsasl2-dev libldap2-dev libssl-dev \
|
libsasl2-dev libldap2-dev libssl-dev \
|
||||||
gnupg gnupg2 gnupg1 \
|
gnupg gnupg2 gnupg1 \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
&& pip install -U --no-cache-dir pip
|
RUN python3 -m venv --upgrade-deps $VENV_PATH
|
||||||
|
|
||||||
# install poetry - respects $POETRY_VERSION & $POETRY_HOME
|
# Install the wheel and all dependencies into the venv
|
||||||
ENV POETRY_VERSION=1.3.1
|
FROM venv-builder-base AS venv-builder
|
||||||
RUN curl -sSL https://install.python-poetry.org | python3 -
|
|
||||||
|
|
||||||
# copy project requirement files here to ensure they will be cached.
|
# Copy built package (wheel) and its dependency requirements
|
||||||
WORKDIR $PYSETUP_PATH
|
COPY --from=packages * /dist/
|
||||||
COPY ./poetry.lock ./pyproject.toml ./
|
|
||||||
|
|
||||||
# install runtime deps - uses $POETRY_VIRTUALENVS_IN_PROJECT internally
|
# Install the wheel with exact versions of dependencies into the venv
|
||||||
RUN poetry install -E pgsql --only main
|
RUN . $VENV_PATH/bin/activate \
|
||||||
|
&& pip install --require-hashes -r /dist/requirements.txt --find-links /dist
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
# CRFPP Image
|
# CRFPP Image
|
||||||
|
@ -96,39 +145,25 @@ RUN apt-get update \
|
||||||
# create directory used for Docker Secrets
|
# create directory used for Docker Secrets
|
||||||
RUN mkdir -p /run/secrets
|
RUN mkdir -p /run/secrets
|
||||||
|
|
||||||
# copying poetry and venv into image
|
# copy CRF++ and add it to the library path
|
||||||
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
|
|
||||||
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
|
|
||||||
|
|
||||||
ENV LD_LIBRARY_PATH=/usr/local/lib
|
ENV LD_LIBRARY_PATH=/usr/local/lib
|
||||||
COPY --from=crfpp /usr/local/lib/ /usr/local/lib
|
COPY --from=crfpp /usr/local/lib/ /usr/local/lib
|
||||||
COPY --from=crfpp /usr/local/bin/crf_learn /usr/local/bin/crf_learn
|
COPY --from=crfpp /usr/local/bin/crf_learn /usr/local/bin/crf_learn
|
||||||
COPY --from=crfpp /usr/local/bin/crf_test /usr/local/bin/crf_test
|
COPY --from=crfpp /usr/local/bin/crf_test /usr/local/bin/crf_test
|
||||||
|
|
||||||
# copy backend
|
# Copy venv into image. It contains a fully-installed mealie backend and frontend.
|
||||||
COPY ./mealie $MEALIE_HOME/mealie
|
COPY --from=venv-builder $VENV_PATH $VENV_PATH
|
||||||
COPY ./poetry.lock ./pyproject.toml $MEALIE_HOME/
|
|
||||||
|
|
||||||
# venv already has runtime deps installed we get a quicker install
|
|
||||||
WORKDIR $MEALIE_HOME
|
|
||||||
RUN . $VENV_PATH/bin/activate && poetry install -E pgsql --only main
|
|
||||||
WORKDIR /
|
|
||||||
|
|
||||||
# Grab CRF++ Model Release
|
# Grab CRF++ Model Release
|
||||||
RUN python $MEALIE_HOME/mealie/scripts/install_model.py
|
RUN python -m mealie.scripts.install_model
|
||||||
|
|
||||||
VOLUME [ "$MEALIE_HOME/data/" ]
|
VOLUME [ "$MEALIE_HOME/data/" ]
|
||||||
ENV APP_PORT=9000
|
ENV APP_PORT=9000
|
||||||
|
|
||||||
EXPOSE ${APP_PORT}
|
EXPOSE ${APP_PORT}
|
||||||
|
|
||||||
HEALTHCHECK CMD python $MEALIE_HOME/mealie/scripts/healthcheck.py || exit 1
|
HEALTHCHECK CMD python -m mealie.scripts.healthcheck || exit 1
|
||||||
|
|
||||||
# ----------------------------------
|
|
||||||
# Copy Frontend
|
|
||||||
|
|
||||||
ENV STATIC_FILES=/spa/static
|
|
||||||
COPY --from=builder /app/dist ${STATIC_FILES}
|
|
||||||
|
|
||||||
ENV HOST 0.0.0.0
|
ENV HOST 0.0.0.0
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ init() {
|
||||||
cd /app
|
cd /app
|
||||||
|
|
||||||
# Activate our virtual environment here
|
# Activate our virtual environment here
|
||||||
. /opt/pysetup/.venv/bin/activate
|
. /opt/mealie/bin/activate
|
||||||
}
|
}
|
||||||
|
|
||||||
change_user
|
change_user
|
||||||
|
@ -41,4 +41,4 @@ init
|
||||||
# Start API
|
# Start API
|
||||||
HOST_IP=`/sbin/ip route|awk '/default/ { print $3 }'`
|
HOST_IP=`/sbin/ip route|awk '/default/ { print $3 }'`
|
||||||
|
|
||||||
exec python /app/mealie/main.py
|
exec mealie
|
||||||
|
|
40
docs/docs/contributors/developers-guide/building-packages.md
Normal file
40
docs/docs/contributors/developers-guide/building-packages.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# Building Packages
|
||||||
|
|
||||||
|
Released packages are [built and published via GitHub actions](maintainers.md#drafting-releases).
|
||||||
|
|
||||||
|
## Python packages
|
||||||
|
|
||||||
|
To build Python packages locally for testing, use [`task`](starting-dev-server.md#without-dev-containers). After installing `task`, run `task py:package` to perform all the steps needed to build the package and a requirements file. To do it manually, run:
|
||||||
|
```sh
|
||||||
|
pushd frontend
|
||||||
|
yarnpkg install
|
||||||
|
yarnpkg generate
|
||||||
|
popd
|
||||||
|
rm -r mealie/frontend
|
||||||
|
cp -a frontend/dist mealie/frontend
|
||||||
|
poetry build
|
||||||
|
poetry export -n --only=main --extras=pgsql --output=dist/requirements.txt
|
||||||
|
MEALIE_VERSION=$(poetry version --short)
|
||||||
|
echo "mealie[pgsql]==${MEALIE_VERSION} \\" >> dist/requirements.txt
|
||||||
|
poetry run pip hash dist/mealie-${MEALIE_VERSION}-py3-none-any.whl | tail -n1 | tr -d '\n' >> dist/requirements.txt
|
||||||
|
echo " \\" >> dist/requirements.txt
|
||||||
|
poetry run pip hash dist/mealie-${MEALIE_VERSION}.tar.gz | tail -n1 >> dist/requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
The Python package can be installed with all of its dependencies pinned to the versions tested by the developers with:
|
||||||
|
```sh
|
||||||
|
pip3 install -r dist/requirements.txt --find-links dist
|
||||||
|
```
|
||||||
|
|
||||||
|
To install with the latest but still compatible dependency versions, instead run `pip3 install dist/mealie-$VERSION-py3-none-any.whl` (where `$VERSION` is the version of mealie to install).
|
||||||
|
|
||||||
|
## Docker image
|
||||||
|
One way to build the Docker image is to run the following command in the project root directory:
|
||||||
|
```sh
|
||||||
|
docker build --tag mealie:dev --file docker/Dockerfile --build-arg COMMIT=$(git rev-parse HEAD) .
|
||||||
|
```
|
||||||
|
|
||||||
|
The Docker image can be built from the pre-built Python packages with the task command `task docker:build-from-package`. This is equivalent to:
|
||||||
|
```sh
|
||||||
|
docker build --tag mealie:dev --file docker/Dockerfile --build-arg COMMIT=$(git rev-parse HEAD) --build-context packages=dist .
|
||||||
|
```
|
|
@ -99,6 +99,7 @@ nav:
|
||||||
- Non-Code: "contributors/non-coders.md"
|
- Non-Code: "contributors/non-coders.md"
|
||||||
- Translating: "contributors/translating.md"
|
- Translating: "contributors/translating.md"
|
||||||
- Developers Guide:
|
- Developers Guide:
|
||||||
|
- Building Packages: "contributors/developers-guide/building-packages.md"
|
||||||
- Code Contributions: "contributors/developers-guide/code-contributions.md"
|
- Code Contributions: "contributors/developers-guide/code-contributions.md"
|
||||||
- Dev Getting Started: "contributors/developers-guide/starting-dev-server.md"
|
- Dev Getting Started: "contributors/developers-guide/starting-dev-server.md"
|
||||||
- Database Changes: "contributors/developers-guide/database-changes.md"
|
- Database Changes: "contributors/developers-guide/database-changes.md"
|
||||||
|
|
|
@ -12,6 +12,7 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
from mealie.core.settings.themes import Theme
|
from mealie.core.settings.themes import Theme
|
||||||
|
|
||||||
from .db_providers import AbstractDBProvider, db_provider_factory
|
from .db_providers import AbstractDBProvider, db_provider_factory
|
||||||
|
from .static import PACKAGE_DIR
|
||||||
|
|
||||||
|
|
||||||
class ScheduleTime(NamedTuple):
|
class ScheduleTime(NamedTuple):
|
||||||
|
@ -109,7 +110,7 @@ class AppSettings(AppLoggingSettings):
|
||||||
BASE_URL: str = "http://localhost:8080"
|
BASE_URL: str = "http://localhost:8080"
|
||||||
"""trailing slashes are trimmed (ex. `http://localhost:8080/` becomes ``http://localhost:8080`)"""
|
"""trailing slashes are trimmed (ex. `http://localhost:8080/` becomes ``http://localhost:8080`)"""
|
||||||
|
|
||||||
STATIC_FILES: str = ""
|
STATIC_FILES: str = str(PACKAGE_DIR / "frontend")
|
||||||
"""path to static files directory (ex. `mealie/dist`)"""
|
"""path to static files directory (ex. `mealie/dist`)"""
|
||||||
|
|
||||||
IS_DEMO: bool = False
|
IS_DEMO: bool = False
|
||||||
|
|
|
@ -5,4 +5,5 @@ from mealie import __version__
|
||||||
APP_VERSION = __version__
|
APP_VERSION = __version__
|
||||||
|
|
||||||
CWD = Path(__file__).parent
|
CWD = Path(__file__).parent
|
||||||
|
PACKAGE_DIR = CWD.parent.parent
|
||||||
BASE_DIR = CWD.parent.parent.parent
|
BASE_DIR = CWD.parent.parent.parent
|
||||||
|
|
|
@ -6,7 +6,7 @@ from mealie.core.logger.config import log_config
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
"app:app",
|
"mealie.app:app",
|
||||||
host=settings.API_HOST,
|
host=settings.API_HOST,
|
||||||
port=settings.API_PORT,
|
port=settings.API_PORT,
|
||||||
log_level=settings.LOG_LEVEL.lower(),
|
log_level=settings.LOG_LEVEL.lower(),
|
||||||
|
|
|
@ -4,9 +4,13 @@ description = "A Recipe Manager"
|
||||||
license = "AGPL"
|
license = "AGPL"
|
||||||
name = "mealie"
|
name = "mealie"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
|
include = [
|
||||||
|
# Explicit include to override .gitignore when packaging the frontend
|
||||||
|
{ path = "mealie/frontend/**/*", format = ["sdist", "wheel"] }
|
||||||
|
]
|
||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
start = "mealie.app:main"
|
mealie = "mealie.main:main"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
Jinja2 = "^3.1.2"
|
Jinja2 = "^3.1.2"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue