From a164c1bcc6dec6d795bdba10f30eec3f27a5383d Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Mon, 29 Jun 2026 04:40:48 +0800 Subject: [PATCH 1/4] update agents --- pkg/aloha/settings.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/pkg/aloha/settings.py b/pkg/aloha/settings.py index 4e70ec6..51554b6 100644 --- a/pkg/aloha/settings.py +++ b/pkg/aloha/settings.py @@ -1,3 +1,7 @@ +from typing import Any + +from attrdict import AttrDict + from .config import hocon, paths @@ -8,11 +12,14 @@ class Settings: Manages configuration loading and provides access to common directories. """ - def __init__(self): - self._config = None + def __init__(self, config: Any | None = None): + if config is None: + self._config = None + else: + self.load_settings(config) @property - def resource_dir(self): + def dir_resource(self): """ Get the resource directory path. @@ -21,7 +28,7 @@ def resource_dir(self): return paths.get_resource_dir() @property - def config_dir(self): + def dir_config(self): """ Get the configuration directory path. @@ -29,6 +36,15 @@ def config_dir(self): """ return paths.get_config_dir() + def load_settings(self, config: Any) -> Any: + if isinstance(config, dict): + self._config = AttrDict({key: self.load_settings(value) for key, value in config.items()}) + elif isinstance(config, list): + self._config = [self.load_settings(value) for value in config] + else: + raise ValueError("Unsupported config type: %s" % str(type(config))) + return self._config + @property def config(self): """ From a8ab40de7ae2650f4f1cecbfc1413c41d1cf48e1 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Mon, 29 Jun 2026 05:03:22 +0800 Subject: [PATCH 2/4] init agent files --- AGENTS.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index e69de29..9ba5d35 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -0,0 +1,125 @@ +# Aloha — Contributor Guidelines + +Welcome, AI Coding Agents (`agy`, `Claude Code`, `GitHub Copilot`, etc.)! This document serves as your central instruction entry point. Please read this file and the referenced skills before making any modifications to the codebase. + +## 1. Project Context + +`aloha-python` is a modern project template (boilerplate) and a versatile utility library (`aloha` package) designed to build robust, containerized microservices in Python. + +### Repository Structure + +- `src/`: Application-specific codebase, configuration resources, and tests. + - `src/resource/config/`: Configuration files (`main.conf`, settings, profiles). + - `src/tests/`: Unit and integration tests. +- `pkg/`: Core `aloha` utility library package source code. +- `tool/`: Helper scripts, build files, and Docker/Docker Compose configs for local CI/CD. +- `doc/`: Documentation files and AI Agent Skills. + - `doc/skill`: The folder to store all project skill files -- all other agent-specific skill folders (e.g.: `.claude/skills`, `.agent/skills`) point to this folder using symlinks. +- `notebook/`: Jupyter notebooks for interactive analysis. +- `.agents/`: Local customization folder for AI agents containing the `skills` symlink setup. + +## 2. Working Rules + +When writing code or configurations for this project, you **MUST** strictly adhere to the following rules: + +### A. Python Coding & Naming Standards + +- **Primary Type/First-Class Identity Prefix**: Place the variable's type, role, or primary characteristics first in its name. + - _Correct_: `name_service`, `port_service`, `svc_ingress`, `cfg_postgres`, `db_mysql`. + - _Incorrect_: `service_name`, `service_port`, `ingress_service`, `postgres_config`, `mysql_db`. +- **Logger Naming**: Use lowercase with underscores for logger names, e.g., `db_sync`, `api_router`. +- **Import Conventions**: Use relative imports if possible, especially inside a package. + +### B. Configuration & Security + +- **HOCON Configuration**: Always use HOCON configuration via `aloha.config` (`SETTINGS` object). Maintain configurations in modular files and import them using the HOCON `include` directive in `main.conf`. +- **No Hardcoded Credentials**: Never write plaintext passwords or secrets in configuration files. Configure secrets to resolve dynamically at runtime using the `PasswordVault`. + +### C. Logging & Concurrency + +- **Safe Multi-Process Logging**: Do not instantiate default Python `FileHandler` inside concurrent or multi-process tasks. Use `aloha.logger.LOG` or named loggers from `get_logger()` to ensure safe concurrent log writing. + +### D. Testing Guidelines + +- **Framework**: Use `pytest` for all unit and integration testing. +- **Harness**: Subclass `UnitTestCase` or `ServiceTestCase` from `aloha.testing` to leverage pre-configured settings, DB connections, and loggers. + +## 3. Skills + +We have defined explicit skills to guide specific development tasks. Refer to the corresponding instruction files before editing relevant code: + +- **[Aloha Python Skill](doc/skills/aloha_python/SKILL.md)** + - Covers Python naming standards, sub-modules usage (`aloha.config`, `aloha.logger`, `aloha.encrypt`, `aloha.db`, `aloha.testing`), and the Cython binary compilation process. +- **[Aloha CI/CD & Scaffolding Skill](doc/skills/aloha_cicd/SKILL.md)** + - Covers project structure layout, local containerized development environments via `./tool/cicd/run-dev.sh`, user-specific port calculations, and production Docker builds. + +## 4. Runtime Environment + +Note: It is always advised to develop/debug/test code inside a container environment by using the method specified in `Local Container Lifecycle`. + +To execute scripts, run tests, or compile code, work within the containerized local development environment: + +### A. Local Container Lifecycle + +Management is driven by `./tool/cicd/run-dev.sh`: + +```bash +# Start the development container in the background +./tool/cicd/run-dev.sh up + +# Open an interactive shell inside the container +./tool/cicd/run-dev.sh enter + +# Stop the development container +./tool/cicd/run-dev.sh down +``` + +> [!NOTE] +> The helper script dynamically assigns `PORT_APP` and `PORT_WEB` based on your system `UID` to prevent port collisions on shared servers. + +### B. Module Execution + +To run application entry points, use the generic module runner: + +```bash +cd src + +# Execute within the dev container +python3 main.py . + +# Example +python3 main.py app_common.main +``` + +### C. Running Tests + +Run tests from the root directory _inside the container terminal_: + +```bash +cd src + +# Run pytest on application source code +pytest ./ + +# Run tests and output test coverage +pytest --cov=./ ./ +``` + +### D. Binary Compilation & Packaging + +To compile code using Cython and build production images: + +```bash +# Source tool utilities and build the Docker image +source tool/tool.sh +build_image app_common latest src/app-demo.Dockerfile +``` + +## 5. Extension Metadata + +This configuration allows AI coding assistants to load this project's custom definitions automatically. + +### Agent Skill Mapping + +- **Config file**: `.agents/skills` +- **Path mapping**: Pointing to `../doc/skills`. Enables `codex`, `claude`, `agy`, etc. to resolve all workspace-scoped skills defined under `doc/skills/`. From c3678f54e008963b1a1ed8761a248cd1a6193d2c Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Mon, 29 Jun 2026 05:06:50 +0800 Subject: [PATCH 3/4] update docs --- pkg/aloha/settings.py | 52 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/pkg/aloha/settings.py b/pkg/aloha/settings.py index 51554b6..20d12fc 100644 --- a/pkg/aloha/settings.py +++ b/pkg/aloha/settings.py @@ -7,12 +7,22 @@ class Settings: """ - Global settings management class for aloha. + Global settings management class for the Aloha package. - Manages configuration loading and provides access to common directories. + This class manages the lazy loading of HOCON configuration files, environment + profile resolution, and provides access to project resource and configuration directories. + + Attributes: + _config (Any | None): Internal storage for the parsed configuration. """ def __init__(self, config: Any | None = None): + """ + Initialize the Settings manager. + + :param config: Optional pre-loaded configuration dictionary, list, or None. + If provided, it is parsed and loaded immediately. + """ if config is None: self._config = None else: @@ -21,22 +31,38 @@ def __init__(self, config: Any | None = None): @property def dir_resource(self): """ - Get the resource directory path. + Get the absolute path of the resource directory. + + Resolves dynamically based on the `DIR_RESOURCE` environment variable, + falling back to the default 'resource' directory in the current working directory. - :return: Resource directory path + :return: Absolute path to the resource directory. """ return paths.get_resource_dir() @property def dir_config(self): """ - Get the configuration directory path. + Get the absolute path of the configuration directory. + + Resolves dynamically based on the `DIR_CONFIG` environment variable, + falling back to the 'config' subdirectory under the resource directory. - :return: Config directory path + :return: Absolute path to the configuration directory. """ return paths.get_config_dir() def load_settings(self, config: Any) -> Any: + """ + Recursively load and transform configuration values. + + Converts raw dictionaries into `AttrDict` objects to support attribute-style + dot notation access, and recursively processes lists and nested values. + + :param config: The configuration data to load (dict or list). + :return: The converted configuration object (AttrDict or list). + :raises ValueError: If the configuration data type is unsupported. + """ if isinstance(config, dict): self._config = AttrDict({key: self.load_settings(value) for key, value in config.items()}) elif isinstance(config, list): @@ -50,9 +76,11 @@ def config(self): """ Get the global configuration object. - Lazily loads configuration from HOCON files on first access. + Lazily loads and parses configuration files on first access. It resolves active + HOCON configuration files based on the `FILES_CONFIG` or `ENV_PROFILE` environment + variables, falls back to `main.conf` if not specified, and merges them into an `AttrDict`. - :return: Configuration object + :return: Merged global configuration settings as an AttrDict. """ if self._config is None: config_files = paths.get_config_files() # by default, use the `main.conf` file in the config_dir @@ -62,10 +90,12 @@ def config(self): def __getitem__(self, item): """ - Get a configuration value by key. + Get a configuration value using dictionary key lookup syntax. + + Allows retrieving configurations using `SETTINGS[key]`. - :param item: Configuration key - :return: Configuration value + :param item: The configuration key to look up. + :return: The resolved configuration value. """ return self.config[item] From 5e7ab7843828b898ef46691e835ca6f13808282c Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Mon, 29 Jun 2026 05:11:22 +0800 Subject: [PATCH 4/4] chore: update dependabot configuration for pip directories --- .github/dependabot.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2bdd9e0..290a717 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,8 +14,18 @@ updates: patterns: - "*" - - package-ecosystem: "pip" # See documentation for possible values - directory: "./" # Location of package manifests + - package-ecosystem: "pip" + directory: "/pkg" + schedule: + interval: "weekly" + day: "sunday" + groups: + all-pip: + patterns: + - "*" + + - package-ecosystem: "pip" + directory: "/src" schedule: interval: "weekly" day: "sunday"