Skip to content

Commit b1d6484

Browse files
refactor(auto-fork): use runtime env vars + compress docs
Address PR review feedback: - Auto-discover config dir from data/remote-config/*/agent/project-repos.json - Extract instance_id from config dir name (e.g., rehor-config-instance1) - Eliminate BOT_CONFIG_PATH and BOT_INSTANCE_ID env var requirements - Update SKILL.md + README.md to reflect auto-discovery - Update tests to create proper directory structure Skills now auto-discover values instead of requiring bot to set extra env vars. All tests pass (24/24). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 944d01b commit b1d6484

4 files changed

Lines changed: 80 additions & 29 deletions

File tree

.claude/skills/auto-fork/README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,20 @@ python3 auto_fork.py --dry-run
2929

3030
## Configuration
3131

32-
Environment variables (auto-provided by bot runtime):
32+
### Required Environment Variables
3333

34-
- `GH_USER_NAME` — bot GitHub username
34+
- `GH_USER_NAME` — bot GitHub username (validated against GitHub username rules)
3535
- `GL_USER_NAME` — bot GitLab username
36-
- `BOT_CONFIG_PATH` — config directory (default `rehor-config`)
37-
- `BOT_INSTANCE_ID` — optional instance ID (affects branch name)
3836

39-
The script validates that `GH_USER_NAME` follows GitHub username rules and will raise a `ValueError` early if validation fails.
37+
### Auto-Discovered Values
38+
39+
The skill automatically discovers the following without requiring environment variables:
40+
41+
- **Config directory**: Scans `data/remote-config/*/agent/project-repos.json` (bot runtime) or `<config-name>/agent/project-repos.json` (local dev)
42+
- **Instance ID**: Extracted from config directory name
43+
- Pattern: `rehor-config-instance1` → instance ID = `instance1`
44+
- Used for branch naming: `bot/auto-fork-{instance_id}`
45+
- Empty if no instance suffix in config name
4046

4147
## Development
4248

.claude/skills/auto-fork/SKILL.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ After this completes successfully, use the **push-and-pr** skill to push and cre
2828

2929
## Configuration
3030

31-
Env vars (auto-provided by runtime):
31+
Required env vars:
3232

3333
- `GH_USER_NAME` — bot GH username
3434
- `GL_USER_NAME` — bot GL username
35-
- `BOT_CONFIG_PATH` — config dir (default `rehor-config`)
36-
- `BOT_INSTANCE_ID` — instance ID (optional, for branch naming)
35+
36+
Auto-discovered:
37+
38+
- Config directory — scans `data/remote-config/*/agent/project-repos.json`
39+
- Instance ID — extracted from config directory name (e.g., `rehor-config-instance1``instance1`)
3740

3841
## Repo Detection
3942

.claude/skills/auto-fork/auto_fork.py

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,23 +84,15 @@ def __init__(self, dry_run: bool = False):
8484
self.dry_run = dry_run
8585
self.bot_username = os.environ.get("GH_USER_NAME", "")
8686
self.gl_username = os.environ.get("GL_USER_NAME", "")
87-
self.instance_id = os.environ.get("BOT_INSTANCE_ID", "")
88-
self.config_path = os.environ.get("BOT_CONFIG_PATH", "rehor-config")
87+
88+
# Auto-discover config directory and instance ID
89+
self.config_dir, self.config_name, self.instance_id = self._discover_config()
8990

9091
# Validate inputs
9192
self._validate_inputs()
9293

93-
# Determine config directory
94-
# Use remote-config if it exists (bot runtime), else fall back to local config
95-
if REMOTE_CONFIG_DIR.exists() and (REMOTE_CONFIG_DIR / self.config_path).exists():
96-
self.config_dir = REMOTE_CONFIG_DIR
97-
logger.info(f"Using remote config at {self.config_dir}")
98-
else:
99-
self.config_dir = SCRIPT_DIR / self.config_path
100-
logger.info(f"Using local config at {self.config_dir}")
101-
10294
self.agent_dir = (
103-
self.config_dir / self.config_path / "agent"
95+
self.config_dir / self.config_name / "agent"
10496
if self.config_dir == REMOTE_CONFIG_DIR
10597
else self.config_dir / "agent"
10698
)
@@ -110,6 +102,53 @@ def __init__(self, dry_run: bool = False):
110102
self.repos_to_fork: List[RepoInfo] = []
111103
self.forked_repos: Dict[str, str] = {} # name -> fork_url
112104

105+
def _discover_config(self) -> Tuple[Path, str, str]:
106+
"""
107+
Auto-discover config directory and instance ID.
108+
109+
Searches for project-repos.json in:
110+
1. data/remote-config/*/agent/project-repos.json (bot runtime)
111+
2. <config-name>/agent/project-repos.json (local dev)
112+
113+
Returns:
114+
Tuple of (config_dir, config_name, instance_id)
115+
116+
Raises:
117+
ValueError: If no valid config directory found
118+
"""
119+
# Try remote-config first (bot runtime)
120+
if REMOTE_CONFIG_DIR.exists():
121+
for subdir in REMOTE_CONFIG_DIR.iterdir():
122+
if not subdir.is_dir():
123+
continue
124+
candidate = subdir / "agent" / "project-repos.json"
125+
if candidate.exists():
126+
config_name = subdir.name
127+
# Extract instance_id from config name if present
128+
# Pattern: rehor-config-instance1 -> instance1
129+
instance_id = ""
130+
if "-" in config_name:
131+
parts = config_name.split("-")
132+
if len(parts) > 2: # e.g. rehor-config-instance1
133+
instance_id = "-".join(parts[2:])
134+
logger.info(f"Using remote config at {REMOTE_CONFIG_DIR / config_name}")
135+
return REMOTE_CONFIG_DIR, config_name, instance_id
136+
137+
# Fall back to local config (dev environment)
138+
# Try common config directory names
139+
for config_name in ["rehor-config", "config"]:
140+
local_config = SCRIPT_DIR / config_name
141+
candidate = local_config / "agent" / "project-repos.json"
142+
if candidate.exists():
143+
logger.info(f"Using local config at {local_config}")
144+
return local_config, config_name, ""
145+
146+
raise ValueError(
147+
"No config directory found. Expected project-repos.json in:\n"
148+
f" - {REMOTE_CONFIG_DIR}/*/agent/project-repos.json\n"
149+
f" - {SCRIPT_DIR}/<config-name>/agent/project-repos.json"
150+
)
151+
113152
def _validate_inputs(self) -> None:
114153
"""
115154
Validate required environment variables and inputs.
@@ -124,9 +163,6 @@ def _validate_inputs(self) -> None:
124163
if not re.match(r"^[a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$", self.bot_username):
125164
raise ValueError(f"Invalid GitHub username: {self.bot_username}")
126165

