Skip to content

Feat/redis valkey#8

Open
Asuniia wants to merge 5 commits intomainfrom
feat/redis-valkey
Open

Feat/redis valkey#8
Asuniia wants to merge 5 commits intomainfrom
feat/redis-valkey

Conversation

@Asuniia
Copy link
Copy Markdown
Contributor

@Asuniia Asuniia commented Mar 25, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Redis and Valkey as supported database options for configuration, available in both local container and external setup modes with optional authentication variants.
  • Chores

    • Version bumped to 26.03.1.
    • Updated release date metadata and configuration UI panel titles.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 25, 2026

📝 Walkthrough

Walkthrough

Version numbers updated from 26.02.17 to 26.03.1. Database configuration extended to support Redis and Valkey in addition to existing options. New Docker Compose service templates and utility function added to manage container configuration and compose file modifications.

Changes

Cohort / File(s) Summary
Version & Metadata
CITATION.cff, pyproject.toml
Updated version from 26.02.17 to 26.03.1 and release date to 2026-03-25.
Agent & Database Setup
commands/agent.py, commands/db.py
Extended database type support to include redis and valkey alongside existing options. Added dynamic port selection via get_free_port(), authentication handling via -auth engine suffix, and Docker Compose snippet injection. Updated configuration JSON generation for new database types, including default port (6379) and database field (0) for Redis/Valkey.
UI Components
commands/dashboard.py
Changed Rich Panel title from "PROPOSED CONFIGURATION" to "SUMMARY" for consistency.
Docker Management
core/docker.py
Added new update_compose_file(path, service_snippet, volume_name) function to programmatically insert service and volume definitions into docker-compose.yml at appropriate sections (networks/volumes blocks).
Compose Templates
templates/compose.py
Added four new Docker Compose service snippet templates: AGENT_REDIS_SNIPPET, AGENT_REDIS_AUTH_SNIPPET, AGENT_VALKEY_SNIPPET, AGENT_VALKEY_AUTH_SNIPPET, with respective authentication configurations (password enforcement and environment variables).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Agent/DB as Agent/DB Config
    participant Docker as Docker Manager
    participant Compose as Compose File
    participant Config as Config JSON

    User->>Agent/DB: Select Redis/Valkey + auth option
    Agent/DB->>Agent/DB: Determine db_engine (e.g., "redis-auth")
    Agent/DB->>Docker: Call update_compose_file() with service snippet
    Docker->>Compose: Read existing docker-compose.yml
    Docker->>Compose: Locate networks/volumes sections
    Docker->>Compose: Insert service snippet & volume definition
    Docker->>Compose: Normalize & write back
    Agent/DB->>Agent/DB: Get dynamic port via get_free_port()
    Agent/DB->>Agent/DB: Generate password secret (if auth enabled)
    Agent/DB->>Config: Write database.json entry (type, username, password, port, host, db=0)
    Config-->>User: Configuration complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Feat/hint #7: Parallel changes to database setup, Docker Compose updates, and container generation logic for local database variants using similar patterns for agent/db configuration and compose file injection.

Poem

🐰 Through gardens of code, the Redis hops,
Valkey dances in Docker pots,
Auth passwords bloom, ports dance free,
Compose files grow with symphony,
A version 26.03 springs to life! 🌱

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feat/redis valkey' is too vague and uses a format that doesn't clearly convey the main changes; it reads like a branch name rather than a descriptive summary. Revise the title to clearly describe the primary change, such as 'Add Redis and Valkey database support' or 'Support Redis and Valkey as database options'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/redis-valkey

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
commands/agent.py (1)

306-349: ⚠️ Potential issue | 🔴 Critical

Critical bug: MongoDB with-auth branch is unreachable.

When the user selects MongoDB with with-auth variant, lines 201-202 change db_engine from "mongodb" to "mongodb-auth". However, the condition at line 306 checks elif db_engine == "mongodb":, which will be False when auth is selected.

The nested check at line 307 if db_variant == "with-auth": can never be true within this branch because the outer condition already excludes the auth case.

This means MongoDB with authentication silently fails to create any container.

🐛 Proposed fix: Add separate branch for mongodb-auth
-            elif db_engine == "mongodb":
-                if db_variant == "with-auth":
+            elif db_engine == "mongodb-auth":
                     mongo_port = get_free_port()
                     db_user = "admin"
                     db_pass = secrets.token_hex(8)
                     # ... rest of auth code ...
