Skip to content

Commit d3b7240

Browse files
Coding-Dev-Toolssenior-dev-rotation-Bcowork-bot
authored
fix: correct install advice, remove false PyPI badge, fix module_path doubling (#44)
* fix: correct click-to-mcp install advice to working git+ URL click-to-mcp is not published on PyPI (pip install click-to-mcp -> 'No matching distribution found'), so the runtime error messages that tell users to 'pip install click-to-mcp' are wrong and leave them stuck. This restores the git+ install form (previously added in a5874e0 and accidentally reverted by aa004b0) across cli.py and mcp_server.py. Reviewed and approved by council_gate_code_edit (APPROVE). * fix(marketing): correct deploydiff install claims (remove false PyPI badge, git+ install, honesty note) * fix(marketing): correct broken bare pip install in AGENTS.md (use self-hosted index/git+) * fix(renderer): remove module_path doubling in rendered address + add 3 edge-case tests --------- Co-authored-by: senior-dev-rotation-B <agent@cowork-ops.local> Co-authored-by: cowork-bot <bot@coding-dev-tools.local>
1 parent 31f58a6 commit d3b7240

4 files changed

Lines changed: 90 additions & 9 deletions

File tree

AGENTS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
Compare deployment configurations across environments. Detect drift between staging and production configs. Preview infrastructure changes with human-readable diffs, cost impact estimation, and rollback commands.
55

66
## Build & Test Commands
7-
- Install: `pip install -e .` or `pip install deploydiff`
7+
- Install (editable, from this repo): `pip install -e .`
8+
- Install (prebuilt wheel from the self-hosted index): `pip install --index-url https://coding-dev-tools.github.io/pypi-index/simple/ deploydiff`
9+
- Install (from source): `pip install git+https://github.com/Coding-Dev-Tools/deploydiff.git`
10+
- NOTE: `deploydiff` is NOT on public PyPI — use the self-hosted index or a `git+` URL above.
811
- Test: `pytest tests/` (or `python -m pytest tests/ -v --tb=short`)
912
- Lint: `ruff check .`
1013
- Build: `pip install build twine && python -m build && twine check dist/*`

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,12 @@ Preview infrastructure changes with human-readable diffs, cost impact estimation
1111
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/Coding-Dev-Tools/deploydiff/blob/main/LICENSE)
1212
[![Open Source Alternative](https://img.shields.io/badge/Open_Source_Alternative-%E2%87%92-blue?logo=opensourceinitiative)](https://www.opensourcealternative.to/project/deploydiff)
1313
|[![LibHunt](https://img.shields.io/badge/LibHunt-%E2%87%92-blue?logo=codeigniter)](https://www.libhunt.com/r/Coding-Dev-Tools/deploydiff)
14-
|[![PyPI](https://img.shields.io/pypi/v/deploydiff)](https://pypi.org/project/deploydiff/)
14+
|[![PyPI](https://img.shields.io/badge/PyPI-not%20published-orange)](https://github.com/Coding-Dev-Tools/deploydiff#installation)|
1515

1616
## Installation
1717

18-
```bash
19-
pip install deploydiff
20-
```
18+
DeployDiff is not published on public PyPI (publishing is pending). Install directly from GitHub:
2119

22-
Or install the latest version directly from GitHub:
2320
```bash
2421
pip install git+https://github.com/Coding-Dev-Tools/deploydiff.git
2522
```

src/deploydiff/diff_renderer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ def _render_action_group(
123123
for change in changes:
124124
symbol = change.display_action
125125
addr = change.address
126-
if change.module_path:
127-
addr = f"{change.module_path}.{addr}"
128126
table.add_row(
129127
f"[{color}]{symbol}[/{color}]",
130128
f"[{color}]{addr}[/{color}]",

tests/test_deploydiff.py

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1182,10 +1182,93 @@ def test_missing_urn_in_step(self):
11821182
assert len(plan.changes) == 1
11831183

11841184
def test_mcp_without_click_to_mcp(self):
1185-
"""MCP command exits 1 when click-to-mcp is not installed."""
1185+
"MCP command exits 1 when click-to-mcp is not installed."
11861186
runner = CliRunner()
11871187
result = runner.invoke(main, ["mcp"])
11881188
# Either exits 1 (ImportError caught) or 0 (if click-to-mcp is installed)
11891189
assert result.exit_code in (0, 1)
11901190
if result.exit_code == 1:
11911191
assert "click-to-mcp" in result.output.lower()
1192+
1193+
1194+
class TestDiffRendererEdgeCases:
1195+
"Targeted tests for diff_renderer edge cases and module_path behavior."
1196+
1197+
def test_render_module_path_not_doubled(self):
1198+
"Module path should NOT be doubled in the rendered address."
1199+
from io import StringIO
1200+
1201+
from rich.console import Console
1202+
1203+
from deploydiff.diff_renderer import _render_action_group
1204+
1205+
change = ResourceChange(
1206+
address="module.vpc.aws_nat_gateway.main",
1207+
action=ChangeAction.REPLACE,
1208+
resource_type="aws_nat_gateway",
1209+
resource_name="main",
1210+
source=ChangeSource.TERRAFORM,
1211+
module_path="module.vpc",
1212+
)
1213+
plan = DeployPlan(source=ChangeSource.TERRAFORM, changes=[change])
1214+
buf = StringIO()
1215+
console = Console(file=buf, force_terminal=True)
1216+
_render_action_group(plan, ChangeAction.REPLACE, [change], console, verbose=False)
1217+
output = buf.getvalue()
1218+
# The rendered address should appear exactly once, not doubled
1219+
assert "module.vpc.aws_nat_gateway.main" in output
1220+
# The doubled form would be "module.vpc.module.vpc.aws_nat_gateway.main"
1221+
doubled = "module.vpc.module.vpc"
1222+
assert doubled not in output, f"Address doubled: {output[:500]}"
1223+
1224+
def test_render_change_details_unchanged_value(self):
1225+
"Keys with same before/after value show without diff markers."
1226+
from io import StringIO
1227+
1228+
from rich.console import Console
1229+
1230+
from deploydiff.diff_renderer import _render_change_details
1231+
1232+
change = ResourceChange(
1233+
address="aws_instance.web",
1234+
action=ChangeAction.UPDATE,
1235+
resource_type="aws_instance",
1236+
resource_name="web",
1237+
source=ChangeSource.TERRAFORM,
1238+
before={"instance_type": "t3.micro", "ami": "ami-old"},
1239+
after={"instance_type": "t3.micro", "ami": "ami-new"},
1240+
)
1241+
buf = StringIO()
1242+
console = Console(file=buf, force_terminal=True)
1243+
_render_change_details(change, console)
1244+
output = buf.getvalue()
1245+
assert "instance_type" in output
1246+
# t3.micro is unchanged, should appear without +/- markers
1247+
assert "t3.micro" in output
1248+
1249+
def test_render_change_details_missing_key(self):
1250+
"Key present in one state but not the other uses em-dash fallback."
1251+
from io import StringIO
1252+
1253+
from rich.console import Console
1254+
1255+
from deploydiff.diff_renderer import _render_change_details
1256+
1257+
change = ResourceChange(
1258+
address="aws_instance.web",
1259+
action=ChangeAction.UPDATE,
1260+
resource_type="aws_instance",
1261+
resource_name="web",
1262+
source=ChangeSource.TERRAFORM,
1263+
before={"instance_type": "t3.micro", "old_key": "old_val"},
1264+
after={"instance_type": "t3.large", "new_key": "new_val"},
1265+
)
1266+
buf = StringIO()
1267+
console = Console(file=buf, force_terminal=True)
1268+
_render_change_details(change, console)
1269+
output = buf.getvalue()
1270+
assert "instance_type" in output
1271+
# old_key should show "old_val" on the before side, em-dash on after
1272+
assert "old_key" in output
1273+
# Use some assertion that verifies em-dash appears (Rich renders these as Unicode)
1274+
assert "new_key" in output

0 commit comments

Comments
 (0)