Skip to content

Commit e2f4324

Browse files
authored
Merge pull request #907 from codeflash-ai/ashraf/cf-861-raise-pr-with-the-github-action-installation-for-the-user
calling cf-api while setting up github actions during init command
2 parents 9b2aa3c + 2f3d57b commit e2f4324

File tree

5 files changed

+674
-76
lines changed

5 files changed

+674
-76
lines changed

codeflash/api/aiservice.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,60 @@ def get_optimization_review(
670670
console.rule()
671671
return ""
672672

673+
def generate_workflow_steps(
674+
self,
675+
repo_files: dict[str, str],
676+
directory_structure: dict[str, Any],
677+
codeflash_config: dict[str, Any] | None = None,
678+
) -> str | None:
679+
"""Generate GitHub Actions workflow steps based on repository analysis.
680+
681+
:param repo_files: Dictionary mapping file paths to their contents
682+
:param directory_structure: 2-level nested directory structure
683+
:param codeflash_config: Optional codeflash configuration
684+
:return: YAML string for workflow steps section, or None on error
685+
"""
686+
payload = {
687+
"repo_files": repo_files,
688+
"directory_structure": directory_structure,
689+
"codeflash_config": codeflash_config,
690+
}
691+
692+
logger.debug(
693+
f"[aiservice.py:generate_workflow_steps] Sending request to AI service with {len(repo_files)} files, "
694+
f"{len(directory_structure)} top-level directories"
695+
)
696+
697+
try:
698+
response = self.make_ai_service_request("/workflow-gen", payload=payload, timeout=60)
699+
except requests.exceptions.RequestException as e:
700+
# AI service unavailable - this is expected, will fall back to static workflow
701+
logger.debug(
702+
f"[aiservice.py:generate_workflow_steps] Request exception (falling back to static workflow): {e}"
703+
)
704+
return None
705+
706+
if response.status_code == 200:
707+
response_data = response.json()
708+
workflow_steps = cast("str", response_data.get("workflow_steps"))
709+
logger.debug(
710+
f"[aiservice.py:generate_workflow_steps] Successfully received workflow steps "
711+
f"({len(workflow_steps) if workflow_steps else 0} chars)"
712+
)
713+
return workflow_steps
714+
# AI service unavailable or endpoint not found - this is expected, will fall back to static workflow
715+
logger.debug(
716+
f"[aiservice.py:generate_workflow_steps] AI service returned status {response.status_code}, "
717+
f"falling back to static workflow generation"
718+
)
719+
try:
720+
error_response = response.json()
721+
error = cast("str", error_response.get("error", "Unknown error"))
722+
logger.debug(f"[aiservice.py:generate_workflow_steps] Error: {error}")
723+
except Exception:
724+
logger.debug("[aiservice.py:generate_workflow_steps] Could not parse error response")
725+
return None
726+
673727

674728
class LocalAiServiceClient(AiServiceClient):
675729
"""Client for interacting with the local AI service."""

codeflash/api/cfapi.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,17 @@ def make_cfapi_request(
5555
*,
5656
api_key: str | None = None,
5757
suppress_errors: bool = False,
58+
params: dict[str, Any] | None = None,
5859
) -> Response:
5960
"""Make an HTTP request using the specified method, URL, headers, and JSON payload.
6061
6162
:param endpoint: The endpoint URL to send the request to.
6263
:param method: The HTTP method to use ('GET', 'POST', etc.).
6364
:param payload: Optional JSON payload to include in the POST request body.
65+
:param extra_headers: Optional extra headers to include in the request.
66+
:param api_key: Optional API key to use for authentication.
6467
:param suppress_errors: If True, suppress error logging for HTTP errors.
68+
:param params: Optional query parameters for GET requests.
6569
:return: The response object from the API.
6670
"""
6771
url = f"{get_cfapi_base_urls().cfapi_base_url}/cfapi{endpoint}"
@@ -75,7 +79,7 @@ def make_cfapi_request(
7579
cfapi_headers["Content-Type"] = "application/json"
7680
response = requests.post(url, data=json_payload, headers=cfapi_headers, timeout=60)
7781
else:
78-
response = requests.get(url, headers=cfapi_headers, timeout=60)
82+
response = requests.get(url, headers=cfapi_headers, params=params, timeout=60)
7983
response.raise_for_status()
8084
return response # noqa: TRY300
8185
except requests.exceptions.HTTPError:
@@ -239,6 +243,20 @@ def create_pr(
239243
return make_cfapi_request(endpoint="/create-pr", method="POST", payload=payload)
240244

241245

246+
def setup_github_actions(owner: str, repo: str, base_branch: str, workflow_content: str) -> Response:
247+
"""Set up GitHub Actions workflow by creating a PR with the workflow file.
248+
249+
:param owner: Repository owner (username or organization)
250+
:param repo: Repository name
251+
:param base_branch: Base branch to create PR against (e.g., "main", "master")
252+
:param workflow_content: Content of the GitHub Actions workflow file (YAML)
253+
:return: Response object with pr_url and pr_number on success
254+
"""
255+
payload = {"owner": owner, "repo": repo, "baseBranch": base_branch, "workflowContent": workflow_content}
256+
257+
return make_cfapi_request(endpoint="/setup-github-actions", method="POST", payload=payload)
258+
259+
242260
def create_staging(
243261
original_code: dict[Path, str],
244262
new_code: dict[Path, str],

0 commit comments

Comments
 (0)