Module: Brainiac::Plugins::Github::AppClient

Defined in:
lib/brainiac/plugins/github/app_client.rb

Overview

HTTP client that authenticates as a GitHub App (installation).

When app credentials are configured (app_id + private_key_path + installation_id), API calls are made as the App's bot user — so PR comments, reactions, etc. appear with the App's identity rather than a personal user.

Supports per-agent apps: if "apps" hash in config has an entry for the agent, that agent's app credentials are used (separate avatar/identity per agent). Falls back to shared "app" config, then to gh CLI.

Constant Summary collapse

GITHUB_API =
"https://api.github.com"
TOKEN_EXPIRY_BUFFER =

refresh token 60s before expiry

60

Class Method Summary collapse

Class Method Details

.configured?(agent_key = nil) ⇒ Boolean

Returns true if GitHub App credentials are fully configured. Checks per-agent first, then shared app config. Guards against empty-string values (common in template configs).

Returns:



34
35
36
37
38
39
40
# File 'lib/brainiac/plugins/github/app_client.rb', line 34

def configured?(agent_key = nil)
  id = Config.app_id(agent_key)
  key_path = Config.private_key_path(agent_key)
  inst_id = Config.installation_id(agent_key)

  !!(id && !id.empty? && key_path && inst_id && !inst_id.empty?)
end

.create_comment(repo, pr_number, body, agent_key: nil) ⇒ Hash

POST a comment on an issue or PR.

Parameters:

  • "owner/repo"

  • comment markdown

  • (defaults to: nil)

    agent key for per-agent app identity

Returns:

  • parsed response



49
50
51
# File 'lib/brainiac/plugins/github/app_client.rb', line 49

def create_comment(repo, pr_number, body, agent_key: nil)
  post("/repos/#{repo}/issues/#{pr_number}/comments", { body: body }, agent_key: agent_key)
end

.create_comment_reaction(repo, comment_id, reaction, agent_key: nil) ⇒ Hash

POST a reaction on an issue comment.

Parameters:

  • "owner/repo"

  • e.g. "eyes", "+1", "rocket"

  • (defaults to: nil)

    agent key for per-agent app identity

Returns:

  • parsed response



60
61
62
# File 'lib/brainiac/plugins/github/app_client.rb', line 60

def create_comment_reaction(repo, comment_id, reaction, agent_key: nil)
  post("/repos/#{repo}/issues/comments/#{comment_id}/reactions", { content: reaction }, agent_key: agent_key)
end

.create_pr_reaction(repo, pr_number, reaction, agent_key: nil) ⇒ Hash

POST a reaction on a PR (or issue) itself.

GitHub's reactions API has NO endpoint for PR reviews — only for issue comments, PR review comments, issues, and PRs. Since a PR is an issue under the hood, PR reactions go through the issues path.

Parameters:

  • "owner/repo"

  • e.g. "eyes", "+1", "rocket"

  • (defaults to: nil)

    agent key for per-agent app identity

Returns:

  • parsed response



75
76
77
# File 'lib/brainiac/plugins/github/app_client.rb', line 75

def create_pr_reaction(repo, pr_number, reaction, agent_key: nil)
  post("/repos/#{repo}/issues/#{pr_number}/reactions", { content: reaction }, agent_key: agent_key)
end

.get(path, agent_key: nil) ⇒ Hash

GET request to GitHub API.

Parameters:

  • API path (e.g. "/repos/owner/repo/pulls/1")

  • (defaults to: nil)

    agent key for per-agent app identity

Returns:

  • parsed response



84
85
86
# File 'lib/brainiac/plugins/github/app_client.rb', line 84

def get(path, agent_key: nil)
  request(:get, path, agent_key: agent_key)
end

.installation_token_for(agent_key = nil, repo_owner: nil) ⇒ Object

Public accessor for installation tokens (used to inject GH_TOKEN into agent env). Returns the raw token string, or nil on failure.



107
108
109
110
111
# File 'lib/brainiac/plugins/github/app_client.rb', line 107

def installation_token_for(agent_key = nil, repo_owner: nil)
  installation_token(agent_key, repo_owner: repo_owner)
rescue StandardError
  nil
end

.post(path, body, agent_key: nil) ⇒ Hash

POST request to GitHub API.

Parameters:

  • API path

  • request body

  • (defaults to: nil)

    agent key for per-agent app identity

Returns:

  • parsed response



94
95
96
# File 'lib/brainiac/plugins/github/app_client.rb', line 94

def post(path, body, agent_key: nil)
  request(:post, path, body, agent_key: agent_key)
end

.reset!Object

Reset cached tokens (useful for testing or when credentials change).



99
100
101
102
103
# File 'lib/brainiac/plugins/github/app_client.rb', line 99

def reset!
  @mutex.synchronize do
    @tokens = {}
  end
end