-                else:
+
+            elif db_engine == "mongodb":
                     mongo_port = get_free_port()
                     db_name = f"mongo_{secrets.token_hex(4)}"
                     # ... rest of non-auth code ...
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commands/agent.py` around lines 306 - 349, The mongodb "with-auth" code is
never reached because db_engine is set to "mongodb-auth" earlier but the branch
checks elif db_engine == "mongodb"; update the branching in commands/agent.py so
the auth snippet executes for the auth engine value: either add a new branch
that checks elif db_engine == "mongodb-auth": (copying the existing block that
references AGENT_MONGODB_AUTH_SNIPPET, env_vars, extra_services, volumes_list,
service_name, mongo_port and calls add_db_to_json) or change the existing
condition to detect db_variant == "with-auth" (while preserving the non-auth
mongodb branch), ensuring service_name, db_user/db_pass generation, env_vars
population and the add_db_to_json call run for the auth case.
commands/db.py (1)

237-267: ⚠️ Potential issue | 🔴 Critical

Critical bug: MongoDB with-auth branch is unreachable (same issue as in agent.py).

When MongoDB with with-auth variant is selected, line 148-149 changes db_engine to "mongodb-auth". The condition at line 237 elif db_engine == "mongodb": will be False, making the nested auth check at line 240 unreachable.

🐛 Proposed fix: Add separate branch for mongodb-auth
-        elif db_engine == "mongodb":
-            db_port = get_free_port()
-            db_name = f"mongo_{secrets.token_hex(4)}"
-            if db_variant == "with-auth":
+        elif db_engine == "mongodb-auth":
+            db_port = get_free_port()
+            db_name = f"mongo_{secrets.token_hex(4)}"
+            db_user = "admin"
+            db_pass = secrets.token_hex(8)
+            service_name = f"db-mongo-auth-{secrets.token_hex(2)}"
+            var_prefix = service_name.upper().replace("-", "_")
+            env_vars[f"{var_prefix}_PORT"] = str(db_port)
+            env_vars[f"{var_prefix}_DB"] = db_name
+            env_vars[f"{var_prefix}_USER"] = db_user
+            env_vars[f"{var_prefix}_PASS"] = db_pass
+            snippet = (
+                AGENT_MONGODB_AUTH_SNIPPET.replace("${SERVICE_NAME}", service_name)
+                .replace("${PORT}", f"${{{var_prefix}_PORT}}")
+                .replace("${VOL_NAME}", f"{service_name}-data")
+                .replace("${DB_NAME}", f"${{{var_prefix}_DB}}")
+                .replace("${USER}", f"${{{var_prefix}_USER}}")
+                .replace("${PASSWORD}", f"${{{var_prefix}_PASS}}")
+            )
+
+        elif db_engine == "mongodb":
+            db_port = get_free_port()
+            db_name = f"mongo_{secrets.token_hex(4)}"
+            service_name = f"db-mongo-{secrets.token_hex(2)}"
             # ... rest of non-auth code
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commands/db.py` around lines 237 - 267, The current branch elif db_engine ==
"mongodb" never runs for the auth variant because elsewhere db_engine is set to
"mongodb-auth"; add a separate branch for db_engine == "mongodb-auth" (similar
to the existing nested with-auth logic) that sets service_name, var_prefix,
env_vars (PORT, DB, USER, PASS), and builds snippet using
AGENT_MONGODB_AUTH_SNIPPET; keep the existing elif db_engine == "mongodb" as the
no-auth path using AGENT_MONGODB_SNIPPET so the two variants are handled
independently (refer to symbols db_engine, "mongodb-auth",
AGENT_MONGODB_AUTH_SNIPPET, AGENT_MONGODB_SNIPPET, service_name, var_prefix,
env_vars, snippet).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@commands/agent.py`:
- Line 13: The import update_compose_file is unused in commands/agent.py; remove
update_compose_file from the import list (leaving ensure_network and
run_compose) to eliminate the unused-import warning, or if you intended to use
it, replace the manual compose-file build logic in the function that currently
constructs the compose template with a call to update_compose_file so the import
is actually used (refer to the symbols update_compose_file, ensure_network,
run_compose to locate the import and compose-building logic).

In `@commands/db.py`:
- Line 11: The import list includes run_compose but that symbol is unused;
remove run_compose from the import statement (leave update_compose_file) in the
module so there are no unused imports, or if run_compose is actually needed,
call it from the appropriate function (e.g., where compose is updated) instead
of leaving it unused; target the import line that currently reads "from
core.docker import run_compose, update_compose_file" and adjust it accordingly.

In `@core/docker.py`:
- Line 33: The function signature update_compose_file currently uses an implicit
None-able parameter for volume_name; update its type annotation to be explicit
(e.g., volume_name: Optional[str] or volume_name: Union[str, None]) and add the
corresponding import (from typing import Optional or Union) at the top of the
module so the annotation conforms to PEP 484.
- Around line 62-80: The insertion offset currently uses volumes_pos + 8 which
assumes the literal length of "volumes:"; update the logic that computes the
search start for the next top-level section to use volumes_pos + len("volumes:")
and advance past any intervening whitespace/newlines before running the
next_section regex so it works with "volumes: " or other formatting; adjust
variables volume_name, vol_snippet, volumes_pos, v_insert_pos and the use of
find_top_level/new_content accordingly so the v_insert_pos is computed from the
whitespace-skipped start.
- Around line 28-30: The except block catching subprocess.CalledProcessError
should preserve the original traceback when re-raising; capture the exception
(e.g., except subprocess.CalledProcessError as e:) and re-raise the Typer exit
with exception chaining (raise typer.Exit(1) from e) so the original
CalledProcessError traceback is preserved for debugging while keeping the
existing console.print call.

In `@pyproject.toml`:
- Line 3: The version string in pyproject.toml ("version = \"26.03.1\"")
deviates from the prior date-based pattern (e.g., 26.02.17); update the
versioning to a consistent scheme and document it: decide whether to keep
YY.MM.DD (date-based) or move to YY.MM.PATCH (semantic-style), then change the
value of version in pyproject.toml to match the chosen format and add/adjust
project documentation or a COMMENT in the repo (release docs or CONTRIBUTING) to
state the new convention so tooling and automation can be aligned with the
chosen scheme.

In `@templates/compose.py`:
- Around line 74-88: AGENT_REDIS_AUTH_SNIPPET contains an unused environment
variable entry for REDIS_PASSWORD that is redundant because the password is
already passed via the redis-server --requirepass argument; remove the line "-
REDIS_PASSWORD=${PASSWORD}" from the AGENT_REDIS_AUTH_SNIPPET string so the
compose snippet only sets the password via the command field (reference:
AGENT_REDIS_AUTH_SNIPPET in compose.py).

---

Outside diff comments:
In `@commands/agent.py`:
- Around line 306-349: The mongodb "with-auth" code is never reached because
db_engine is set to "mongodb-auth" earlier but the branch checks elif db_engine
== "mongodb"; update the branching in commands/agent.py so the auth snippet
executes for the auth engine value: either add a new branch that checks elif
db_engine == "mongodb-auth": (copying the existing block that references
AGENT_MONGODB_AUTH_SNIPPET, env_vars, extra_services, volumes_list,
service_name, mongo_port and calls add_db_to_json) or change the existing
condition to detect db_variant == "with-auth" (while preserving the non-auth
mongodb branch), ensuring service_name, db_user/db_pass generation, env_vars
population and the add_db_to_json call run for the auth case.

In `@commands/db.py`:
- Around line 237-267: The current branch elif db_engine == "mongodb" never runs
for the auth variant because elsewhere db_engine is set to "mongodb-auth"; add a
separate branch for db_engine == "mongodb-auth" (similar to the existing nested
with-auth logic) that sets service_name, var_prefix, env_vars (PORT, DB, USER,
PASS), and builds snippet using AGENT_MONGODB_AUTH_SNIPPET; keep the existing
elif db_engine == "mongodb" as the no-auth path using AGENT_MONGODB_SNIPPET so
the two variants are handled independently (refer to symbols db_engine,
"mongodb-auth", AGENT_MONGODB_AUTH_SNIPPET, AGENT_MONGODB_SNIPPET, service_name,
var_prefix, env_vars, snippet).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f3f26e7a-4c18-4b87-b8aa-41bcb66063d6

📥 Commits

Reviewing files that changed from the base of the PR and between d1d8db9 and bbb51b8.

📒 Files selected for processing (7)
  • CITATION.cff
  • commands/agent.py
  • commands/dashboard.py
  • commands/db.py
  • core/docker.py
  • pyproject.toml
  • templates/compose.py
📜 Review details
🧰 Additional context used
🪛 Ruff (0.15.6)
core/docker.py

[error] 11-11: subprocess call: check for execution of untrusted input

(S603)


[error] 12-12: Starting a process with a partial executable path

(S607)


[error] 18-18: subprocess call: check for execution of untrusted input

(S603)


[error] 19-19: Starting a process with a partial executable path

(S607)


[warning] 30-30: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


[warning] 33-33: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


[warning] 40-40: Unnecessary mode argument

Remove mode argument

(UP015)


[warning] 43-43: Missing return type annotation for private function find_top_level

(ANN202)

🔇 Additional comments (6)
CITATION.cff (1)

25-26: LGTM - Metadata correctly synchronized.

The version and release date are properly updated and consistent with the corresponding changes in pyproject.toml.

commands/dashboard.py (1)

125-125: LGTM!

The panel title change to "SUMMARY" is consistent with the same update in commands/agent.py, improving UI consistency across the CLI.

templates/compose.py (1)

60-117: LGTM!

The Redis and Valkey Docker Compose snippets are well-structured with proper placeholder variables for service names, ports, volumes, and passwords. The command configurations for persistence (--appendonly yes) and authentication (--requirepass) follow best practices for these in-memory data stores.

commands/agent.py (1)

385-525: LGTM!

The Redis and Valkey container generation branches are well-structured and follow the established patterns:

  • Proper port allocation via get_free_port()
  • Unique service names with random suffixes
  • Correct env var prefixing for compose variable substitution
  • Appropriate database.json entries with database: "0" for key-value stores
commands/db.py (2)

268-313: LGTM!

The Redis and Valkey branches correctly use substring matching ("redis" in db_engine, "valkey" in db_engine) to handle both standard and auth variants in a single branch. The auth detection with "auth" in db_engine works correctly since the engine string is either "redis"/"valkey" or "redis-auth"/"valkey-auth".


315-332: Clean consolidation of post-snippet processing.

The unified handling for all snippet-based engines reduces code duplication. The use of db_engine.split("-")[0] to derive the base type and the conditional database value ("0" for key-value stores) is a good approach.


from core.config import add_db_to_json, load_db_config, write_env_file, write_file
from core.docker import ensure_network, run_compose
from core.docker import ensure_network, run_compose, update_compose_file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Unused import: update_compose_file is not used in this file.

The import of update_compose_file was added but the function is not called anywhere in commands/agent.py. This file builds the compose file from templates directly rather than using update_compose_file.

♻️ Proposed fix
-from core.docker import ensure_network, run_compose, update_compose_file
+from core.docker import ensure_network, run_compose
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commands/agent.py` at line 13, The import update_compose_file is unused in
commands/agent.py; remove update_compose_file from the import list (leaving
ensure_network and run_compose) to eliminate the unused-import warning, or if
you intended to use it, replace the manual compose-file build logic in the
function that currently constructs the compose template with a call to
update_compose_file so the import is actually used (refer to the symbols
update_compose_file, ensure_network, run_compose to locate the import and
compose-building logic).

