diff --git a/Dockerfile b/Dockerfile index 3517970..4545601 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,8 @@ # Dockerfile: https://github.com/max-pfeiffer/python-poetry/blob/main/build/Dockerfile ARG BASE_IMAGE FROM ${BASE_IMAGE} -ARG APPLICATION_SERVER_PORT +RUN apt update +RUN apt install -y git LABEL maintainer="Mike DuPont " @@ -16,36 +17,28 @@ ENV PYTHONUNBUFFERED=1 \ POETRY_VIRTUALENVS_IN_PROJECT=true \ POETRY_CACHE_DIR="/application_root/.cache" \ VIRTUAL_ENVIRONMENT_PATH="/application_root/.venv" \ - APPLICATION_SERVER_PORT=$APPLICATION_SERVER_PORT + POETRY_HOME="/opt/poetry" +# https://python-poetry.org/docs/#installing-manually +RUN python -m venv ${VIRTUAL_ENVIRONMENT_PATH} + # Adding the virtual environment to PATH in order to "activate" it. # https://docs.python.org/3/library/venv.html#how-venvs-work ENV PATH="$VIRTUAL_ENVIRONMENT_PATH/bin:$PATH" -# Principle of least privilege: create a new user for running the application -RUN groupadd -g 1001 python_application && \ - useradd -r -u 1001 -g python_application python_application - # Set the WORKDIR to the application root. # https://www.uvicorn.org/settings/#development # https://docs.docker.com/engine/reference/builder/#workdir WORKDIR ${PYTHONPATH} -RUN chown python_application:python_application ${PYTHONPATH} -# Create cache directory and set permissions because user 1001 has no home -# and poetry cache directory. # https://python-poetry.org/docs/configuration/#cache-directory -RUN mkdir ${POETRY_CACHE_DIR} && chown python_application:python_application ${POETRY_CACHE_DIR} - -# Use the unpriveledged user to run the application -USER 1001 +RUN mkdir ${POETRY_CACHE_DIR} WORKDIR /opt/ai-ticket COPY pyproject.toml /opt/ai-ticket/ COPY setup.cfg /opt/ai-ticket/ +COPY README.md /opt/ai-ticket/ COPY requirements.txt /opt/ai-ticket/ COPY ./src/ /opt/ai-ticket/src/ -RUN pip install /opt/ai-ticket/ - -RUN apt update -RUN apt install -y git -RUN pip install --trusted-host pypi.python.org -r requirements.txt + +RUN ls ${VIRTUAL_ENVIRONMENT_PATH}/bin/activate +RUN pip install /opt/ai-ticket/ && pip install --trusted-host pypi.python.org -r requirements.txt diff --git a/Makefile b/Makefile index 53433c5..6395f33 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ +test_build: + sudo docker-compose build + test: bash ./runact.sh diff --git a/README.md b/README.md index 66e667f..43a8cfd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ai-ticket +# AI-Ticket The AI Ticket system to handle the AI with tickets. Human Powered AI-Ops to Help you with the last mile of your AI code generated system. @@ -35,3 +35,11 @@ Welcome to our innovative user-driven workflow, designed to empower you to inter - Be mindful of providing timely and appropriate responses to prevent workflow stalls. This user-driven ticket-based workflow offers flexibility, control, and a unique way to collaborate with our system. Dive in, generate tickets, and explore the possibilities of this interactive and dynamic approach. + + +# Infrastructure + +The docker images are organized like this : + +* act_base is the foundation of all actions. +* poetry_base is contains the poetry magic layer with shared containers. diff --git a/docker-compose.yml b/docker-compose.yml index 979f9d5..7c9876e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,48 @@ version: '3' services: - ai_ticket: - build: . - act_base: - # the base image of github action + + act_base: #root base of action build: vendor/act_base + + poetry_base: # use poetry + build: + context: vendor/python-poetry/build + args: + OFFICIAL_PYTHON_IMAGE: act_base + POETRY_VERSION: 1.6.1 + depends_on: + - act_base + + ai_ticket: # the ticket to unite + build: + context: . + args: + BASE_IMAGE: act_base + depends_on: + - poetry_base + + basic_agent: #basic agnet + build: + context: vendor/basic_agent/ + args: + OFFICIAL_PYTHON_IMAGE: act_base + depends_on: + - ai_ticket + + mockopenai: # interface + depends_on: + - ai_ticket + environment: + - GITHUB_PAT=${GITHUB_PAT} + - GITHUB_REPO=${GITHUB_REPO} + build: + context: vendor/lollms/ + args: + OFFICIAL_PYTHON_IMAGE: localhost/ai-ticket_ai_ticket:latest + ports: + - "5000:8080" - autogpt: + autogpt: #the beast entrypoint: bash -c "poetry run pip install /opt/ai-ticket && poetry run autogpt --install-plugin-deps --skip-news -y --ai-name 'meta-autogpt' --ai-role 'you will introspect autogpt and reveal its internals via reflection and comprehension' --ai-goal 'Observe your behaviour' --ai-goal 'Reflect over your outcomes' --ai-goal 'Orient yourself to your knowledge' --ai-goal 'Decide on your next step' --ai-goal 'Act on your chosen next experiment' " # uncomment thse next 3 lines for debugging @@ -20,20 +56,10 @@ services: - OPENAI_API_BASE=http://mockopenai:8080/v1 build: context: vendor/Auto-GPT/ - depends_on: - - ai_ticket - - mockopenai + dockerfile: slim/Dockerfile + args: + OFFICIAL_PYTHON_IMAGE: localhost/ai-ticket_ai_ticket:latest - mockopenai: depends_on: - - ai_ticket - - environment: - - GITHUB_PAT=${GITHUB_PAT} - - GITHUB_REPO=${GITHUB_REPO} - - build: - context: vendor/lollms/ - ports: - - "5000:8080" - + - basic_agent + - mockopenai diff --git a/dockerbuild/Dockerfile b/dockerbuild/Dockerfile deleted file mode 100644 index b8a9eaa..0000000 --- a/dockerbuild/Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# The Poetry installation is provided through the base image. Please check the -# base image if you interested in the details. -# Base image: https://hub.docker.com/r/pfeiffermax/python-poetry -# Dockerfile: https://github.com/max-pfeiffer/python-poetry/blob/main/build/Dockerfile -ARG BASE_IMAGE -FROM ${BASE_IMAGE} -ARG APPLICATION_SERVER_PORT - -LABEL maintainer="Max Pfeiffer " - - # https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUNBUFFERED -ENV PYTHONUNBUFFERED=1 \ - # https://docs.python.org/3/using/cmdline.html#envvar-PYTHONDONTWRITEBYTECODE - PYTHONDONTWRITEBYTECODE=1 \ - PYTHONPATH=/application_root \ - # https://python-poetry.org/docs/configuration/#virtualenvsin-project - POETRY_VIRTUALENVS_IN_PROJECT=true \ - POETRY_CACHE_DIR="/application_root/.cache" \ - VIRTUAL_ENVIRONMENT_PATH="/application_root/.venv" \ - APPLICATION_SERVER_PORT=$APPLICATION_SERVER_PORT - -# Adding the virtual environment to PATH in order to "activate" it. -# https://docs.python.org/3/library/venv.html#how-venvs-work -ENV PATH="$VIRTUAL_ENVIRONMENT_PATH/bin:$PATH" - -# Principle of least privilege: create a new user for running the application -RUN groupadd -g 1001 python_application && \ - useradd -r -u 1001 -g python_application python_application - -# Set the WORKDIR to the application root. -# https://www.uvicorn.org/settings/#development -# https://docs.docker.com/engine/reference/builder/#workdir -WORKDIR ${PYTHONPATH} -RUN chown python_application:python_application ${PYTHONPATH} - -# Create cache directory and set permissions because user 1001 has no home -# and poetry cache directory. -# https://python-poetry.org/docs/configuration/#cache-directory -RUN mkdir ${POETRY_CACHE_DIR} && chown python_application:python_application ${POETRY_CACHE_DIR} - -# Document the exposed port -# https://docs.docker.com/engine/reference/builder/#expose -EXPOSE ${APPLICATION_SERVER_PORT} - -# Use the unpriveledged user to run the application -USER 1001 - -# Run the uvicorn application server. -CMD exec uvicorn --workers 1 --host 0.0.0.0 --port $APPLICATION_SERVER_PORT app.main:app diff --git a/dockerbuild/images.py b/dockerbuild/images.py index 1b24e3f..9dfdc72 100644 --- a/dockerbuild/images.py +++ b/dockerbuild/images.py @@ -1,32 +1,10 @@ -from pathlib import Path -from typing import Optional +from dockerbuild.baseimage import ExampleApplicationImage import docker +from pathlib import Path from docker.models.images import Image -from dockerbuild.constants import ( - BASE_IMAGES, - APPLICATION_SERVER_PORT, -) - - -class DockerImage: - def __init__( - self, - docker_client: docker.client, - target_architecture: str, - version: str, - ): - self.docker_client: docker.client = docker_client - self.dockerfile_name: str = "Dockerfile" - self.dockerfile_directory: Optional[Path] = None - self.image_name: Optional[str] = None - self.image_tag: Optional[str] = None - self.version: Optional[str] = version - self.target_architecture: str = target_architecture - - -class AITicketPoetryImage(DockerImage): +class AITicketPoetryImage(ExampleApplicationImage): def __init__( self, docker_client: docker.client, @@ -37,59 +15,11 @@ def __init__( # An image name is made up of slash-separated name components, # optionally prefixed by a registry hostname. # see: https://docs.docker.com/engine/reference/commandline/tag/ - self.image_name: str = "h4ckermike/ai-ticket:test_ai_ticket" - self.dockerfile_directory: Path = Path(__file__).parent.resolve() - - def build(self) -> Image: - self.image_tag: str = f"{self.version}-{self.target_architecture}" - - buildargs: dict[str, str] = { - "BASE_IMAGE": BASE_IMAGES[self.target_architecture], - "APPLICATION_SERVER_PORT": APPLICATION_SERVER_PORT, - } - - image: Image = self.docker_client.images.build( - path=str(self.dockerfile_directory), - dockerfile=self.dockerfile_name, - tag=f"{self.image_name}:{self.image_tag}", - buildargs=buildargs, - )[0] - return image - - -class ExampleApplicationImage(DockerImage): - def build( - self, - target: str, - base_image_tag: str, - ) -> Image: - - self.image_tag = f"{self.version}-{self.target_architecture}" + self.image_name: str = "h4ckermike/ai-ticket" + self.dockerfile_directory: Path = Path(__file__).parent.parent.resolve() - buildargs: dict[str, str] = { - "BASE_IMAGE": base_image_tag, - } - print("buildargs",dict( - args=buildargs, - path=str(self.dockerfile_directory), - dockerfile=self.dockerfile_name, - tag=f"{self.image_name}:{self.image_tag}", - #target=target, - buildargs=buildargs, - )) - - image: Image = self.docker_client.images.build( - - path=str(self.dockerfile_directory), - dockerfile=self.dockerfile_name, - tag=f"{self.image_name}:{self.image_tag}", - #target=target, - buildargs=buildargs, - )[0] - return image - -class ActBaseImage(ExampleApplicationImage): +class AutoGptImage(ExampleApplicationImage): def __init__( self, docker_client: docker.client, @@ -97,14 +27,31 @@ def __init__( version: str, ): super().__init__(docker_client, target_architecture, version) - # An image name is made up of slash-separated name components, - # optionally prefixed by a registry hostname. - # see: https://docs.docker.com/engine/reference/commandline/tag/ self.image_name: str = "h4ckermike/act_base" self.dockerfile_directory: Path = ( Path(__file__).parent.parent.resolve() / "vendor" / "act_base" ) +class ActBaseImage(ExampleApplicationImage): + def __init__( self, docker_client: docker.client, target_architecture: str, version: str, + ): + super().__init__(docker_client, target_architecture, version) + self.image_name: str = "h4ckermike/autogpt" + self.dockerfile_directory: Path = ( + Path(__file__).parent.parent.resolve() + / "vendor" + / "Auto-GPT/" + ) + +class OpenAIImage(ExampleApplicationImage): + def __init__( self, docker_client: docker.client,target_architecture: str,version: str ): + super().__init__(docker_client, target_architecture, version) + self.image_name: str = "h4ckermike/mockopenai" + self.dockerfile_directory: Path = ( + Path(__file__).parent.parent.resolve() + / "vendor" + / "lollms/" + ) diff --git a/dockerbuild/publish.py b/dockerbuild/publish.py index f41f993..714b77a 100644 --- a/dockerbuild/publish.py +++ b/dockerbuild/publish.py @@ -1,11 +1,13 @@ import click import docker -BASE_IMAGE="nikolaik/python-nodejs:python3.10-nodejs20" + from docker.client import DockerClient + from dockerbuild.constants import ( TARGET_ARCHITECTURES, ) -from dockerbuild.images import ActBaseImage +import dockerbuild.images +from dockerbuild.baseimage import BASE_IMAGE @click.command() @click.option( @@ -28,29 +30,24 @@ def main( version_tag: str, registry: str, ) -> None: - docker_client: DockerClient = docker.from_env() - + docker_client: DockerClient = docker.from_env() for target_architecture in TARGET_ARCHITECTURES: - new_uvicorn_gunicorn_poetry_image: UvicornPoetryImage = ( - ActBaseImage(docker_client, target_architecture, version_tag) - ) - - # Delete old existing images - for old_image in docker_client.images.list( - new_uvicorn_gunicorn_poetry_image.image_name - ): - for tag in old_image.tags: - print("tag",tag) - docker_client.images.remove(tag, force=True) - - new_uvicorn_gunicorn_poetry_image.build( - target=target_architecture, - base_image_tag=BASE_IMAGE, - ) - - # https://docs.docker.com/engine/reference/commandline/push/ - # https://docs.docker.com/engine/reference/commandline/tag/ - # https://docs.docker.com/engine/reference/commandline/image_tag/ + #import pdb + #pdb.set_trace() + for x in dir(dockerbuild.images) : + cls = getattr(dockerbuild.images,x) + if not isinstance(cls,type): + continue + print(cls) + new_uvicorn_gunicorn_poetry_image = (cls(docker_client,target_architecture,version_tag)) + if new_uvicorn_gunicorn_poetry_image: + for old_image in docker_client.images.list(new_uvicorn_gunicorn_poetry_image.image_name): + for tag in old_image.tags: + print("tag",tag) + docker_client.images.remove(tag, force=True) + new_uvicorn_gunicorn_poetry_image.build( + target=target_architecture,base_image_tag=BASE_IMAGE + ) if docker_hub_username and docker_hub_password: login_kwargs: dict = { "username": docker_hub_username, @@ -58,9 +55,7 @@ def main( } if registry: login_kwargs["registry"] = registry - docker_client.login(**login_kwargs) - if registry: repository: str = ( f"{registry}/{new_uvicorn_gunicorn_poetry_image.image_name}" @@ -68,14 +63,15 @@ def main( else: repository: str = new_uvicorn_gunicorn_poetry_image.image_name - for line in docker_client.images.push( - repository, - tag=new_uvicorn_gunicorn_poetry_image.image_tag, - stream=True, - decode=True, - ): - print(line) - docker_client.close() + if False: + for line in docker_client.images.push( + repository, + tag=new_uvicorn_gunicorn_poetry_image.image_tag, + stream=True, + decode=True, + ): + print(line) + docker_client.close() if __name__ == "__main__": diff --git a/pyproject.toml b/pyproject.toml index 864896e..2158d50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -python = "^3.7" +#python = "^3.11" requires = [ "setuptools>=42", "wheel", @@ -40,7 +40,7 @@ classifiers = [ # [tool.poetry.scripts] # [tool.poetry.dependencies] [tool.poetry.dependencies] -python = "3.11.4" +#python = "3.11.4" click = "8.1.7" docker = "6.1.3"