Forge (GitHub/GitLab)¶
Forge ABC¶
forge
¶
Git forge abstraction for GitLab and GitHub.
Provides a polymorphic interface for merge/pull request operations,
pipeline status checking, and review comment handling. Follows the
same ABC pattern as agentic_ci.backend and agentic_ci.harness.
Usage::
from agentic_ci.forge import Forge
forge = Forge.detect("https://gitlab.com/org/repo/-/merge_requests/42")
status = forge.mr_status("https://gitlab.com/org/repo/-/merge_requests/42")
ForgeError
¶
Bases: Exception
Raised when a forge API operation fails.
Forge
¶
Bases: ABC
Abstract base for git forge (GitLab/GitHub) API operations.
Concrete implementations handle authentication and API differences.
Use Forge.detect(url) to get the right implementation for a URL.
detect(url, *, github_token=None)
classmethod
¶
Return the correct Forge implementation for a URL.
Inspects the hostname to choose between GitLab and GitHub.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
Any URL on the forge (repo URL, MR/PR URL, etc.). |
required |
github_token
|
str | None
|
Token for GitHub API authentication. |
None
|
Raises:
| Type | Description |
|---|---|
ForgeError
|
If the URL hostname is not recognized. |
Source code in src/agentic_ci/forge/__init__.py
create_merge_request(repo_url, source_branch, target_branch, title, description)
abstractmethod
¶
Create an MR/PR.
Returns (web_url, None) on success or (None, error_msg)
on failure.
Source code in src/agentic_ci/forge/__init__.py
mr_status(mr_url)
abstractmethod
¶
Get MR/PR state, source branch, and pipeline status.
Returns {"state": str, "source_branch": str, "pipeline_status": str}.
State is normalized to "open", "merged", or "closed".
Source code in src/agentic_ci/forge/__init__.py
review_comments(mr_url)
abstractmethod
¶
Get unresolved review comment threads with diff positions.
Returns a list of dicts with keys:
thread_id, file, line, body, author.
general_comments(mr_url, since=None, skip_patterns=None)
abstractmethod
¶
Get general (non-diff-positioned) MR/PR comments.
Returns a list of dicts with keys: author, body, created_at.
Comments created before since (ISO 8601) are excluded.
Comments containing any string in skip_patterns are excluded.
If skip_patterns is None, a default list is used.
Source code in src/agentic_ci/forge/__init__.py
reply(mr_url, thread_id, message)
abstractmethod
¶
resolve(mr_url, thread_id)
abstractmethod
¶
update_description(mr_url, *, title=None, description=None)
abstractmethod
¶
Update an existing MR/PR title and/or description.
Only the provided keyword arguments are updated; omitted fields are left unchanged.
Raises ForgeError on API failure.
Source code in src/agentic_ci/forge/__init__.py
pipeline_failures(mr_url)
abstractmethod
¶
Get failed CI job names and log tails.
Returns {"pipeline_status": str, "failed_jobs": [{"name", "id", "log"}]}.
parse_gitlab_mr_url(url)
¶
Parse a GitLab MR URL into (project_path, mr_iid).
Raises ForgeError if the URL does not match the expected pattern.
Source code in src/agentic_ci/forge/__init__.py
parse_github_pr_url(url)
¶
Parse a GitHub PR URL into (owner/repo, pr_number).
Raises ForgeError if the URL does not match the expected pattern.
Source code in src/agentic_ci/forge/__init__.py
repo_path_from_url(url)
¶
Extract the repository path from a GitLab or GitHub URL.
Strips trailing slashes and .git suffixes.
Source code in src/agentic_ci/forge/__init__.py
detect_forge(url, *, github_token=None)
¶
GitHub¶
github
¶
GitHub forge implementation.
Provides GitHubForge for interacting with the GitHub REST and
GraphQL APIs (pull requests, check runs, review threads).
GitHubForge(token=None)
¶
Bases: Forge
GitHub REST + GraphQL API implementation of the Forge interface.
Source code in src/agentic_ci/forge/github.py
graphql(query, variables=None)
¶
Execute a GitHub GraphQL query or mutation.
Returns the data dict from the response.
Raises ForgeError on HTTP or GraphQL errors.
Source code in src/agentic_ci/forge/github.py
check_runs(repo_path, sha)
¶
Fetch all check runs for a commit SHA.
Returns (check_runs, accessible) where accessible is
False when the token lacks checks:read permission (403).
Source code in src/agentic_ci/forge/github.py
commit_statuses(repo_path, sha)
¶
Fetch commit statuses for a SHA.
GitHub has two parallel CI reporting mechanisms: Check Runs
(used by GitHub Actions) and Commit Statuses (the older API
used by external CI like Prow, Jenkins, and other integrations).
check_runs() only covers the first; this method covers the
second so _derive_pipeline_status() sees the full picture.
Merge-management contexts (tide, Mergify) are excluded
since they reflect merge policy, not CI results.
See https://docs.github.com/en/rest/commits/statuses
Source code in src/agentic_ci/forge/github.py
generate_github_jwt(app_id, private_key_pem)
¶
Generate a GitHub App JWT signed with RS256.
The JWT is valid for 10 minutes (GitHub maximum).
Requires the PyJWT and cryptography packages.
Install with: pip install agentic-ci[forge]
Source code in src/agentic_ci/forge/github.py
get_installation_token(jwt_token, installation_id)
¶
Exchange a GitHub App JWT for an installation access token.
Returns the token string (valid for 1 hour).
Raises RuntimeError on failure.
Source code in src/agentic_ci/forge/github.py
resolve_app_token(repo_url, github_config)
¶
Resolve a GitHub App installation token for a repo URL.
Extracts the GitHub org from repo_url, looks up the matching
App configuration in github_config, and returns a short-lived
installation token.
Returns None (with an error log) on any failure.
Source code in src/agentic_ci/forge/github.py
GitLab¶
gitlab
¶
GitLab forge implementation.
Provides GitLabForge for interacting with the GitLab REST API
(merge requests, pipelines, discussions).
GitLabForge()
¶
Bases: Forge
GitLab REST API implementation of the Forge interface.
Source code in src/agentic_ci/forge/gitlab.py
project_id(project_path)
¶
Look up the numeric GitLab project ID from a project path.
Raises ForgeError if the project cannot be found.
Source code in src/agentic_ci/forge/gitlab.py
mr_diff_position(mr_url)
¶
Get the first changed line position and diff refs from a GitLab MR.
This is a GitLab-specific operation not available on other forges.
Returns {"file", "line", "base_sha", "head_sha", "start_sha"}.
Source code in src/agentic_ci/forge/gitlab.py
CLI¶
cli
¶
CLI subcommands for forge operations.
Registered as the agentic-ci forge subcommand group.
Usage::
agentic-ci forge mr-status <URL>
agentic-ci forge mr-comments <URL>
agentic-ci forge mr-general-comments <URL> [--since ISO]
agentic-ci forge mr-reply <URL> <thread_id> <message>
agentic-ci forge mr-resolve <URL> <thread_id>
agentic-ci forge pipeline-failures <URL>
agentic-ci forge mr-diff-position <URL>
agentic-ci forge github-token --app-id ID --installation-id ID --private-key PEM
cmd_mr_status(args)
¶
Get MR/PR state, source branch, and pipeline status.
Source code in src/agentic_ci/forge/cli.py
cmd_mr_comments(args)
¶
Get unresolved review comment threads.
Source code in src/agentic_ci/forge/cli.py
cmd_mr_general_comments(args)
¶
Get general (non-diff-positioned) MR/PR comments.
Source code in src/agentic_ci/forge/cli.py
cmd_mr_reply(args)
¶
Reply to a review thread.
cmd_mr_resolve(args)
¶
Resolve a review thread.
cmd_pipeline_failures(args)
¶
Get failed CI job names and logs.
Source code in src/agentic_ci/forge/cli.py
cmd_mr_update(args)
¶
Update MR/PR title and/or description.
Source code in src/agentic_ci/forge/cli.py
cmd_mr_diff_position(args)
¶
Get the first changed line position and diff refs (GitLab only).
Source code in src/agentic_ci/forge/cli.py
cmd_github_token(args)
¶
Generate a short-lived GitHub App installation token.
Source code in src/agentic_ci/forge/cli.py
register_subcommands(forge_parser)
¶
Register forge subcommands on the given parser.
Called from the main agentic-ci CLI to wire up the forge
subcommand group.
Source code in src/agentic_ci/forge/cli.py
Session¶
session
¶
HTTP session and adapter configuration for forge API calls.
Provides auth-injecting adapters for GitLab (PRIVATE-TOKEN) and GitHub (Bearer token), plus a pre-configured session with retry logic.
ForgeAuthError
¶
Bases: RuntimeError
Raised when forge API authentication credentials are missing.
GitLabHTTPAdapter
¶
Bases: HTTPAdapter
Requests adapter that injects PRIVATE-TOKEN for GitLab REST API.
GitHubHTTPAdapter(token, **kwargs)
¶
build_session(github_token=None)
¶
Build a requests session with forge-specific auth adapters.
The session automatically injects the correct auth headers based
on the request URL prefix (gitlab.com or api.github.com).
Source code in src/agentic_ci/forge/session.py
extract_api_error(resp)
¶
Extract a human-readable error message from a forge API error response.
Tries message, then errors[0].message, falling back to
"Unknown error".