from rich.table import Table

from core.config import add_db_to_json, load_db_config, save_db_config, write_env_file
from core.docker import run_compose, update_compose_file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Unused import: run_compose is not used in this file.

The run_compose function is imported but never called in commands/db.py.

♻️ Proposed fix
-from core.docker import run_compose, update_compose_file
+from core.docker import update_compose_file
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from core.docker import run_compose, update_compose_file
from core.docker import update_compose_file
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commands/db.py` at line 11, The import list includes run_compose but that
symbol is unused; remove run_compose from the import statement (leave
update_compose_file) in the module so there are no unused imports, or if
run_compose is actually needed, call it from the appropriate function (e.g.,
where compose is updated) instead of leaving it unused; target the import line
that currently reads "from core.docker import run_compose, update_compose_file"
and adjust it accordingly.

Comment on lines 28 to +30
except subprocess.CalledProcessError:
console.print("[danger]Command failed.[/danger]")
raise typer.Exit(1) No newline at end of file
raise typer.Exit(1)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider chaining the exception for better debugging.

When re-raising within an except clause, chaining with from preserves the original traceback.

♻️ Proposed fix
     except subprocess.CalledProcessError:
+    except subprocess.CalledProcessError as e:
         console.print("[danger]Command failed.[/danger]")
-        raise typer.Exit(1)
+        raise typer.Exit(1) from e
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except subprocess.CalledProcessError:
console.print("[danger]Command failed.[/danger]")
raise typer.Exit(1)
\ No newline at end of file
raise typer.Exit(1)
except subprocess.CalledProcessError as e:
console.print("[danger]Command failed.[/danger]")
raise typer.Exit(1) from e
🧰 Tools
🪛 Ruff (0.15.6)

[warning] 30-30: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/docker.py` around lines 28 - 30, The except block catching
subprocess.CalledProcessError should preserve the original traceback when
re-raising; capture the exception (e.g., except subprocess.CalledProcessError as
e:) and re-raise the Typer exit with exception chaining (raise typer.Exit(1)
from e) so the original CalledProcessError traceback is preserved for debugging
while keeping the existing console.print call.