127-
if not self.config_path:
128-
raise ValueError("BOT_CONFIG_PATH cannot be empty")
129-
130166
def detect_unforkable_repos(self) -> OperationResult:
131167
"""
132168
Scan project-repos.json for repos needing forks.

.claude/skills/auto-fork/tests/conftest.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
# Test constants
99
TEST_BOT_USERNAME = "test-bot"
10-
TEST_INSTANCE_ID = "test-instance"
1110
GITLAB_HOST = "gitlab.cee.redhat.com" # Match constant from auto_fork.py
1211

1312
# Test data - repos configuration for fixtures
@@ -33,20 +32,22 @@ def set_env_vars(monkeypatch):
3332
"""Set required env vars for all tests."""
3433
monkeypatch.setenv("GH_USER_NAME", TEST_BOT_USERNAME)
3534
monkeypatch.setenv("GL_USER_NAME", TEST_BOT_USERNAME)
36-
monkeypatch.setenv("BOT_INSTANCE_ID", TEST_INSTANCE_ID)
37-
monkeypatch.setenv("BOT_CONFIG_PATH", "test-config")
3835

3936

4037
@pytest.fixture
41-
def temp_config_dir(tmp_path):
38+
def temp_config_dir(tmp_path, monkeypatch):
4239
"""
4340
Create temporary config directory structure with git repo.
4441
4542
Creates:
46-
- test-config/agent/project-repos.json with TEST_REPOS_CONFIG
43+
- data/remote-config/test-config/agent/project-repos.json
4744
- Initialized git repo with origin remote
45+
- Monkeypatches REMOTE_CONFIG_DIR to point to temp location
4846
"""
49-
config_dir = tmp_path / "test-config"
47+
# Create data/remote-config structure (matches bot runtime)
48+
data_dir = tmp_path / "data"
49+
remote_config_dir = data_dir / "remote-config"
50+
config_dir = remote_config_dir / "test-config"
5051
agent_dir = config_dir / "agent"
5152
agent_dir.mkdir(parents=True)
5253

@@ -67,6 +68,11 @@ def temp_config_dir(tmp_path):
6768
check=True,
6869
)
6970

71+
# Monkeypatch REMOTE_CONFIG_DIR to point to temp location
72+
import auto_fork
73+
74+
monkeypatch.setattr(auto_fork, "REMOTE_CONFIG_DIR", remote_config_dir)
75+
7076
return config_dir
7177

7278

0 commit comments

Comments
 (0)