From b0968eaa308cda73534b9a7ef27f9ce58afe1820 Mon Sep 17 00:00:00 2001 From: Eric Anderton Date: Tue, 17 Oct 2023 11:00:25 -0400 Subject: [PATCH] cleaned up __root__ references, fixed bugs, added small features - Fixed pyproject.toml dependencies - Added model properties to encapsulate `__root__` - Added online help for commands - Added `show-config` command - Added `--basedir` CLI option - Fixed docker syntax line in base template - Added support for SHELL in stage template - Fixed bug with LABEL k/v pair - Updated test suite --- .github/workflows/docs.yml | 25 +++++++++------ CONTRIBUTING.md | 2 +- TODO.md | 5 ++- docker_printer/cli.py | 31 ++++++++++++------- docker_printer/models.py | 4 +++ .../templates/base.Dockerfile.jinja2 | 2 +- .../templates/stage.Dockerfile.jinja2 | 6 +++- examples/fastapi_app/Dockerfile.synth | 2 +- pyproject.toml | 2 +- requirements.txt | 2 +- 10 files changed, 54 insertions(+), 27 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6368ebf..fdaa55b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -4,15 +4,22 @@ on: - push jobs: - docs_build: + docs: runs-on: ubuntu-latest + permissions: + id-token: write + contents: read steps: - - uses: actions/checkout@v3 - - uses: ammaraskar/sphinx-action@master - with: - docs-folder: "docs/" + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: '3.11' + cache: 'pip' # caching pip dependencies + - run: pip install -r docs/requirements.txt + - run: cd docs && make html - - uses: actions/upload-artifact@v1 - with: - name: DocumentationHTML - path: docs/_build/html/ + - uses: actions/upload-artifact@v3 + with: + name: DocumentationHTML + path: docs/build/html/ + retention-days: 30 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2fab5f7..9c430a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,4 +5,4 @@ 1. Start virtualenv: `source venv/bin/activate` 1. Install dependencies and this project in editable mode: `pip install --editable .` -To run the examples, use the \ No newline at end of file +To run the examples, use the diff --git a/TODO.md b/TODO.md index 8b2f0e3..d880d12 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,6 @@ - Add `setup` feature for modules - Add build profiles to control the generation of the bakefile(s) -- Add duplicate name check to config file validation \ No newline at end of file +- Add duplicate name check to config file validation +- Upgrade to pydantic 2.x +- Unit tests +- Integration (CLI) tests diff --git a/docker_printer/cli.py b/docker_printer/cli.py index 1c95777..c84a84a 100644 --- a/docker_printer/cli.py +++ b/docker_printer/cli.py @@ -23,7 +23,7 @@ def version_callback(value: bool): if value: typer.echo(__version__) raise typer.Exit() - + def base_dir_callback(value: str = None): # Change CWD to target so path resolution works as expected @@ -64,7 +64,7 @@ def _synth(): with open(dockerfile_path, "w", newline="\n") as f: f.write(dockerfile) - for build_config in build_configs.__root__: + for build_config in build_configs.configs: bakefile_path = base_dir() / f"docker-bake.{build_config.name}.json" bakefile = build_config.generate_bakefile(targets) with open(bakefile_path, "w", newline="\n") as f: @@ -80,16 +80,19 @@ def build(name: str = "default"): _, build_configs = _synth() try: - config = next(cfg for cfg in build_configs.__root__ if cfg.name == name) + config = next(cfg for cfg in build_configs.configs if cfg.name == name) except StopIteration: - names = ", ".join(set([x.name for x in build_configs.__root__])) - typer.secho(f"Error: No build config found with name '{name}'", fg=typer.colors.RED) + names = ", ".join(set([x.name for x in build_configs.configs])) + typer.secho( + f"Error: No build config found with name '{name}'", fg=typer.colors.RED + ) typer.secho(f"Valid names: {names}", fg=typer.colors.YELLOW) typer.Exit(1) else: typer.echo(config.build_command) subprocess.run(config.build_command, shell=True) + @app.command() def show_config(): """List the current config files and build targets.""" @@ -97,7 +100,7 @@ def show_config(): target_config_file = targets_file() build_config_file = builds_file() - targets = TargetCollection.parse_obj(yml_load(target_config_file)) + target_configs = TargetCollection.parse_obj(yml_load(target_config_file)) build_configs = BuildConfigCollection.parse_obj(yml_load(build_config_file)) typer.secho("Config files", bold=True, fg=typer.colors.GREEN) @@ -105,11 +108,14 @@ def show_config(): typer.echo(str(build_config_file)) typer.secho("\nTargets", bold=True, fg=typer.colors.GREEN) - for target in targets.__root__: - typer.echo(target) + for target in target_configs.targets: + typer.echo(target.name) + for mod in target.all_modules(): + typer.echo(f" {mod.name}") + typer.echo() typer.secho("\nBuilds", bold=True, fg=typer.colors.GREEN) - for build_config in build_configs.__root__: + for build_config in build_configs.configs: typer.echo(f"{build_config.name} {build_config.image}") @@ -124,7 +130,10 @@ def init( """Initializes a new project tree.""" base_dir = path / "docker-printer" if base_dir.exists(): - typer.secho(f"Error: {base_dir} already exists, cannot initialize new project", fg=typer.colors.RED) + typer.secho( + f"Error: {base_dir} already exists, cannot initialize new project", + fg=typer.colors.RED, + ) typer.Exit(1) base_dir.mkdir(exist_ok=False, parents=False) @@ -138,4 +147,4 @@ def init( *.rendered.yml """.lstrip() ) - ) \ No newline at end of file + ) diff --git a/docker_printer/models.py b/docker_printer/models.py index 61cb11d..976adde 100644 --- a/docker_printer/models.py +++ b/docker_printer/models.py @@ -333,3 +333,7 @@ def build_command(self): class BuildConfigCollection(BaseModel): __root__: List[BuildConfig] + + @property + def configs(self): + return [t for t in self.__root__] diff --git a/docker_printer/resources/templates/base.Dockerfile.jinja2 b/docker_printer/resources/templates/base.Dockerfile.jinja2 index f400f3c..2c71f56 100644 --- a/docker_printer/resources/templates/base.Dockerfile.jinja2 +++ b/docker_printer/resources/templates/base.Dockerfile.jinja2 @@ -1,4 +1,4 @@ -# syntax = docker/dockerfile:1.2 +# syntax=docker/dockerfile:1 {% block pre_init %}{% endblock %} diff --git a/docker_printer/resources/templates/stage.Dockerfile.jinja2 b/docker_printer/resources/templates/stage.Dockerfile.jinja2 index 8375aa8..50ff9a0 100644 --- a/docker_printer/resources/templates/stage.Dockerfile.jinja2 +++ b/docker_printer/resources/templates/stage.Dockerfile.jinja2 @@ -4,7 +4,7 @@ FROM {{ base }} AS {{ name }} {% block labels -%} {% for key, value in labels.items() -%} -LABEL "{{ key }}"={{ value }}" +LABEL "{{ key }}"="{{ value }}" {% endfor %} {%- endblock %} @@ -20,6 +20,10 @@ ENV {{ key }}="{{ value }}" {% endfor %} {%- endblock %} +{% if shell -%} +SHELL {{ shell|tojson|safe }} +{%- endif %} + {% block instructions -%} {% for instr in instructions -%} {{ instr }} diff --git a/examples/fastapi_app/Dockerfile.synth b/examples/fastapi_app/Dockerfile.synth index 44425da..7edbde2 100644 --- a/examples/fastapi_app/Dockerfile.synth +++ b/examples/fastapi_app/Dockerfile.synth @@ -1,4 +1,4 @@ -# syntax = docker/dockerfile:1.2 +# syntax=docker/dockerfile:1 ARG PYTHON_VERSION=3.9 ARG BASE_OS=slim diff --git a/pyproject.toml b/pyproject.toml index a6ffa26..7e760c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ dependencies = [ "pyyaml", "jinja2", "click", - "pydantic", + "pydantic==1.*", "typer", "rich" ] diff --git a/requirements.txt b/requirements.txt index 253aea8..a10375c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,4 @@ jinja2 click pydantic==1.* typer -rich \ No newline at end of file +rich