raise typer.Exit(1)


def update_compose_file(path: Path, service_snippet: str, volume_name: str = None):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Use explicit Optional or union type for volume_name parameter.

PEP 484 prohibits implicit Optional. The parameter should explicitly indicate it can be None.

♻️ Proposed fix
-def update_compose_file(path: Path, service_snippet: str, volume_name: str = None):
+def update_compose_file(path: Path, service_snippet: str, volume_name: str | None = None):
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def update_compose_file(path: Path, service_snippet: str, volume_name: str = None):
def update_compose_file(path: Path, service_snippet: str, volume_name: str | None = None):
🧰 Tools
🪛 Ruff (0.15.6)

[warning] 33-33: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/docker.py` at line 33, The function signature update_compose_file
currently uses an implicit None-able parameter for volume_name; update its type
annotation to be explicit (e.g., volume_name: Optional[str] or volume_name:
Union[str, None]) and add the corresponding import (from typing import Optional
or Union) at the top of the module so the annotation conforms to PEP 484.

core/docker.py Outdated
Comment on lines +62 to +80
if volume_name:
vol_snippet = f" {volume_name}:\n"
volumes_pos = find_top_level(new_content, "volumes")
if volumes_pos != -1:
next_section = re.search(
r"^[a-z]+:", new_content[volumes_pos + 8 :], re.MULTILINE
)
if next_section:
v_insert_pos = volumes_pos + 8 + next_section.start()
else:
v_insert_pos = len(new_content)

new_content = (
new_content[:v_insert_pos].rstrip()
+ "\n"
+ vol_snippet
+ "\n"
+ new_content[v_insert_pos:]
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Volume insertion offset relies on fixed string length.

The volumes_pos + 8 offset assumes the volumes: key is exactly 8 characters with no trailing whitespace. If the compose file has volumes: (with trailing space) or unusual formatting, the search offset may be incorrect.

Consider using volumes_pos + len("volumes:") for clarity, and optionally skipping whitespace/newlines before the regex search.

♻️ Proposed improvement
         if volumes_pos != -1:
+            volumes_key_len = len("volumes:")
             next_section = re.search(
-                r"^[a-z]+:", new_content[volumes_pos + 8 :], re.MULTILINE
+                r"^[a-z]+:", new_content[volumes_pos + volumes_key_len :], re.MULTILINE
             )
             if next_section:
-                v_insert_pos = volumes_pos + 8 + next_section.start()
+                v_insert_pos = volumes_pos + volumes_key_len + next_section.start()
             else:
                 v_insert_pos = len(new_content)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if volume_name:
vol_snippet = f" {volume_name}:\n"
volumes_pos = find_top_level(new_content, "volumes")
if volumes_pos != -1:
next_section = re.search(
r"^[a-z]+:", new_content[volumes_pos + 8 :], re.MULTILINE
)
if next_section:
v_insert_pos = volumes_pos + 8 + next_section.start()
else:
v_insert_pos = len(new_content)
new_content = (
new_content[:v_insert_pos].rstrip()
+ "\n"
+ vol_snippet
+ "\n"
+ new_content[v_insert_pos:]
)
if volume_name:
vol_snippet = f" {volume_name}:\n"
volumes_pos = find_top_level(new_content, "volumes")
if volumes_pos != -1:
volumes_key_len = len("volumes:")
next_section = re.search(
r"^[a-z]+:", new_content[volumes_pos + volumes_key_len :], re.MULTILINE
)
if next_section:
v_insert_pos = volumes_pos + volumes_key_len + next_section.start()
else:
v_insert_pos = len(new_content)
new_content = (
new_content[:v_insert_pos].rstrip()
"\n"
vol_snippet
"\n"
new_content[v_insert_pos:]
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/docker.py` around lines 62 - 80, The insertion offset currently uses
volumes_pos + 8 which assumes the literal length of "volumes:"; update the logic
that computes the search start for the next top-level section to use volumes_pos
+ len("volumes:") and advance past any intervening whitespace/newlines before
running the next_section regex so it works with "volumes: " or other formatting;
adjust variables volume_name, vol_snippet, volumes_pos, v_insert_pos and the use
of find_top_level/new_content accordingly so the v_insert_pos is computed from
the whitespace-skipped start.

