diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4da07b94..e7b149c2 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,43 +1,34 @@ # Contributing to this project -Thank you for your interest in contributing! We welcome contributions of all kinds, from -bug reports to new features. This document outlines our guidelines to make the process -smooth and effective. +Thank you for your interest in contributing! We welcome contributions of all kinds, from bug reports to new +features. This document outlines our guidelines to make the process smooth and effective. ## Code of Conduct -We are committed to providing a welcoming and respectful community for everyone. We -expect all contributors to adhere to a high standard of conduct. **Harassment, abusive -language, discrimination (including but not limited to racism, sexism, homophobia, -transphobia, ableism, or any other form of prejudice) will not be tolerated.** -Violations may result in removal from the project and/or reporting. +We are committed to providing a welcoming and respectful community for everyone. We expect all contributors to +adhere to a high standard of conduct. **Harassment, abusive language, discrimination (including but not +limited to racism, sexism, homophobia, transphobia, ableism, or any other form of prejudice) will not be +tolerated.** Violations may result in removal from the project and/or reporting. ## How to contribute -1. **Discuss first:** Before tackling a significant change or feature, please open an - issue to discuss your idea. This helps ensure it aligns with the project's goals and - avoids wasted effort. +1. **Discuss first:** Before tackling a significant change or feature, please open an issue to discuss your + idea. This helps ensure it aligns with the project's goals and avoids wasted effort. 2. **Code style & formatting:** We aim for consistent code style throughout the project. - - - Please run any automated formatting tools included in this repository (e.g., - `pre-commit`, `prettier`, `ruff`, `go fmt`). Check the `.editorconfig` or build - scripts for details. + - Please run any automated formatting tools included in this repository (e.g., `pre-commit`, `prettier`, + `ruff`, `go fmt`). Check the `.editorconfig` or build scripts for details. - Try to follow existing coding conventions within the codebase. 3. **Submit a pull request:** When you're ready to contribute: - - Create a pull request against the `main` branch. - In your PR description, _clearly explain_: - **What changed?** A concise summary of your changes. - - **Why did you make this change?** What problem does it solve or what improvement - does it offer? - - **Output Changes (if applicable):** If your changes affect the output of the - project (e.g., UI, logs), please include screenshots _before and after_ to - illustrate the impact. - -4. **Be patient:** We are a small team with limited time dedicated to managing this - repository. We will review pull requests as quickly as possible, but it may take some - time. Your patience is greatly appreciated! + - **Why did you make this change?** What problem does it solve or what improvement does it offer? + - **Output Changes (if applicable):** If your changes affect the output of the project (e.g., UI, logs), + please include screenshots _before and after_ to illustrate the impact. + +4. **Be patient:** We are a small team with limited time dedicated to managing this repository. We will review + pull requests as quickly as possible, but it may take some time. Your patience is greatly appreciated! Thanks again for your contribution! diff --git a/.github/workflows/build-and-upload.yaml b/.github/workflows/build-and-upload.yaml index 31189274..d5b9ab76 100644 --- a/.github/workflows/build-and-upload.yaml +++ b/.github/workflows/build-and-upload.yaml @@ -18,7 +18,19 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Log in to the Container registry + uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GHCR_PAT }} + + - name: Set up Python + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: "3.13" - name: Install regctl run: | @@ -65,7 +77,7 @@ jobs: image: "tonistiigi/binfmt@sha256:66e11bea77a5ea9d6f0fe79b57cd2b189b5d15b93a2bdb925be22949232e4e55" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Setup custom builder run: | @@ -74,25 +86,13 @@ jobs: - name: Run local Docker registry run: docker run -d -p 5000:5000 --name registry --network=host registry:2 - - name: Set up Python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 - with: - python-version: 3.9 - - - name: Install Poetry - run: pip install poetry - - - name: Install dependencies - run: poetry install + - name: Install Dibber + run: pip install dibber - name: Build images - run: poetry run build_multiplatform --parallel 8 + run: dibber build-multiplatform --parallel 8 - name: Upload images if: success() run: | - echo "$PASSWORD" | docker login ghcr.io --username "$USERNAME" --password-stdin - poetry run upload - env: - PASSWORD: ${{ secrets.GHCR_PAT }} - USERNAME: ${{ secrets.GHCR_USERNAME }} + dibber upload diff --git a/.github/workflows/keepalive.yaml b/.github/workflows/keepalive.yaml index 72021f39..1b2bf432 100644 --- a/.github/workflows/keepalive.yaml +++ b/.github/workflows/keepalive.yaml @@ -13,7 +13,7 @@ jobs: name: Keepalive runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Prepare git run: | diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index d0e9793f..9c464a49 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -12,12 +12,16 @@ jobs: # added or changed files to the repository. contents: write steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Set up Python + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: - python-version: "3.10" + python-version: "3.13" + # Run pre-commit --all-files - - uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507 # v3.0.0 + - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 + # Commit all changed files back to the repository - - uses: stefanzweifel/git-auto-commit-action@3ea6ae190baf489ba007f7c92608f33ce20ef04a # v4.16.0 + - uses: stefanzweifel/git-auto-commit-action@778341af668090896ca464160c2def5d1d1a3eb0 # v6.0.1 if: always() diff --git a/.github/workflows/scan-images.yaml b/.github/workflows/scan-images.yaml index 4815d304..5fda5e98 100644 --- a/.github/workflows/scan-images.yaml +++ b/.github/workflows/scan-images.yaml @@ -20,24 +20,21 @@ jobs: name: Build docker images runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Python - uses: actions/setup-python@v1 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: - python-version: 3.9 + python-version: "3.13" - - name: Install Poetry - run: pip install poetry - - - name: Install dependencies - run: poetry install + - name: Install Dibber + run: pip install dibber - name: Build images - run: poetry run build --parallel 8 + run: dibber build --parallel 8 - name: List images - run: poetry run list + run: dibber list - name: Install Trivy run: | @@ -51,4 +48,4 @@ jobs: trivy image --download-db-only - name: Trivy security scan - run: poetry run scan + run: dibber scan diff --git a/.gitignore b/.gitignore index f0bed849..eb048f78 100644 --- a/.gitignore +++ b/.gitignore @@ -144,3 +144,5 @@ cython_debug/ .idea .vscode .DS_Store + +.python-version diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 875601e5..a7786908 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,25 +2,25 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.10.0.1 + rev: v0.11.0.1 hooks: # Run shellcheck for all .sh files - id: shellcheck - - repo: https://github.com/pycqa/isort - rev: 6.0.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.12 hooks: - - id: isort - - - repo: https://github.com/psf/black - rev: 25.1.0 - hooks: - # Format Python files - - id: black - language_version: python3 + - id: ruff + name: ruff lint + args: [--fix] + - id: ruff + name: ruff sort imports + args: ["--select", "I", "--fix"] + - id: ruff-format + name: ruff format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: # Clean up trailing whitespace - id: trailing-whitespace @@ -53,27 +53,22 @@ repos: - id: check-added-large-files - repo: https://github.com/PyCQA/bandit - rev: 1.7.4 + rev: 1.8.6 hooks: # Do a security scan with Bandit - id: bandit - args: ["--ini", ".bandit", "-r"] + args: ["--configfile", "bandit.yaml"] exclude: | (?x)^( .*/tests/.* )$ - - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.7.1 + - repo: https://github.com/rbubley/mirrors-prettier/ + rev: v3.6.2 hooks: # Run prettier to format non-Python files - id: prettier - - repo: https://github.com/PyCQA/flake8 - rev: 7.1.1 - hooks: - - id: flake8 - - repo: https://github.com/twu/skjold rev: v0.6.2 hooks: diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index b3062b35..00000000 --- a/.prettierrc.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - printWidth: 88, - trailingComma: "es5", - useTabs: false, - tabWidth: 2, - semi: false, - singleQuote: false, - endOfLine: "lf", - proseWrap: "always", - overrides: [ - { - files: "*.yaml", - options: { - proseWrap: "preserve", - }, - }, - ], -} diff --git a/.prettierrc.toml b/.prettierrc.toml new file mode 100644 index 00000000..a38efd62 --- /dev/null +++ b/.prettierrc.toml @@ -0,0 +1,13 @@ +printWidth = 110 +trailingComma = "es5" +useTabs = false +tabWidth = 2 +semi = false +singleQuote = false +endOfLine = "lf" +proseWrap = 'always' + +[[overrides]] + files = "*.{yaml,yml}" + [overrides.options] + proseWrap = "preserve" diff --git a/.src/docker_build/images.py b/.src/docker_build/images.py deleted file mode 100644 index f7a0f1d8..00000000 --- a/.src/docker_build/images.py +++ /dev/null @@ -1,235 +0,0 @@ -import time -from datetime import timedelta -from pathlib import Path -from typing import Dict, List, Optional - -import humanize -from docker_build.utils import run -from loguru import logger -from pydantic import BaseModel -from yaml import load - -from settings import conf - -try: - from yaml import CLoader as Loader -except ImportError: - from yaml import Loader - - -class Config(BaseModel): - tags: List[str] - - -def find_images() -> Dict[str, List[str]]: - result = {} - - images = [ - p.name for p in Path(".").iterdir() if p.is_dir() and not p.name.startswith(".") - ] - - for image in images: - versions = [ - p.name - for p in Path(image).iterdir() - if p.is_dir() and not p.name.startswith(".") - ] - result[image] = versions - - return result - - -class ImageConf: - priority: int - image: list[str] - - def __init__(self, priority: int, image: list[str]): - self.priority = priority - self.image = image - - def __repr__(self): - return f"<{':'.join(self.image)} @ {self.priority} prio>" - - -def sort_images(images_: Dict[str, List[str]]) -> List[ImageConf]: - images = [] - for image, versions in images_.items(): - for version in versions: - images.append(f"{image}/{version}") - images.sort() - for image_or_list in conf.PRIORITY_BUILDS: - if isinstance(image_or_list, str): - try: - images.remove(image_or_list) - except ValueError: - logger.error( - "{image} found in PRIORITY_BUILDS is incorrect", image=image_or_list - ) - raise - else: - for _img in image_or_list: - try: - images.remove(_img) - except ValueError: - logger.error( - "{image} found in PRIORITY_BUILDS is incorrect", image=_img - ) - raise - - priority = 1 - result = [] - for image_or_list in conf.PRIORITY_BUILDS: - if isinstance(image_or_list, str): - try: - result.append( - ImageConf( - priority=priority, image=image_or_list.split("/", maxsplit=1) - ) - ) - except ValueError: - logger.error( - "{image} found in PRIORITY_BUILDS is incorrect", image=image_or_list - ) - raise - else: - for _img in image_or_list: - try: - result.append( - ImageConf(priority=priority, image=_img.split("/", maxsplit=1)) - ) - except ValueError: - logger.error( - "{image} found in PRIORITY_BUILDS is incorrect", image=_img - ) - raise - priority += 1 - - result += [ - ImageConf(priority=priority, image=img.split("/", maxsplit=1)) for img in images - ] - - return result - - -def build_image(image: str, version: str, verbose=True, platform: Optional[str] = None): - config = get_config(image, version) - name = f"{image}/{version}" - tag = docker_tag(image, version) - - logger.info("Building {name}", name=name) - - # Full commandline with all tags in one - cmd = ["docker", "build", name, "-t", tag] - for tag in config.tags: - full_name = docker_tag(image, tag) - cmd += ["-t", full_name] - - # make it possible to reuse this image in other local builds - cmd += ["-t", docker_tag(image, tag=version, local=True)] - - if platform: - cmd += ["--platform", platform] - - start = time.perf_counter() - run(cmd, verbose=verbose) - end = time.perf_counter() - if not verbose: - logger.info( - "Built {name} in {elapsed}", - name=name, - elapsed=humanize.precisedelta(timedelta(seconds=end - start)), - ) - - -def build_image_multiplatform( - image: str, version: str, platforms: List[str], verbose=True -): - name = f"{image}/{version}" - - logger.info("Building {name}", name=name) - - localhost_tag = f"{conf.LOCAL_REGISTRY}/{image}:{version}" - build_cmd = [ - "docker", - "buildx", - "build", - "--platform", - ",".join(platforms), - name, - "-t", - localhost_tag, - "--build-arg", - f"LOCAL_REGISTRY={conf.LOCAL_REGISTRY}/", - "--network=host", - "--push", # push to localhost registry - ] - - start = time.perf_counter() - run(build_cmd, verbose=verbose) - end = time.perf_counter() - if not verbose: - logger.info( - "Built {name} in {elapsed}", - name=name, - elapsed=humanize.precisedelta(timedelta(seconds=end - start)), - ) - - -def upload_tags_from_local_registry(images: Dict[str, List[str]]): - # local docker registry runs by HTTP, so we state it in regctl - run(["regctl", "registry", "set", "--tls", "disabled", conf.LOCAL_REGISTRY]) - for image, versions in images.items(): - for version in versions: - config = get_config(image, version) - localhost_tag = f"{conf.LOCAL_REGISTRY}/{image}:{version}" - tags = [docker_tag(image, tag) for tag in config.tags] - tags.append(docker_tag(image, version)) - for tag in tags: - run(["regctl", "image", "copy", localhost_tag, tag], verbose=True) - - -def docker_image(image: str) -> str: - return f"{conf.DOCKER_USER}/{image}" - - -def docker_tag(image: str, tag: str, local: bool = False) -> str: - if not local: - return f"{docker_image(image)}:{tag}" - return f"{image}:{tag}" - - -def get_config(image: str, version: str) -> Config: - config_path = f"{image}/{version}/config.yaml" - config_text = Path(config_path).read_text(encoding="utf-8") - config = load(config_text, Loader=Loader) - return Config(**config) - - -def update_scanner(): - logger.info("Updating trivy database") - run(["trivy", "image", "--download-db-only"]) - - -def scan_image(image: str, version: str) -> bool: - try: - run( - [ - "trivy", - "image", - "--skip-update", - "--severity", - "HIGH,CRITICAL", - "--exit-code", - "1", - "--timeout", - "7m", - f"{docker_image(image)}:{version}", - ], - cwd=f"{image}/{version}", - ) - return True - except Exception: - logger.error( - "{image}:{version} has vulnerabilities!", image=image, version=version - ) - return False diff --git a/.src/docker_build/main.py b/.src/docker_build/main.py deleted file mode 100644 index 13271537..00000000 --- a/.src/docker_build/main.py +++ /dev/null @@ -1,166 +0,0 @@ -import multiprocessing.context -import os -import signal -import sys -from enum import Enum -from multiprocessing import Pool -from typing import Optional - -import docker_build.utils as utils -import typer -from docker_build.images import ( - build_image, - build_image_multiplatform, - docker_tag, - find_images, - scan_image, - sort_images, - update_scanner, - upload_tags_from_local_registry, -) -from docker_build.validation import validate - -from settings import conf - - -class Platform(str, Enum): - LINUX_AMD64 = "linux/amd64" - LINUX_ARM64 = "linux/arm64" - - -build = typer.Typer() -build_multiplatform = typer.Typer() -upload = typer.Typer() -scan = typer.Typer() -list = typer.Typer() -docker_username = typer.Typer() -ALL_PLATFORMS = [Platform.LINUX_AMD64.value, Platform.LINUX_ARM64.value] - - -def init_pool(logger_, env): - utils.logger = logger_ - os.environ.update(env) - - -def _build_all_images( - parallel: int, multiplatform: bool, platform: Optional[Platform] = None -): - platform = platform.value if platform else None - images = find_images() - validate(images) - sorted_images = sort_images(images) - - if parallel == 1: - images = [img_conf.image for img_conf in sorted_images] - for image, version in images: - if multiplatform: - build_image_multiplatform(image, version, ALL_PLATFORMS) - else: - build_image(image, version, platform=platform) - else: - utils.logger.info(f"Building {len(sorted_images)} images in {parallel} threads") - utils.logger.remove() - utils.logger.add(sys.stderr, enqueue=True, level="INFO") - - original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) - with Pool( - parallel, initializer=init_pool, initargs=(utils.logger, os.environ) - ) as pool: - signal.signal(signal.SIGINT, original_sigint_handler) - - def _build_images(_images): - if multiplatform: - res = pool.starmap_async( - build_image_multiplatform, - [(image, version, ALL_PLATFORMS) for image, version in _images], - ) - else: - res = pool.starmap_async( - build_image, - [ - (image, version, False, platform) - for image, version in _images - ], - ) - while True: - try: - # Have a timeout to be non-blocking for signals - res.get(3) - break - except multiprocessing.context.TimeoutError: - pass - - max_prio = max(ic.priority for ic in sorted_images) - - for prio in range(1, max_prio + 1): - images = [ - img_conf.image - for img_conf in sorted_images - if img_conf.priority == prio - ] - try: - utils.logger.info( - "Building {c} priority {prio} images with up to {parallel} threads", - c=len(images), - prio=prio, - parallel=parallel, - ) - _build_images(images) - except KeyboardInterrupt: - utils.logger.error("Caught KeyboardInterrupt, terminating workers") - pool.terminate() - raise - - pool.close() - - -@build.command(help="Build docker images") -def _build( - parallel: int = typer.Option(1), platform: Optional[Platform] = typer.Option(None) -): - _build_all_images(parallel, platform=platform, multiplatform=False) - - -@build_multiplatform.command(help="Build docker images for multiple platforms") -def _build_multiplatform( - parallel: int = typer.Option(1), -): - _build_all_images(parallel, multiplatform=True) - - -@upload.command(help="Upload docker tags") -def _upload(): - images = find_images() - validate(images) - upload_tags_from_local_registry(images) - - -@scan.command(help="Scan docker images") -def _scan(): - update_scanner() - images = find_images() - vuln_images = [] - for image, versions in sorted(images.items()): - for version in versions: - if not scan_image(image, version): - vuln_images.append(docker_tag(image, version)) - - if vuln_images: - utils.logger.error("Some images have vulnerabilities!") - for img in vuln_images: - print(f" - {img}") - - raise typer.Exit(code=1) - - -@list.command(help="List unique docker images managed by this tool") -def _list(): - images = find_images() - for image, versions in images.items(): - for version in versions: - print(docker_tag(image, version)) - - -@docker_username.command(help="Get the configured Docker username") -def _docker_username(): - print(conf.DOCKER_USER) diff --git a/.src/docker_build/utils.py b/.src/docker_build/utils.py deleted file mode 100644 index ffafde70..00000000 --- a/.src/docker_build/utils.py +++ /dev/null @@ -1,21 +0,0 @@ -from subprocess import PIPE, STDOUT, check_call # nosec -from subprocess import run as sp_run # nosec -from typing import List - -from loguru import logger - - -def run(cmd: List[str], verbose=True, cwd=None): - logger.debug("Executing: {cmd}", cmd=" ".join(cmd)) - if verbose: - check_call(cmd, cwd=cwd) - else: - result = sp_run(cmd, stdout=PIPE, stderr=STDOUT, cwd=cwd) - if result.returncode > 0: - logger.error( - "{cmd} exited with code {code}", - cmd=" ".join(cmd), - code=result.returncode, - ) - logger.error(result.stdout.decode("utf-8")) - raise Exception(f"Failed to run {cmd}") diff --git a/.src/docker_build/validation.py b/.src/docker_build/validation.py deleted file mode 100644 index 3c719644..00000000 --- a/.src/docker_build/validation.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Dict, List - -from docker_build.images import docker_tag, get_config -from loguru import logger - - -def validate(images: Dict[str, List[str]]): - for image in images.keys(): - tags = {} - for version in images[image]: - name = f"{image}/{version}" - logger.debug("Validating {name}", name=name) - _validate_version(image, version) - _tags = _get_tags(image, version) - - # Check tags are unique - for tag in _tags: - if tag in tags.keys(): - src = tags[tag] - raise ValueError( - f"{name} trying to redefine {tag} already defined in {src}" - ) - tags[tag] = name - logger.debug("{name} has tag {tag}", name=name, tag=tag) - - -def _validate_version(image: str, version: str): - pass - - -def _get_tags(image: str, version: str): - tags = [docker_tag(image, version)] - config = get_config(image, version) - tags += [docker_tag(image, tag) for tag in config.tags] - return tags diff --git a/LICENSE.md b/LICENSE.md index a6d59b08..8c4b4cac 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,27 +1,24 @@ ## "New BSD" / "BSD 3-clause" -license -Copyright 2021 Janne Enberg +Copyright 2025 Janne Enberg -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: +Redistribution and use in source and binary forms, with or without modification, are permitted provided that +the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the + following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may be - used to endorse or promote products derived from this software without specific prior - written permission. +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/README.md b/README.md index 1df16b0d..c28d75fe 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,9 @@ -# Docker image builder +# Docker images -Builds your Docker images automatically, like magic. Good for handling common base -images for all your projects, apps, whatever. +This repository builds docker images to +[github.com/orgs/ioxiocom/packages](https://github.com/orgs/ioxiocom/packages) or `ghcr.io/ioxiocom/...`. -This repository builds images to -[IOXIO® GitHub Packages](https://github.com/orgs/ioxiocom/packages) or -`ghcr.io/ioxiocom/` - -## How do you use this then? - -Well, we got 3 things you need to worry about: - -1. General configuration in `settings.py`: Basically you need to set up your Docker hub - username prefixed by the `ghcr.io` since we are using GitHub container registry so as - to prefix all built images with the right name -2. Images and versions: First level of subdirectories in this repo is "images", as in - the repository names (`username/`) for Docker hub. The subdirectories in - that defines the "versions" - basically default tags for things to be built for that - repository. -3. Additional tags: In `image/version/config.yaml` you can define additional tags for - the built image, like `latest`, or whatever aliases you may want for it. - -Afterwards you can either set this up on your own build pipelines with the commands: - -``` -poetry install -poetry run build_multiplatform -poetry run upload -poetry run scan -``` - -If you have images other images depend on, check out the `settings.PRIORITY_BUILDS` -option. Each list within it gets assigned a priority and can be built in parallel with -`--parallel` argument, the rest of the images will then get built after everything in -the `PRIORITY_BUILDS`. - -```python -# Simple priority to a couple of images -PRIORITY_BUILDS = [ - "ubuntu-base/20.04", - "ubuntu-base/22.04", -] -``` - -```python -# Tiered priorities of things that depend on earlier priorities -PRIORITY_BUILDS = [ - [ - "ubuntu-base/20.04", - "ubuntu-base/22.04", - ], - [ - "python-base/ubuntu20.04-python3.9", - "python-base/ubuntu22.04-python3.10", - ] -] -``` - -## But what does it require? - -You will need: - -- [Docker CLI](https://docs.docker.com/get-docker/) >= 20.10.0 (we use - `docker push --all-tags` to save some time) -- [Python](https://www.python.org/downloads/) >= 3.9 -- [Poetry](https://python-poetry.org/docs/#installation) - -You could also just use the preconfigured GitHub workflows. If you do you'll just need -to add a `DOCKERHUB_TOKEN` secret ("token" is a -[personal access token](https://docs.docker.com/docker-hub/access-tokens/)) that will be -used to log into your account for upload. This needs to be for the Docker hub user -configured in `settings.py`. - -The `scan` command uses `trivy` which you will need installed on your system first. - -## Multiplatform support - -There are several technical restrictions when building images for multiple platforms -with `buildx`, such as that `buildx` can't find an image in local docker environment -(see notes in -[output](https://docs.docker.com/engine/reference/commandline/buildx_build/#output) -section of the docs). But it's possible to push base images right away to a docker -registry and then explicitly define this registry in `FROM` statements. - -That's why there are 2 options to build images: - -- `poetry run build` builds all images for the current platform only with `docker build` - under the hood. It's suitable for local development of the images -- `poetry run build_multiplatform` builds all images using `docker buildx build` for - linux/amd64 and linux/arm64. It requires extra setup (check - [pipeline code](./.github/workflows/build-and-upload.yaml)) and is not recommended for - local development - -## Contributions - -If you plan on contributing to the code ensure you use -[pre-commit](https://pre-commit.com/#install) to guarantee the code style stays uniform -etc. - -Also, please open an issue first to discuss the idea before sending a PR so that you -know if it would be wanted or needs re-thinking or if you should just make a fork for -yourself. +Built using [dibber](https://github.com/lietu/dibber). ## If I use this it means you own my things, right? diff --git a/bandit.yaml b/bandit.yaml new file mode 100644 index 00000000..86f63f11 --- /dev/null +++ b/bandit.yaml @@ -0,0 +1,2 @@ +assert_used: + skips: ["*_test.py", "*test_*.py"] diff --git a/dibber.toml b/dibber.toml new file mode 100644 index 00000000..d10ec2f6 --- /dev/null +++ b/dibber.toml @@ -0,0 +1,17 @@ + +docker_user = "ghcr.io/ioxiocom" + +local_registry = "localhost:5000" + +priority_builds = [ + [ + "ubuntu-base/24.04", + "nginx-base/alpine-nginx", + ], + [ + "python-base/ubuntu24.04-python3.13", + ], + [ + "python-base/ubuntu24.04-python3.13-nginx", + ], +] diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index fb9b9796..00000000 --- a/poetry.lock +++ /dev/null @@ -1,324 +0,0 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. - -[[package]] -name = "attrs" -version = "21.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, -] - -[package.extras] -dev = ["coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] -docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] -tests-no-zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] - -[[package]] -name = "click" -version = "8.0.4" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.6" -files = [ - {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"}, - {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.4" -description = "Cross-platform colored terminal text." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, -] - -[[package]] -name = "exceptiongroup" -version = "1.0.4" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, - {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "humanize" -version = "4.4.0" -description = "Python humanize utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "humanize-4.4.0-py3-none-any.whl", hash = "sha256:8830ebf2d65d0395c1bd4c79189ad71e023f277c2c7ae00f263124432e6f2ffa"}, - {file = "humanize-4.4.0.tar.gz", hash = "sha256:efb2584565cc86b7ea87a977a15066de34cdedaf341b11c851cfcfd2b964779c"}, -] - -[package.extras] -tests = ["freezegun", "pytest", "pytest-cov"] - -[[package]] -name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -optional = false -python-versions = "*" -files = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] - -[[package]] -name = "loguru" -version = "0.6.0" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = ">=3.5" -files = [ - {file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"}, - {file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "tox (>=3.9.0)"] - -[[package]] -name = "packaging" -version = "20.9" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"}, - {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"}, -] - -[package.dependencies] -pyparsing = ">=2.0.2" - -[[package]] -name = "pluggy" -version = "0.13.1" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, - {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] - -[[package]] -name = "pydantic" -version = "1.10.14" -description = "Data validation and settings management using python type hints" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic-1.10.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4fcec873f90537c382840f330b90f4715eebc2bc9925f04cb92de593eae054"}, - {file = "pydantic-1.10.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e3a76f571970fcd3c43ad982daf936ae39b3e90b8a2e96c04113a369869dc87"}, - {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d886bd3c3fbeaa963692ef6b643159ccb4b4cefaf7ff1617720cbead04fd1d"}, - {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:798a3d05ee3b71967844a1164fd5bdb8c22c6d674f26274e78b9f29d81770c4e"}, - {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:23d47a4b57a38e8652bcab15a658fdb13c785b9ce217cc3a729504ab4e1d6bc9"}, - {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9f674b5c3bebc2eba401de64f29948ae1e646ba2735f884d1594c5f675d6f2a"}, - {file = "pydantic-1.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:24a7679fab2e0eeedb5a8924fc4a694b3bcaac7d305aeeac72dd7d4e05ecbebf"}, - {file = "pydantic-1.10.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d578ac4bf7fdf10ce14caba6f734c178379bd35c486c6deb6f49006e1ba78a7"}, - {file = "pydantic-1.10.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa7790e94c60f809c95602a26d906eba01a0abee9cc24150e4ce2189352deb1b"}, - {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad4e10efa5474ed1a611b6d7f0d130f4aafadceb73c11d9e72823e8f508e663"}, - {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245f4f61f467cb3dfeced2b119afef3db386aec3d24a22a1de08c65038b255f"}, - {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:21efacc678a11114c765eb52ec0db62edffa89e9a562a94cbf8fa10b5db5c046"}, - {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:412ab4a3f6dbd2bf18aefa9f79c7cca23744846b31f1d6555c2ee2b05a2e14ca"}, - {file = "pydantic-1.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:e897c9f35281f7889873a3e6d6b69aa1447ceb024e8495a5f0d02ecd17742a7f"}, - {file = "pydantic-1.10.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d604be0f0b44d473e54fdcb12302495fe0467c56509a2f80483476f3ba92b33c"}, - {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42c7d17706911199798d4c464b352e640cab4351efe69c2267823d619a937e5"}, - {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:596f12a1085e38dbda5cbb874d0973303e34227b400b6414782bf205cc14940c"}, - {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfb113860e9288d0886e3b9e49d9cf4a9d48b441f52ded7d96db7819028514cc"}, - {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bc3ed06ab13660b565eed80887fcfbc0070f0aa0691fbb351657041d3e874efe"}, - {file = "pydantic-1.10.14-cp37-cp37m-win_amd64.whl", hash = "sha256:ad8c2bc677ae5f6dbd3cf92f2c7dc613507eafe8f71719727cbc0a7dec9a8c01"}, - {file = "pydantic-1.10.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c37c28449752bb1f47975d22ef2882d70513c546f8f37201e0fec3a97b816eee"}, - {file = "pydantic-1.10.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49a46a0994dd551ec051986806122767cf144b9702e31d47f6d493c336462597"}, - {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e3819bd20a42470d6dd0fe7fc1c121c92247bca104ce608e609b59bc7a77ee"}, - {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbb503bbbbab0c588ed3cd21975a1d0d4163b87e360fec17a792f7d8c4ff29f"}, - {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:336709883c15c050b9c55a63d6c7ff09be883dbc17805d2b063395dd9d9d0022"}, - {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ae57b4d8e3312d486e2498d42aed3ece7b51848336964e43abbf9671584e67f"}, - {file = "pydantic-1.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:dba49d52500c35cfec0b28aa8b3ea5c37c9df183ffc7210b10ff2a415c125c4a"}, - {file = "pydantic-1.10.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c66609e138c31cba607d8e2a7b6a5dc38979a06c900815495b2d90ce6ded35b4"}, - {file = "pydantic-1.10.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d986e115e0b39604b9eee3507987368ff8148222da213cd38c359f6f57b3b347"}, - {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:646b2b12df4295b4c3148850c85bff29ef6d0d9621a8d091e98094871a62e5c7"}, - {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282613a5969c47c83a8710cc8bfd1e70c9223feb76566f74683af889faadc0ea"}, - {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:466669501d08ad8eb3c4fecd991c5e793c4e0bbd62299d05111d4f827cded64f"}, - {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:13e86a19dca96373dcf3190fcb8797d40a6f12f154a244a8d1e8e03b8f280593"}, - {file = "pydantic-1.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:08b6ec0917c30861e3fe71a93be1648a2aa4f62f866142ba21670b24444d7fd8"}, - {file = "pydantic-1.10.14-py3-none-any.whl", hash = "sha256:8ee853cd12ac2ddbf0ecbac1c289f95882b2d4482258048079d13be700aa114c"}, - {file = "pydantic-1.10.14.tar.gz", hash = "sha256:46f17b832fe27de7850896f3afee50ea682220dd218f7e9c88d436788419dca6"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pyparsing" -version = "2.4.7" -description = "Python parsing module" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, - {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, -] - -[[package]] -name = "pytest" -version = "7.2.0" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, -] - -[package.dependencies] -attrs = ">=19.2.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} - -[package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] - -[[package]] -name = "pyyaml" -version = "6.0" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[[package]] -name = "typer" -version = "0.7.0" -description = "Typer, build great CLIs. Easy to code. Based on Python type hints." -optional = false -python-versions = ">=3.6" -files = [ - {file = "typer-0.7.0-py3-none-any.whl", hash = "sha256:b5e704f4e48ec263de1c0b3a2387cd405a13767d2f907f44c1a08cbad96f606d"}, - {file = "typer-0.7.0.tar.gz", hash = "sha256:ff797846578a9f2a201b53442aedeb543319466870fbe1c701eab66dd7681165"}, -] - -[package.dependencies] -click = ">=7.1.1,<9.0.0" - -[package.extras] -all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"] -dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] -doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] -test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"] - -[[package]] -name = "typing-extensions" -version = "4.3.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -optional = false -python-versions = ">=3.7" -files = [ - {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, - {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, -] - -[[package]] -name = "win32-setctime" -version = "1.0.3" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -files = [ - {file = "win32_setctime-1.0.3-py3-none-any.whl", hash = "sha256:dc925662de0a6eb987f0b01f599c01a8236cb8c62831c22d9cada09ad958243e"}, - {file = "win32_setctime-1.0.3.tar.gz", hash = "sha256:4e88556c32fdf47f64165a2180ba4552f8bb32c1103a2fafd05723a0bd42bd4b"}, -] - -[package.extras] -dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] - -[metadata] -lock-version = "2.0" -python-versions = "^3.9" -content-hash = "d96972183865fd08d0f63d887be1b9289dca5e8c43ef8fbd90e4dfc963a6f6ca" diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 60b88a8f..00000000 --- a/pyproject.toml +++ /dev/null @@ -1,34 +0,0 @@ -[tool.poetry] -name = "docker-images" -version = "1.0.0" -description = "Docker image manager" -authors = ["Janne Enberg "] -license = "BSD" -packages = [{ include = "docker_build", from = ".src" }] - -[tool.poetry.dependencies] -python = "^3.9" -typer = "^0.7.0" -pytest = "^7.2.0" -pydantic = "^1.10.13" -PyYAML = "^6.0" -loguru = "^0.6.0" -humanize = "^4.4.0" - -[tool.poetry.dev-dependencies] - -[tool.poetry.scripts] -build = "docker_build.main:build" -build_multiplatform = "docker_build.main:build_multiplatform" -docker_username = "docker_build.main:docker_username" -list = "docker_build.main:list" -scan = "docker_build.main:scan" -upload = "docker_build.main:upload" - -[tool.skjold] -report_only = false -sources = ["pyup", "gemnasium"] - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/settings.py b/settings.py deleted file mode 100644 index a9eef0bc..00000000 --- a/settings.py +++ /dev/null @@ -1,26 +0,0 @@ -from pydantic import BaseSettings - - -# Any of these can be overridden via environment variables with matching names -class Settings(BaseSettings): - # GitHub container registry and organization name, used for "registry/org/image" -name generation - DOCKER_USER = "ghcr.io/ioxiocom" - - LOCAL_REGISTRY = "localhost:5000" - - # List of images that should be built beforehand - PRIORITY_BUILDS = [ - [ - "ubuntu-base/24.04", - "nginx-base/alpine-nginx", - ], - [ - "python-base/ubuntu24.04-python3.13", - ], - [ - "python-base/ubuntu24.04-python3.13-nginx", - ], - ] - - -conf = Settings() diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 31c99d5c..00000000 --- a/setup.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[flake8] -# Black takes care of line formatting so flake8 should not mess with them -extend-ignore = E203, E501 - -[isort] -profile = black