105 lines
3.8 KiB
Python
105 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
import shutil, os
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
OUT = ROOT / "install"
|
|
VER = (ROOT / "VERSION").read_text().strip() if (ROOT / "VERSION").exists() else "0.1.0"
|
|
BUNDLE = OUT / f"cascadingdev-{VER}"
|
|
|
|
def main():
|
|
# Removes the old install bundle if it already exists
|
|
if BUNDLE.exists():
|
|
shutil.rmtree(BUNDLE)
|
|
# Create the directories
|
|
(BUNDLE / "assets" / "hooks").mkdir(parents=True, exist_ok=True)
|
|
(BUNDLE / "assets" / "templates").mkdir(parents=True, exist_ok=True)
|
|
|
|
# Copy the git hook and any other runtime utilities.
|
|
shutil.copy2(ROOT / "assets" / "runtime" / "ramble.py", BUNDLE / "ramble.py")
|
|
shutil.copy2(ROOT / "assets" / "runtime" / "create_feature.py", BUNDLE / "create_feature.py")
|
|
|
|
shutil.copy2(ROOT / "assets" / "hooks" / "pre-commit", BUNDLE / "assets" / "hooks" / "pre-commit")
|
|
|
|
# copy core templates
|
|
|
|
for t in [
|
|
"feature_request.md",
|
|
"feature.discussion.md",
|
|
"feature.discussion.sum.md",
|
|
"design.discussion.md",
|
|
"design_doc.md",
|
|
"USER_GUIDE.md",
|
|
"root_gitignore",
|
|
]:
|
|
shutil.copy2(ROOT / "assets" / "templates" / t, BUNDLE / "assets" / "templates" / t)
|
|
|
|
# copy (recursively) the contents of process/ and rules/ templates folders
|
|
def copy_tree(src, dst):
|
|
if dst.exists():
|
|
shutil.rmtree(dst)
|
|
shutil.copytree(src, dst)
|
|
copy_tree(ROOT / "assets" / "templates" / "process", BUNDLE / "assets" / "templates" / "process")
|
|
copy_tree(ROOT / "assets" / "templates" / "rules", BUNDLE / "assets" / "templates" / "rules")
|
|
|
|
# copy shared AI configuration
|
|
config_src = ROOT / "config"
|
|
if config_src.exists():
|
|
copy_tree(config_src, BUNDLE / "config")
|
|
|
|
# copy agents directory
|
|
agents_src = ROOT / "agents"
|
|
if agents_src.exists():
|
|
copy_tree(agents_src, BUNDLE / "agents")
|
|
|
|
# copy automation directory (workflow.py and future orchestration scripts)
|
|
automation_src = ROOT / "automation"
|
|
if automation_src.exists():
|
|
copy_tree(automation_src, BUNDLE / "automation")
|
|
|
|
# copy agent SDK
|
|
sdk_src = ROOT / "src" / "cascadingdev"
|
|
if sdk_src.exists():
|
|
copy_tree(sdk_src, BUNDLE / "sdk" / "cascadingdev")
|
|
|
|
# write installer entrypoint
|
|
shutil.copy2(ROOT / "src" / "cascadingdev" / "setup_project.py",
|
|
BUNDLE / "setup_cascadingdev.py")
|
|
|
|
install_doc = """# CascadingDev Installer
|
|
|
|
## Requirements
|
|
- Python 3.10+ and git
|
|
- (Optional) PySide6 or PyQt5 for the Ramble GUI
|
|
|
|
## Quick Start
|
|
```bash
|
|
python setup_cascadingdev.py --target /path/to/your-project
|
|
```
|
|
|
|
### Options
|
|
- `--target PATH`: directory to create or reuse for the repo
|
|
- `--no-ramble`: skip the Ramble GUI and answer prompts in the terminal
|
|
- `--provider {mock,claude}`: select the Ramble provider (default: mock)
|
|
- `--claude-cmd CMD`: command to invoke when provider is `claude`
|
|
|
|
### Steps Performed
|
|
1. Creates the standard CascadingDev folder layout in the target.
|
|
2. Copies templates, policies, rules, and runtime scripts into place.
|
|
3. Initializes git (if needed) and installs the pre-commit hook.
|
|
4. Launches Ramble unless `--no-ramble` is provided.
|
|
5. Seeds initial feature discussions, summaries, and rules.
|
|
6. Commits the bootstrap state so the repo starts clean.
|
|
|
|
### Troubleshooting
|
|
- If the GUI fails, activate a virtualenv then `pip install PySide6`, or rerun with `--no-ramble`.
|
|
- Ensure `git` is available on PATH; the installer runs `git init` and `git commit`.
|
|
- Remove or empty the target directory if rerunning into conflicting files.
|
|
"""
|
|
(BUNDLE / "INSTALL.md").write_text(install_doc.strip() + "\n", encoding="utf-8")
|
|
(BUNDLE / "VERSION").write_text(VER, encoding="utf-8")
|
|
print(f"[✓] Built installer → {BUNDLE}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|