diff --git a/dds/builders/docker.py b/dds/builders/docker.py index d18a072..eeb5e5a 100644 --- a/dds/builders/docker.py +++ b/dds/builders/docker.py @@ -59,7 +59,15 @@ def resolve_image_tag( def _build_args_str(build_args: dict[str, str] | None) -> str: - """Format build args dict into Docker --build-arg flags.""" + """Format build args dict into Docker --build-arg flags. + + Values containing spaces or shell-special characters are quoted to prevent + word-splitting when the command string is passed to the shell. + """ if not build_args: return "" - return " ".join(f"--build-arg {k}={v}" for k, v in build_args.items()) + import shlex + + return " ".join( + f"--build-arg {k}={shlex.quote(str(v))}" for k, v in build_args.items() + ) diff --git a/dds/cli.py b/dds/cli.py index 36d1f7c..8497902 100644 --- a/dds/cli.py +++ b/dds/cli.py @@ -66,10 +66,10 @@ def _check_access(environment: str, env_cfg: dict) -> None: ) raise SystemExit(1) - if True: - console.print( - f" [dim]Access check: {deployer_email} ✓ ({environment})[/dim]" - ) + # Always emit a dim confirmation so operators have an audit trail. + console.print( + f" [dim]Access check: {deployer_email} ✓ ({environment})[/dim]" + ) def _make_ctx(click_ctx: click.Context, environment: str, service: str) -> DeployContext: diff --git a/dds/providers/azure/container.py b/dds/providers/azure/container.py index 8381636..deaa558 100644 --- a/dds/providers/azure/container.py +++ b/dds/providers/azure/container.py @@ -349,7 +349,15 @@ def _http_check(url: str, timeout: float = 10.0, verbose: bool = False) -> bool: def _build_args_str(build_args: dict[str, str] | None) -> str: - """Format build args dict into Docker --build-arg flags.""" + """Format build args dict into Docker --build-arg flags. + + Values containing spaces or shell-special characters are quoted to prevent + word-splitting when the command string is passed to the shell. + """ if not build_args: return "" - return " ".join(f"--build-arg {k}={v}" for k, v in build_args.items()) + import shlex + + return " ".join( + f"--build-arg {k}={shlex.quote(str(v))}" for k, v in build_args.items() + ) diff --git a/dds/providers/azure/swa.py b/dds/providers/azure/swa.py index 2d429ae..266b623 100644 --- a/dds/providers/azure/swa.py +++ b/dds/providers/azure/swa.py @@ -27,6 +27,7 @@ def deploy(self, ctx: DeployContext) -> None: env_production_path = os.path.join(project_dir, ".env.production") env_production_backup = None + env_prod_local_backup: str | None = None if env_file: env_file_path = os.path.join(project_dir, env_file) @@ -46,6 +47,8 @@ def deploy(self, ctx: DeployContext) -> None: env_prod_local = os.path.join(project_dir, ".env.production.local") if os.path.exists(env_prod_local): + with open(env_prod_local) as f: + env_prod_local_backup = f.read() os.remove(env_prod_local) try: @@ -107,6 +110,18 @@ def deploy(self, ctx: DeployContext) -> None: f.write(env_production_backup) if ctx.verbose: console.print(" Restored original .env.production") + elif env_file and os.path.exists(env_production_path): + # We created .env.production from scratch — remove it + os.remove(env_production_path) + if ctx.verbose: + console.print(" Removed temporary .env.production") + + env_prod_local_path = os.path.join(project_dir, ".env.production.local") + if env_prod_local_backup is not None: + with open(env_prod_local_path, "w") as f: + f.write(env_prod_local_backup) + if ctx.verbose: + console.print(" Restored original .env.production.local") def status(self, ctx: DeployContext) -> None: """Show status for a Static Web App.""" diff --git a/dds/providers/docker/container.py b/dds/providers/docker/container.py index 22f43f6..d38d826 100644 --- a/dds/providers/docker/container.py +++ b/dds/providers/docker/container.py @@ -179,7 +179,7 @@ def rollback(self, ctx: DeployContext, target_revision: str | None = None) -> bo ssh( host, f"{cd_prefix}docker compose -f {compose_file} down {service_name} && " - f"docker compose -f {compose_file} up -d {service_name}", + f"{cd_prefix}docker compose -f {compose_file} up -d {service_name}", verbose=ctx.verbose, )