Skip to content

Commit

Permalink
Merge branch 'main' into feat/docs-update
Browse files Browse the repository at this point in the history
  • Loading branch information
fubuloubu authored Oct 28, 2024
2 parents 446d098 + db17fdd commit 9df70c8
Show file tree
Hide file tree
Showing 9 changed files with 469 additions and 167 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ jobs:
with:
python-version: "3.10"

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install .[doc]
- name: Ape Docs
uses: apeworx/sphinx-ape@main
with:
Expand Down
89 changes: 0 additions & 89 deletions build_docs.py

This file was deleted.

8 changes: 7 additions & 1 deletion docs/commands/cluster.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Cloud Platform
==============
CLI commands for interacting with the Silverback Platform.

.. click:: silverback._cli:login
:prog: silverback login
Expand All @@ -8,7 +9,12 @@ Cloud Platform
.. click:: silverback._cli:cluster
:prog: silverback cluster
:nested: full
:commands: workspaces, new, list, info, health
:commands: new, update, list, info, health

.. click:: silverback._cli:workspaces
:prog: silverback cluster workspaces
:nested: full
:commands: new, list, info, update, delete

.. click:: silverback._cli:vars
:prog: silverback cluster vars
Expand Down
1 change: 1 addition & 0 deletions docs/commands/run.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Local Development
=================
CLI commands for local development of running Silverback bots and task workers.

.. click:: silverback._cli:run
:prog: silverback run
Expand Down
3 changes: 3 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.. dynamic-toc-tree::
:commands:
- run
- cluster
144 changes: 144 additions & 0 deletions silverback/_build_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import shlex
import subprocess
from functools import singledispatchmethod
from pathlib import Path
from typing import Union

import click
from ape.utils.os import clean_path

DOCKERFILE_CONTENT = """
FROM ghcr.io/apeworx/silverback:stable
USER root
WORKDIR /app
RUN chown harambe:harambe /app
USER harambe
"""


# Note: Python3.12 supports subclassing pathlib.Path
class BasePath(Path):
_flavour = type(Path())._flavour # type: ignore


class FilePath(BasePath):
"""A subclass of Path representing a file."""


class DirPath(BasePath):
"""A subclass of Path representing a path"""


def get_path(path: Path):
if path.is_file():
return FilePath(str(path))
elif path.is_dir():
return DirPath(str(path))
else:
raise ValueError(f"{path} is neither a file nor a directory")


PathType = Union["FilePath", "DirPath"]


def generate_dockerfiles(path: Path):
path = get_path(path)
dg = DockerfileGenerator()
dg.generate_dockerfiles(path)


def build_docker_images(path: Path):
DockerfileGenerator.build_images(path)


class DockerfileGenerator:

@property
def dockerfile_name(self):
return self._dockerfile_name

@dockerfile_name.setter
def dockerfile_name(self, name):
self._dockerfile_name = name

@singledispatchmethod
def generate_dockerfiles(self, path: PathType):
"""
Will generate a file based on path type
"""
raise NotImplementedError(f"Path type {type(path)} not supported")

@generate_dockerfiles.register
def _(self, path: FilePath):
dockerfile_content = self._check_for_requirements(DOCKERFILE_CONTENT)
self.dockerfile_name = f"Dockerfile.{path.parent.name}-bot"
dockerfile_content += f"COPY {path.name}/ /app/bot.py\n"
self._build_helper(dockerfile_content)

@generate_dockerfiles.register
def _(self, path: DirPath):
bots = self._get_all_bot_files(path)
for bot in bots:
dockerfile_content = self._check_for_requirements(DOCKERFILE_CONTENT)
if bot.name == "__init__.py" or bot.name == "bot.py":
self.dockerfile_name = f"Dockerfile.{bot.parent.parent.name}-bot"
dockerfile_content += f"COPY {path.name}/ /app/bot\n"
else:
self.dockerfile_name = f"Dockerfile.{bot.name.replace('.py', '')}"
dockerfile_content += f"COPY {path.name}/{bot.name} /app/bot.py\n"
self._build_helper(dockerfile_content)

def _build_helper(self, dockerfile_c: str):
"""
Used in multiple places in build.
"""
dockerfile_path = Path.cwd() / ".silverback-images" / self.dockerfile_name
dockerfile_path.parent.mkdir(exist_ok=True)
dockerfile_path.write_text(dockerfile_c.strip() + "\n")
click.echo(f"Generated {clean_path(dockerfile_path)}")

def _check_for_requirements(self, dockerfile_content):
if (Path.cwd() / "requirements.txt").exists():
dockerfile_content += "COPY requirements.txt .\n"
dockerfile_content += (
"RUN pip install --upgrade pip && pip install -r requirements.txt\n"
)

if (Path.cwd() / "ape-config.yaml").exists():
dockerfile_content += "COPY ape-config.yaml .\n"
dockerfile_content += "RUN ape plugins install -U .\n"

return dockerfile_content

def _get_all_bot_files(self, path: DirPath):
files = sorted({file for file in path.iterdir() if file.is_file()}, reverse=True)
bots = []
for file in files:
if file.name == "__init__.py" or file.name == "bot.py":
bots = [file]
break
bots.append(file)
return bots

@staticmethod
def build_images(path: Path):
dockerfiles = {file for file in path.iterdir() if file.is_file()}
for file in dockerfiles:
try:
command = shlex.split(
"docker build -f "
f"./{file.parent.name}/{file.name} "
f"-t {file.name.split('.')[1]}:latest ."
)
result = subprocess.run(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
check=True,
)
click.echo(result.stdout)
except subprocess.CalledProcessError as e:
click.echo("Error during docker build:")
click.echo(e.stderr)
raise
Loading

0 comments on commit 9df70c8

Please sign in to comment.