Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b459eef34b |
@@ -1,5 +1,4 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
import tomllib
|
import tomllib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -9,6 +8,7 @@ import dotenv
|
|||||||
from jinja2 import Environment
|
from jinja2 import Environment
|
||||||
|
|
||||||
from ..preset.model import Variables
|
from ..preset.model import Variables
|
||||||
|
from .util import get_environ
|
||||||
|
|
||||||
|
|
||||||
def do_bool(data: str | None) -> bool:
|
def do_bool(data: str | None) -> bool:
|
||||||
@@ -19,10 +19,6 @@ def do_bool(data: str | None) -> bool:
|
|||||||
return data.lower() not in ["false", "null", "none", "0", ""]
|
return data.lower() not in ["false", "null", "none", "0", ""]
|
||||||
|
|
||||||
|
|
||||||
def do_env(key: str, default: str | None = None) -> str | None:
|
|
||||||
return os.environ.get(key=key.upper(), default=default)
|
|
||||||
|
|
||||||
|
|
||||||
def do_not(value: Any | None) -> bool:
|
def do_not(value: Any | None) -> bool:
|
||||||
return not do_bool(str(value))
|
return not do_bool(str(value))
|
||||||
|
|
||||||
@@ -31,6 +27,8 @@ def _build_env(basepath: Path) -> Environment:
|
|||||||
env = Environment()
|
env = Environment()
|
||||||
|
|
||||||
def do_file(filename: str) -> Path | None:
|
def do_file(filename: str) -> Path | None:
|
||||||
|
if not filename:
|
||||||
|
return None
|
||||||
result = Path(filename)
|
result = Path(filename)
|
||||||
if not result.is_absolute():
|
if not result.is_absolute():
|
||||||
result = basepath / result
|
result = basepath / result
|
||||||
@@ -73,6 +71,11 @@ def _build_env(basepath: Path) -> Environment:
|
|||||||
keys = list(data.keys())
|
keys = list(data.keys())
|
||||||
return keys[keyindex]
|
return keys[keyindex]
|
||||||
|
|
||||||
|
env_data = get_environ(basepath)
|
||||||
|
|
||||||
|
def do_env(key: str, default: str | None = None) -> str | None:
|
||||||
|
return env_data.get(key.upper(), default)
|
||||||
|
|
||||||
env.filters["file"] = do_file
|
env.filters["file"] = do_file
|
||||||
env.filters["read"] = do_read
|
env.filters["read"] = do_read
|
||||||
env.filters["get"] = do_get
|
env.filters["get"] = do_get
|
||||||
@@ -91,6 +94,12 @@ class PathTemplate:
|
|||||||
|
|
||||||
def update_variables(self, templates: Variables, variables: Variables):
|
def update_variables(self, templates: Variables, variables: Variables):
|
||||||
for k, v in templates.items():
|
for k, v in templates.items():
|
||||||
|
if isinstance(v, dict):
|
||||||
|
variables[k] = {
|
||||||
|
kk: self._env.from_string(vv).render(**variables)
|
||||||
|
for kk, vv in v.items()
|
||||||
|
}
|
||||||
|
else:
|
||||||
variables[k] = self._env.from_string(v).render(**variables)
|
variables[k] = self._env.from_string(v).render(**variables)
|
||||||
|
|
||||||
def fill_template(self, template: str, variables: Variables) -> str:
|
def fill_template(self, template: str, variables: Variables) -> str:
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import dotenv
|
||||||
|
|
||||||
|
|
||||||
def merge_dicts(target: dict, enhancer: dict) -> dict:
|
def merge_dicts(target: dict, enhancer: dict) -> dict:
|
||||||
for key, val in enhancer.items():
|
for key, val in enhancer.items():
|
||||||
if key not in target:
|
if key not in target:
|
||||||
@@ -9,3 +15,10 @@ def merge_dicts(target: dict, enhancer: dict) -> dict:
|
|||||||
else:
|
else:
|
||||||
target[key] = val
|
target[key] = val
|
||||||
return target
|
return target
|
||||||
|
|
||||||
|
|
||||||
|
def get_environ(path: Path) -> dict[str, str]:
|
||||||
|
result = os.environ.copy()
|
||||||
|
if (env_file := path / ".env").exists():
|
||||||
|
result.update(dotenv.dotenv_values(env_file))
|
||||||
|
return result
|
||||||
|
|||||||
@@ -1,4 +1,16 @@
|
|||||||
[presets.config.tasks.setup.config]
|
[presets.config.tasks.setup.env]
|
||||||
priority = 1
|
priority = 1
|
||||||
conditions = ["{{ ('.env-base' | file) and ('.env' | file | not ) }}"]
|
conditions = ["{{ ('.env-base' | file) and ('.env' | file | not ) }}"]
|
||||||
commands = ["cp .env-base .env"]
|
commands = ["cp .env-base .env"]
|
||||||
|
|
||||||
|
[presets.config.tasks.setup.env2]
|
||||||
|
priority = 1
|
||||||
|
conditions = ["{{ ('.env.default' | file) and ('.env' | file | not ) }}"]
|
||||||
|
commands = ["cp .env.default .env"]
|
||||||
|
|
||||||
|
[presets.config.tasks.setup.json]
|
||||||
|
priority = 1
|
||||||
|
conditions = [
|
||||||
|
"{{ ('config.example.json' | file) and ('config.json' | file | not ) }}",
|
||||||
|
]
|
||||||
|
commands = ["cp config.example.json config.json"]
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
[presets.docker]
|
[presets.docker]
|
||||||
conditions = ["{{ 'Dockerfile' | file }}"]
|
conditions = ["{{ 'Dockerfile' | file }}"]
|
||||||
variables.docker_name = "{{ 'pyproject.toml' | read | get('project.name') or 'package.json' | read | get('name') }}"
|
variables.docker_name = "{{ project_name }}"
|
||||||
variables.docker_version = "{{ 'pyproject.toml' | read | get('project.version') or 'package.json' | read | get('version') }}"
|
variables.docker_version = "{{ project_version }}"
|
||||||
variables.docker_repo = "{{ '.env' | read | get('DOCKER_REPO') }}"
|
variables.docker_repo = "{{ 'DOCKER_REPO' | env }}"
|
||||||
variables.docker_group = "{{ '.env' | read | get('DOCKER_GROUP') }}"
|
variables.docker_group = "{{ 'DOCKER_GROUP' | env }}"
|
||||||
variables.docker_image = "{% if docker_group | bool %}{{ docker_group }}/{% endif %}{{ docker_name }}"
|
variables.docker_image = "{% if docker_group | bool %}{{ docker_group }}/{% endif %}{{ docker_name }}"
|
||||||
variables.docker_tag = "{{ '.env' | read | get('DOCKER_TAG') or 'latest' }}"
|
variables.docker_tag = "{{ 'DOCKER_TAG' | env('latest') }}"
|
||||||
|
variables.docker_target = "{{ 'DOCKER_TARGET' | env }}"
|
||||||
|
variables.docker_target_arg = "{{ ('--target ' + docker_target) if docker_target else '' }}"
|
||||||
|
|
||||||
# build
|
# build
|
||||||
[presets.docker.tasks.build.default]
|
[presets.docker.tasks.build.default]
|
||||||
commands = ["docker build -t {{ docker_image }} . -f Dockerfile"]
|
commands = ["docker build {{ docker_target_arg }} -t {{ docker_image }} . -f Dockerfile"]
|
||||||
|
|
||||||
# publish version
|
# publish version
|
||||||
[presets.docker.tasks.publish.version]
|
[presets.docker.tasks.publish.version]
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
[presets.gitea]
|
||||||
|
variables.publish_repo = "{{ 'PUBLISH_REPO' | env }}"
|
||||||
|
variables.publish_repo_path = "{{ publish_repo }}/generic/{{ project_name }}/{{ project_version }}"
|
||||||
|
variables.publish_user = "{{ 'PUBLISH_USER' | env }}"
|
||||||
|
variables.publish_password = "{{ 'PUBLISH_PASSWORD' | env }}"
|
||||||
|
variables.publish_auth = "{{ publish_user }}:{{ publish_password }}"
|
||||||
|
variables.publish_artefacts = {}
|
||||||
|
|
||||||
|
[presets.gitea.tasks.publish."{{ publish_artefacts | tojson }}"]
|
||||||
|
conditions = ["{{ item | file }}"]
|
||||||
|
variables.artefact_file = "{{ item }}"
|
||||||
|
variables.artefact_name = "{{ (artefact_file | file).name }}"
|
||||||
|
commands = [
|
||||||
|
"curl --user \"{{ publish_auth }}\" -X DELETE \"{{ publish_repo_path }}/{{ artefact_name }}\"",
|
||||||
|
"curl --user \"{{ publish_auth }}\" --fail --upload-file \"{{ artefact_file }}\" \"{{ publish_repo_path }}/{{ artefact_name }}\"",
|
||||||
|
]
|
||||||
|
|
||||||
|
[presets.gitea.tasks.publish.debian_repo]
|
||||||
|
conditions = ["{{ publish_artefacts.debian | file }}"]
|
||||||
|
variables.artefact_file = "{{ publish_artefacts.debian }}"
|
||||||
|
commands = [
|
||||||
|
"curl --user \"{{ publish_auth }}\" -X DELETE \"{{ publish_repo }}/debian/pool/noble/main/{{ project_name }}/{{ project_version }}/all\"",
|
||||||
|
"curl --user \"{{ publish_auth }}\" --fail --upload-file \"{{ artefact_file }}\" \"{{ publish_repo }}/debian/pool/noble/main/upload\"",
|
||||||
|
]
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
[presets.'*']
|
[presets.'*']
|
||||||
priority = 1000
|
priority = 1000
|
||||||
conditions = ["{{ true }}"]
|
conditions = ["{{ true }}"]
|
||||||
|
variables.project_name = "{{ 'pyproject.toml' | read | get('project.name') or 'package.json' | read | get('name') }}"
|
||||||
|
variables.project_version = "{{ 'pyproject.toml' | read | get('project.version') or 'package.json' | read | get('version') }}"
|
||||||
variables.version = "{{ 'version' | env }}"
|
variables.version = "{{ 'version' | env }}"
|
||||||
tasks = {}
|
tasks = {}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import json
|
||||||
import operator
|
import operator
|
||||||
from os import environ
|
from os import environ
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -14,7 +15,7 @@ class PresetEntryDetector(EntryDetector):
|
|||||||
def __init__(self, preset_loader_config: PresetLoaderConfig | None = None):
|
def __init__(self, preset_loader_config: PresetLoaderConfig | None = None):
|
||||||
self._preset_loader_config = preset_loader_config
|
self._preset_loader_config = preset_loader_config
|
||||||
|
|
||||||
# pylint:disable=too-many-locals
|
# pylint:disable=too-many-locals,too-many-nested-blocks,too-many-branches
|
||||||
def detect_entry(self, basepath: Path, rootpath: Path) -> Entry:
|
def detect_entry(self, basepath: Path, rootpath: Path) -> Entry:
|
||||||
template = PathTemplate(basepath)
|
template = PathTemplate(basepath)
|
||||||
preset = PresetLoader(basepath, self._preset_loader_config).load()
|
preset = PresetLoader(basepath, self._preset_loader_config).load()
|
||||||
@@ -44,14 +45,24 @@ class PresetEntryDetector(EntryDetector):
|
|||||||
continue
|
continue
|
||||||
for task_name, task_pack in preset.tasks.items():
|
for task_name, task_pack in preset.tasks.items():
|
||||||
for sub_tag, task_preset in task_pack.items():
|
for sub_tag, task_preset in task_pack.items():
|
||||||
|
sub_tags = template.fill_template(sub_tag, preset_variables)
|
||||||
|
try:
|
||||||
|
sub_tags = json.loads(sub_tags)
|
||||||
|
except ValueError:
|
||||||
|
sub_tags = {sub_tags: None}
|
||||||
|
for i_sub_tag, i_sub_tag_value in sub_tags.items():
|
||||||
|
if i_sub_tag_value:
|
||||||
|
preset_variables["item"] = i_sub_tag_value
|
||||||
if not task_preset.conditions or template.check_conditions(
|
if not task_preset.conditions or template.check_conditions(
|
||||||
task_preset.conditions, preset_variables
|
task_preset.conditions, preset_variables
|
||||||
):
|
):
|
||||||
variables = preset_variables.copy()
|
variables = preset_variables.copy()
|
||||||
if task_preset.variables:
|
if task_preset.variables:
|
||||||
template.update_variables(task_preset.variables, variables)
|
template.update_variables(
|
||||||
|
task_preset.variables, variables
|
||||||
|
)
|
||||||
task = Task(
|
task = Task(
|
||||||
key=TaskKey(task_name, tag, sub_tag),
|
key=TaskKey(task_name, tag, i_sub_tag),
|
||||||
commands=[
|
commands=[
|
||||||
template.fill_template(command, variables)
|
template.fill_template(command, variables)
|
||||||
for command in task_preset.commands
|
for command in task_preset.commands
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
Variables = dict[str, str]
|
Variables = dict[str, Any]
|
||||||
|
|
||||||
|
|
||||||
class TaskPreset(BaseModel):
|
class TaskPreset(BaseModel):
|
||||||
|
|||||||
Reference in New Issue
Block a user