Initial commit
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env -S uv run
|
||||
# /// script
|
||||
# dependencies = ["python-dotenv", "pydantic"]
|
||||
# ///
|
||||
|
||||
"""
|
||||
ADW Plan Build Test Review Iso - Compositional workflow for isolated planning, building, testing, and reviewing
|
||||
|
||||
Usage: uv run adw_plan_build_test_review_iso.py <issue-number> [adw-id] [--skip-e2e] [--skip-resolution]
|
||||
|
||||
This script runs:
|
||||
1. adw_plan_iso.py - Planning phase (isolated)
|
||||
2. adw_build_iso.py - Implementation phase (isolated)
|
||||
3. adw_test_iso.py - Testing phase (isolated)
|
||||
4. adw_review_iso.py - Review phase (isolated)
|
||||
|
||||
The scripts are chained together via persistent state (adw_state.json).
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add the parent directory to Python path to import modules
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from adw_modules.workflow_ops import ensure_adw_id
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point."""
|
||||
# Check for flags
|
||||
skip_e2e = "--skip-e2e" in sys.argv
|
||||
skip_resolution = "--skip-resolution" in sys.argv
|
||||
|
||||
# Remove flags from argv
|
||||
if skip_e2e:
|
||||
sys.argv.remove("--skip-e2e")
|
||||
if skip_resolution:
|
||||
sys.argv.remove("--skip-resolution")
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: uv run adw_plan_build_test_review_iso.py <issue-number> [adw-id] [--skip-e2e] [--skip-resolution]")
|
||||
print("\nThis runs the isolated plan, build, test, and review workflow:")
|
||||
print(" 1. Plan (isolated)")
|
||||
print(" 2. Build (isolated)")
|
||||
print(" 3. Test (isolated)")
|
||||
print(" 4. Review (isolated)")
|
||||
sys.exit(1)
|
||||
|
||||
issue_number = sys.argv[1]
|
||||
adw_id = sys.argv[2] if len(sys.argv) > 2 else None
|
||||
|
||||
# Ensure ADW ID exists with initialized state
|
||||
adw_id = ensure_adw_id(issue_number, adw_id)
|
||||
print(f"Using ADW ID: {adw_id}")
|
||||
|
||||
# Get the directory where this script is located
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# Run isolated plan with the ADW ID
|
||||
plan_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_plan_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
]
|
||||
print(f"\n=== ISOLATED PLAN PHASE ===")
|
||||
print(f"Running: {' '.join(plan_cmd)}")
|
||||
plan = subprocess.run(plan_cmd)
|
||||
if plan.returncode != 0:
|
||||
print("Isolated plan phase failed")
|
||||
sys.exit(1)
|
||||
|
||||
# Run isolated build with the ADW ID
|
||||
build_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_build_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
]
|
||||
print(f"\n=== ISOLATED BUILD PHASE ===")
|
||||
print(f"Running: {' '.join(build_cmd)}")
|
||||
build = subprocess.run(build_cmd)
|
||||
if build.returncode != 0:
|
||||
print("Isolated build phase failed")
|
||||
sys.exit(1)
|
||||
|
||||
# Run isolated test with the ADW ID
|
||||
test_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_test_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
]
|
||||
if skip_e2e:
|
||||
test_cmd.append("--skip-e2e")
|
||||
|
||||
print(f"\n=== ISOLATED TEST PHASE ===")
|
||||
print(f"Running: {' '.join(test_cmd)}")
|
||||
test = subprocess.run(test_cmd)
|
||||
if test.returncode != 0:
|
||||
print("Isolated test phase failed")
|
||||
sys.exit(1)
|
||||
|
||||
# Run isolated review with the ADW ID
|
||||
review_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_review_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
]
|
||||
if skip_resolution:
|
||||
review_cmd.append("--skip-resolution")
|
||||
|
||||
print(f"\n=== ISOLATED REVIEW PHASE ===")
|
||||
print(f"Running: {' '.join(review_cmd)}")
|
||||
review = subprocess.run(review_cmd)
|
||||
if review.returncode != 0:
|
||||
print("Isolated review phase failed")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"\n=== ISOLATED WORKFLOW COMPLETED ===")
|
||||
print(f"ADW ID: {adw_id}")
|
||||
print(f"All phases completed successfully!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
152
skills/adw-bootstrap/reference/scaled/workflows/adw_sdlc_iso.py
Normal file
152
skills/adw-bootstrap/reference/scaled/workflows/adw_sdlc_iso.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env -S uv run
|
||||
# /// script
|
||||
# dependencies = ["python-dotenv", "pydantic"]
|
||||
# ///
|
||||
|
||||
"""
|
||||
ADW SDLC Iso - Complete Software Development Life Cycle workflow with isolation
|
||||
|
||||
Usage: uv run adw_sdlc_iso.py <issue-number> [adw-id] [--skip-e2e] [--skip-resolution]
|
||||
|
||||
This script runs the complete ADW SDLC pipeline in isolation:
|
||||
1. adw_plan_iso.py - Planning phase (isolated)
|
||||
2. adw_build_iso.py - Implementation phase (isolated)
|
||||
3. adw_test_iso.py - Testing phase (isolated)
|
||||
4. adw_review_iso.py - Review phase (isolated)
|
||||
5. adw_document_iso.py - Documentation phase (isolated)
|
||||
|
||||
The scripts are chained together via persistent state (adw_state.json).
|
||||
Each phase runs in its own git worktree with dedicated ports.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add the parent directory to Python path to import modules
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from adw_modules.workflow_ops import ensure_adw_id
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point."""
|
||||
# Check for flags
|
||||
skip_e2e = "--skip-e2e" in sys.argv
|
||||
skip_resolution = "--skip-resolution" in sys.argv
|
||||
|
||||
# Remove flags from argv
|
||||
if skip_e2e:
|
||||
sys.argv.remove("--skip-e2e")
|
||||
if skip_resolution:
|
||||
sys.argv.remove("--skip-resolution")
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: uv run adw_sdlc_iso.py <issue-number> [adw-id] [--skip-e2e] [--skip-resolution]")
|
||||
print("\nThis runs the complete isolated Software Development Life Cycle:")
|
||||
print(" 1. Plan (isolated)")
|
||||
print(" 2. Build (isolated)")
|
||||
print(" 3. Test (isolated)")
|
||||
print(" 4. Review (isolated)")
|
||||
print(" 5. Document (isolated)")
|
||||
sys.exit(1)
|
||||
|
||||
issue_number = sys.argv[1]
|
||||
adw_id = sys.argv[2] if len(sys.argv) > 2 else None
|
||||
|
||||
# Ensure ADW ID exists with initialized state
|
||||
adw_id = ensure_adw_id(issue_number, adw_id)
|
||||
print(f"Using ADW ID: {adw_id}")
|
||||
|
||||
# Get the directory where this script is located
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# Run isolated plan with the ADW ID
|
||||
plan_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_plan_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
]
|
||||
print(f"\n=== ISOLATED PLAN PHASE ===")
|
||||
print(f"Running: {' '.join(plan_cmd)}")
|
||||
plan = subprocess.run(plan_cmd)
|
||||
if plan.returncode != 0:
|
||||
print("Isolated plan phase failed")
|
||||
sys.exit(1)
|
||||
|
||||
# Run isolated build with the ADW ID
|
||||
build_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_build_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
]
|
||||
print(f"\n=== ISOLATED BUILD PHASE ===")
|
||||
print(f"Running: {' '.join(build_cmd)}")
|
||||
build = subprocess.run(build_cmd)
|
||||
if build.returncode != 0:
|
||||
print("Isolated build phase failed")
|
||||
sys.exit(1)
|
||||
|
||||
# Run isolated test with the ADW ID
|
||||
test_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_test_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
"--skip-e2e", # Always skip E2E tests in SDLC workflows
|
||||
]
|
||||
|
||||
print(f"\n=== ISOLATED TEST PHASE ===")
|
||||
print(f"Running: {' '.join(test_cmd)}")
|
||||
test = subprocess.run(test_cmd)
|
||||
if test.returncode != 0:
|
||||
print("Isolated test phase failed")
|
||||
# Note: Continue anyway as some tests might be flaky
|
||||
print("WARNING: Test phase failed but continuing with review")
|
||||
|
||||
# Run isolated review with the ADW ID
|
||||
review_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_review_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
]
|
||||
if skip_resolution:
|
||||
review_cmd.append("--skip-resolution")
|
||||
|
||||
print(f"\n=== ISOLATED REVIEW PHASE ===")
|
||||
print(f"Running: {' '.join(review_cmd)}")
|
||||
review = subprocess.run(review_cmd)
|
||||
if review.returncode != 0:
|
||||
print("Isolated review phase failed")
|
||||
sys.exit(1)
|
||||
|
||||
# Run isolated documentation with the ADW ID
|
||||
document_cmd = [
|
||||
"uv",
|
||||
"run",
|
||||
os.path.join(script_dir, "adw_document_iso.py"),
|
||||
issue_number,
|
||||
adw_id,
|
||||
]
|
||||
print(f"\n=== ISOLATED DOCUMENTATION PHASE ===")
|
||||
print(f"Running: {' '.join(document_cmd)}")
|
||||
document = subprocess.run(document_cmd)
|
||||
if document.returncode != 0:
|
||||
print("Isolated documentation phase failed")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"\n=== ISOLATED SDLC COMPLETED ===")
|
||||
print(f"ADW ID: {adw_id}")
|
||||
print(f"All phases completed successfully!")
|
||||
print(f"\nWorktree location: trees/{adw_id}/")
|
||||
print(f"To clean up: ./scripts/purge_tree.sh {adw_id}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
340
skills/adw-bootstrap/reference/scaled/workflows/adw_ship_iso.py
Executable file
340
skills/adw-bootstrap/reference/scaled/workflows/adw_ship_iso.py
Executable file
@@ -0,0 +1,340 @@
|
||||
#!/usr/bin/env -S uv run
|
||||
# /// script
|
||||
# dependencies = ["python-dotenv", "pydantic"]
|
||||
# ///
|
||||
|
||||
"""
|
||||
ADW Ship Iso - AI Developer Workflow for shipping (merging) to main
|
||||
|
||||
Usage:
|
||||
uv run adw_ship_iso.py <issue-number> <adw-id>
|
||||
|
||||
Workflow:
|
||||
1. Load state and validate worktree exists
|
||||
2. Validate ALL state fields are populated (not None)
|
||||
3. Perform manual git merge in main repository:
|
||||
- Fetch latest from origin
|
||||
- Checkout main
|
||||
- Merge feature branch
|
||||
- Push to origin/main
|
||||
4. Post success message to issue
|
||||
|
||||
This workflow REQUIRES that all previous workflows have been run and that
|
||||
every field in ADWState has a value. This is our final approval step.
|
||||
|
||||
Note: Merge operations happen in the main repository root, not in the worktree,
|
||||
to preserve the worktree's state.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
import json
|
||||
import subprocess
|
||||
from typing import Optional, Dict, Any, Tuple
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from adw_modules.state import ADWState
|
||||
from adw_modules.github import (
|
||||
make_issue_comment,
|
||||
get_repo_url,
|
||||
extract_repo_path,
|
||||
)
|
||||
from adw_modules.beads_integration import is_beads_issue, close_beads_issue
|
||||
from adw_modules.workflow_ops import format_issue_message
|
||||
from adw_modules.worktree_ops import validate_worktree
|
||||
from adw_modules.data_types import ADWStateData
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Agent name constant
|
||||
AGENT_SHIPPER = "shipper"
|
||||
|
||||
|
||||
def get_main_repo_root() -> str:
|
||||
"""Get the main repository root directory (parent of adws)."""
|
||||
# This script is in adws/, so go up one level to get repo root
|
||||
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
def manual_merge_to_main(branch_name: str, logger: logging.Logger) -> Tuple[bool, Optional[str]]:
|
||||
"""Manually merge a branch to main using git commands.
|
||||
|
||||
This runs in the main repository root, not in a worktree.
|
||||
|
||||
Args:
|
||||
branch_name: The feature branch to merge
|
||||
logger: Logger instance
|
||||
|
||||
Returns:
|
||||
Tuple of (success, error_message)
|
||||
"""
|
||||
repo_root = get_main_repo_root()
|
||||
logger.info(f"Performing manual merge in main repository: {repo_root}")
|
||||
|
||||
try:
|
||||
# Save current branch to restore later
|
||||
result = subprocess.run(
|
||||
["git", "rev-parse", "--abbrev-ref", "HEAD"],
|
||||
capture_output=True, text=True, cwd=repo_root
|
||||
)
|
||||
original_branch = result.stdout.strip()
|
||||
logger.debug(f"Original branch: {original_branch}")
|
||||
|
||||
# Step 1: Fetch latest from origin
|
||||
logger.info("Fetching latest from origin...")
|
||||
result = subprocess.run(
|
||||
["git", "fetch", "origin"],
|
||||
capture_output=True, text=True, cwd=repo_root
|
||||
)
|
||||
if result.returncode != 0:
|
||||
return False, f"Failed to fetch from origin: {result.stderr}"
|
||||
|
||||
# Step 2: Checkout main
|
||||
logger.info("Checking out main branch...")
|
||||
result = subprocess.run(
|
||||
["git", "checkout", "main"],
|
||||
capture_output=True, text=True, cwd=repo_root
|
||||
)
|
||||
if result.returncode != 0:
|
||||
return False, f"Failed to checkout main: {result.stderr}"
|
||||
|
||||
# Step 3: Pull latest main
|
||||
logger.info("Pulling latest main...")
|
||||
result = subprocess.run(
|
||||
["git", "pull", "origin", "main"],
|
||||
capture_output=True, text=True, cwd=repo_root
|
||||
)
|
||||
if result.returncode != 0:
|
||||
# Try to restore original branch
|
||||
subprocess.run(["git", "checkout", original_branch], cwd=repo_root)
|
||||
return False, f"Failed to pull latest main: {result.stderr}"
|
||||
|
||||
# Step 4: Merge the feature branch (no-ff to preserve all commits)
|
||||
logger.info(f"Merging branch {branch_name} (no-ff to preserve all commits)...")
|
||||
result = subprocess.run(
|
||||
["git", "merge", branch_name, "--no-ff", "-m", f"Merge branch '{branch_name}' via ADW Ship workflow"],
|
||||
capture_output=True, text=True, cwd=repo_root
|
||||
)
|
||||
if result.returncode != 0:
|
||||
# Try to restore original branch
|
||||
subprocess.run(["git", "checkout", original_branch], cwd=repo_root)
|
||||
return False, f"Failed to merge {branch_name}: {result.stderr}"
|
||||
|
||||
# Step 5: Push to origin/main
|
||||
logger.info("Pushing to origin/main...")
|
||||
result = subprocess.run(
|
||||
["git", "push", "origin", "main"],
|
||||
capture_output=True, text=True, cwd=repo_root
|
||||
)
|
||||
if result.returncode != 0:
|
||||
# Try to restore original branch
|
||||
subprocess.run(["git", "checkout", original_branch], cwd=repo_root)
|
||||
return False, f"Failed to push to origin/main: {result.stderr}"
|
||||
|
||||
# Step 6: Restore original branch
|
||||
logger.info(f"Restoring original branch: {original_branch}")
|
||||
subprocess.run(["git", "checkout", original_branch], cwd=repo_root)
|
||||
|
||||
logger.info("✅ Successfully merged and pushed to main!")
|
||||
return True, None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error during merge: {e}")
|
||||
# Try to restore original branch
|
||||
try:
|
||||
subprocess.run(["git", "checkout", original_branch], cwd=repo_root)
|
||||
except:
|
||||
pass
|
||||
return False, str(e)
|
||||
|
||||
|
||||
def validate_state_completeness(state: ADWState, logger: logging.Logger) -> tuple[bool, list[str]]:
|
||||
"""Validate that all fields in ADWState have values (not None).
|
||||
|
||||
Returns:
|
||||
tuple of (is_valid, missing_fields)
|
||||
"""
|
||||
# Get the expected fields from ADWStateData model
|
||||
expected_fields = {
|
||||
"adw_id",
|
||||
"issue_number",
|
||||
"branch_name",
|
||||
"plan_file",
|
||||
"issue_class",
|
||||
"worktree_path",
|
||||
"backend_port",
|
||||
"frontend_port",
|
||||
}
|
||||
|
||||
missing_fields = []
|
||||
|
||||
for field in expected_fields:
|
||||
value = state.get(field)
|
||||
if value is None:
|
||||
missing_fields.append(field)
|
||||
logger.warning(f"Missing required field: {field}")
|
||||
else:
|
||||
logger.debug(f"✓ {field}: {value}")
|
||||
|
||||
return len(missing_fields) == 0, missing_fields
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point."""
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Parse command line args
|
||||
# INTENTIONAL: adw-id is REQUIRED - we need it to find the worktree and state
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: uv run adw_ship_iso.py <issue-number> <adw-id>")
|
||||
print("\nError: Both issue-number and adw-id are required")
|
||||
print("Run the complete SDLC workflow before shipping")
|
||||
sys.exit(1)
|
||||
|
||||
issue_number = sys.argv[1]
|
||||
adw_id = sys.argv[2]
|
||||
|
||||
# Try to load existing state
|
||||
state = ADWState.load(adw_id, logger)
|
||||
if not state:
|
||||
# No existing state found
|
||||
logger.error(f"No state found for ADW ID: {adw_id}")
|
||||
logger.error("Run the complete SDLC workflow before shipping")
|
||||
print(f"\nError: No state found for ADW ID: {adw_id}")
|
||||
print("Run the complete SDLC workflow before shipping")
|
||||
sys.exit(1)
|
||||
|
||||
# Update issue number from state if available
|
||||
issue_number = state.get("issue_number", issue_number)
|
||||
|
||||
# Track that this ADW workflow has run
|
||||
state.append_adw_id("adw_ship_iso")
|
||||
|
||||
logger.info(f"ADW Ship Iso starting - ID: {adw_id}, Issue: {issue_number}")
|
||||
|
||||
# Check if this is a beads issue
|
||||
is_beads = is_beads_issue(issue_number)
|
||||
logger.info(f"Issue type: {'beads' if is_beads else 'GitHub'}")
|
||||
|
||||
# Post initial status (only for GitHub issues)
|
||||
if not is_beads:
|
||||
make_issue_comment(
|
||||
issue_number,
|
||||
format_issue_message(adw_id, "ops", f"🚢 Starting ship workflow\n"
|
||||
f"📋 Validating state completeness...")
|
||||
)
|
||||
|
||||
# Step 1: Validate state completeness
|
||||
logger.info("Validating state completeness...")
|
||||
is_valid, missing_fields = validate_state_completeness(state, logger)
|
||||
|
||||
if not is_valid:
|
||||
error_msg = f"State validation failed. Missing fields: {', '.join(missing_fields)}"
|
||||
logger.error(error_msg)
|
||||
if not is_beads:
|
||||
make_issue_comment(
|
||||
issue_number,
|
||||
format_issue_message(adw_id, AGENT_SHIPPER, f"❌ {error_msg}\n\n"
|
||||
"Please ensure all workflows have been run:\n"
|
||||
"- adw_plan_iso.py (creates plan_file, branch_name, issue_class)\n"
|
||||
"- adw_build_iso.py (implements the plan)\n"
|
||||
"- adw_test_iso.py (runs tests)\n"
|
||||
"- adw_review_iso.py (reviews implementation)\n"
|
||||
"- adw_document_iso.py (generates docs)")
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
logger.info("✅ State validation passed - all fields have values")
|
||||
|
||||
# Step 2: Validate worktree exists
|
||||
valid, error = validate_worktree(adw_id, state)
|
||||
if not valid:
|
||||
logger.error(f"Worktree validation failed: {error}")
|
||||
if not is_beads:
|
||||
make_issue_comment(
|
||||
issue_number,
|
||||
format_issue_message(adw_id, AGENT_SHIPPER, f"❌ Worktree validation failed: {error}")
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
worktree_path = state.get("worktree_path")
|
||||
logger.info(f"✅ Worktree validated at: {worktree_path}")
|
||||
|
||||
# Step 3: Get branch name
|
||||
branch_name = state.get("branch_name")
|
||||
logger.info(f"Preparing to merge branch: {branch_name}")
|
||||
|
||||
if not is_beads:
|
||||
make_issue_comment(
|
||||
issue_number,
|
||||
format_issue_message(adw_id, AGENT_SHIPPER, f"📋 State validation complete\n"
|
||||
f"🔍 Preparing to merge branch: {branch_name}")
|
||||
)
|
||||
|
||||
# Step 4: Perform manual merge
|
||||
logger.info(f"Starting manual merge of {branch_name} to main...")
|
||||
if not is_beads:
|
||||
make_issue_comment(
|
||||
issue_number,
|
||||
format_issue_message(adw_id, AGENT_SHIPPER, f"🔀 Merging {branch_name} to main...\n"
|
||||
"Using manual git operations in main repository")
|
||||
)
|
||||
|
||||
success, error = manual_merge_to_main(branch_name, logger)
|
||||
|
||||
if not success:
|
||||
logger.error(f"Failed to merge: {error}")
|
||||
if not is_beads:
|
||||
make_issue_comment(
|
||||
issue_number,
|
||||
format_issue_message(adw_id, AGENT_SHIPPER, f"❌ Failed to merge: {error}")
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
logger.info(f"✅ Successfully merged {branch_name} to main")
|
||||
|
||||
# Step 5: Close beads issue if applicable
|
||||
if is_beads:
|
||||
logger.info(f"Closing beads issue: {issue_number}")
|
||||
success, error = close_beads_issue(
|
||||
issue_number,
|
||||
f"Completed via ADW {adw_id} - merged to main"
|
||||
)
|
||||
if not success:
|
||||
logger.warning(f"Failed to close beads issue: {error}")
|
||||
else:
|
||||
logger.info(f"✅ Closed beads issue: {issue_number}")
|
||||
|
||||
# Step 6: Post success message (only for GitHub issues)
|
||||
if not is_beads:
|
||||
make_issue_comment(
|
||||
issue_number,
|
||||
format_issue_message(adw_id, AGENT_SHIPPER,
|
||||
f"🎉 **Successfully shipped!**\n\n"
|
||||
f"✅ Validated all state fields\n"
|
||||
f"✅ Merged branch `{branch_name}` to main\n"
|
||||
f"✅ Pushed to origin/main\n\n"
|
||||
f"🚢 Code has been deployed to production!")
|
||||
)
|
||||
|
||||
# Save final state
|
||||
state.save("adw_ship_iso")
|
||||
|
||||
# Post final state summary (only for GitHub issues)
|
||||
if not is_beads:
|
||||
make_issue_comment(
|
||||
issue_number,
|
||||
f"{adw_id}_ops: 📋 Final ship state:\n```json\n{json.dumps(state.data, indent=2)}\n```"
|
||||
)
|
||||
|
||||
logger.info("Ship workflow completed successfully")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user