Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/cowork-auto-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ jobs:
set -eu
existing=$(gh pr list --repo "$GITHUB_REPOSITORY" --head "$GITHUB_REF_NAME" --state open --json number --jq 'length')
if [ "$existing" = "0" ]; then
# The default GITHUB_TOKEN may lack pull-requests:write in some org
# configurations. Fail gracefully so the CI job stays green; the PR
# can be opened externally (e.g. by the orchestrator agent).
gh pr create --repo "$GITHUB_REPOSITORY" \
--head "$GITHUB_REF_NAME" \
--title "cowork-bot: automated improvements ($GITHUB_REF_NAME)" \
--body "Automated improvement PR from the Cowork repo-improver rotation (one coherent senior-dev improvement per run; see individual commit messages). Subsequent runs push additional commits to this PR rather than opening new ones."
--body "Automated improvement PR from the Cowork repo-improver rotation (one coherent senior-dev improvement per run; see individual commit messages). Subsequent runs push additional commits to this PR rather than opening new ones." \
|| echo "::warning::gh pr create failed (likely token permission). Open the PR manually or via an external agent."
else
echo "Open PR already exists for $GITHUB_REF_NAME — nothing to do."
fi
2 changes: 1 addition & 1 deletion src/configdrift/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ def scan(
# Use directory basenames as env names
dir_mapping = {}
for d in dirs:
env_name = Path(d).stem
env_name = Path(d).name
dir_mapping[env_name] = d
else:
console.print(
Expand Down
34 changes: 34 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,40 @@ def test_scan_env_and_toml_dirs(self):
data = json.loads(result.stdout)
assert "prod" in data

def test_scan_dir_names_with_dots_preserved(self):
"""Dir names containing dots must not be truncated by Path.stem."""
with tempfile.TemporaryDirectory() as tmpdir:
dev_dir = Path(tmpdir) / "dev"
prod_us = Path(tmpdir) / "prod.us"
prod_eu = Path(tmpdir) / "prod.eu"
dev_dir.mkdir()
prod_us.mkdir()
prod_eu.mkdir()
(dev_dir / "c.yaml").write_text(yaml.dump({"host": "localhost"}))
(prod_us / "c.yaml").write_text(yaml.dump({"host": "us.example.com"}))
(prod_eu / "c.yaml").write_text(yaml.dump({"host": "eu.example.com"}))

# Table output: all 3 envs must appear as distinct columns
result = runner.invoke(
app,
["scan", str(dev_dir), str(prod_us), str(prod_eu)],
)
assert result.exit_code == 0, f"STDOUT: {result.stdout}"
assert "dev →" in result.stdout, "Baseline 'dev' should appear in table"
assert "prod.us" in result.stdout, f"Missing prod.us in output:\n{result.stdout}"
assert "prod.eu" in result.stdout, f"Missing prod.eu in output:\n{result.stdout}"

# JSON output: both targets must be separate keys (not collapsed)
result2 = runner.invoke(
app,
["scan", str(dev_dir), str(prod_us), str(prod_eu), "--output", "json"],
)
assert result2.exit_code == 0, f"STDOUT: {result2.stdout}"
data = json.loads(result2.stdout)
assert "prod.us" in data, f"Missing prod.us in {list(data.keys())}"
assert "prod.eu" in data, f"Missing prod.eu in {list(data.keys())}"
assert len(data) == 2, f"Expected 2 targets, got {len(data)}: {list(data.keys())}"

def test_scan_no_changes_env_skipped_in_table(self):
"""Scan with multiple envs where one has no changes."""
with tempfile.TemporaryDirectory() as tmpdir:
Expand Down
Loading