pyproject.toml Outdated
[project]
name = "portabase-cli"
version = "26.02.17"
version = "26.03.1"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Versioning scheme appears to have changed.

The version format has shifted from 26.02.17 (which matched the date-based pattern YY.MM.DD = 2026-02-17) to 26.03.1 (which appears to be YY.MM.PATCH format). This inconsistency could:

  • Break tooling or automation that expects a consistent versioning pattern
  • Confuse users about the project's versioning strategy
  • Create ambiguity for future releases

Please clarify the intended versioning scheme going forward. If switching to semantic versioning (e.g., YY.MM.PATCH), consider documenting this change and ensuring all tooling is updated accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyproject.toml` at line 3, The version string in pyproject.toml ("version =
\"26.03.1\"") deviates from the prior date-based pattern (e.g., 26.02.17);
update the versioning to a consistent scheme and document it: decide whether to
keep YY.MM.DD (date-based) or move to YY.MM.PATCH (semantic-style), then change
the value of version in pyproject.toml to match the chosen format and add/adjust
project documentation or a COMMENT in the repo (release docs or CONTRIBUTING) to
state the new convention so tooling and automation can be aligned with the
chosen scheme.

Comment on lines +74 to +88
AGENT_REDIS_AUTH_SNIPPET = """
${SERVICE_NAME}:
image: redis:latest
container_name: ${PROJECT_NAME}-${SERVICE_NAME}
ports:
- "${PORT}:6379"
volumes:
- ${VOL_NAME}:/data
environment:
- REDIS_PASSWORD=${PASSWORD}
command: [ "redis-server", "--requirepass", "${PASSWORD}", "--appendonly", "yes" ]
networks:
- portabase
- default
"""
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Does the official Redis Docker image support REDIS_PASSWORD environment variable?

💡 Result:

No, the official Redis Docker image (redis on Docker Hub from docker-library/redis) does not support a REDIS_PASSWORD environment variable. The entrypoint script (docker-entrypoint.sh) does not process or use any such environment variable to configure a password. Official documentation on Docker Hub, GitHub repo README, and Redis developer docs show no mention of REDIS_PASSWORD as a supported env var. Passwords must be set via command-line arguments like redis-server --requirepass password, a mounted redis.conf file with requirepass password, or for Redis Stack images (redis/redis-stack), via REDIS_ARGS="--requirepass password". Unofficial blogs and Stack Overflow examples claiming REDIS_PASSWORD support are incorrect or refer to custom setups; recent PRs (#355, #492) to add it were not merged as of 2026-02-24.

Citations:


Remove the unused REDIS_PASSWORD environment variable.

The official Redis Docker image does not process REDIS_PASSWORD as an environment variable. The password is correctly configured via the --requirepass command argument (line 87), making the REDIS_PASSWORD env var (lines 82-83) redundant and misleading. Remove it to avoid confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/compose.py` around lines 74 - 88, AGENT_REDIS_AUTH_SNIPPET contains
an unused environment variable entry for REDIS_PASSWORD that is redundant
because the password is already passed via the redis-server --requirepass
argument; remove the line "- REDIS_PASSWORD=${PASSWORD}" from the
AGENT_REDIS_AUTH_SNIPPET string so the compose snippet only sets the password
via the command field (reference: AGENT_REDIS_AUTH_SNIPPET in compose.py).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant