brainiac-github 0.2.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: df22ea85b48c5fd4960ad4e8bb28c3e59f551839c2cbc900dc065edc74039ed3
|
|
4
|
+
data.tar.gz: d8708dd8352a97e01bac35eb65ddb13ab7aea6249876987d4e73fd89328f97ee
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 241be88652dfaf39203b734d212d6b91e641017a3344cd4c8cabdad2332e1262f8e848e12680ca0612d43c9e44db6c124c9d1e6e76aecc5c625a4f30b8cff499
|
|
7
|
+
data.tar.gz: 5096d8be04c2c469770b93e5c998502cd545cb78553f64ec40e621d84f8d03c0d5e3ec9263c77237db1bc92cdb7396cb2ddff4b626be6230ca279b3f91676a14
|
|
@@ -61,15 +61,19 @@ module Brainiac
|
|
|
61
61
|
post("/repos/#{repo}/issues/comments/#{comment_id}/reactions", { content: reaction }, agent_key: agent_key)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
# POST a reaction on a PR
|
|
64
|
+
# POST a reaction on a PR (or issue) itself.
|
|
65
|
+
#
|
|
66
|
+
# GitHub's reactions API has NO endpoint for PR reviews — only for
|
|
67
|
+
# issue comments, PR review comments, issues, and PRs. Since a PR is
|
|
68
|
+
# an issue under the hood, PR reactions go through the issues path.
|
|
65
69
|
#
|
|
66
70
|
# @param repo [String] "owner/repo"
|
|
67
|
-
# @param
|
|
68
|
-
# @param reaction [String]
|
|
71
|
+
# @param pr_number [Integer]
|
|
72
|
+
# @param reaction [String] e.g. "eyes", "+1", "rocket"
|
|
69
73
|
# @param agent_key [String, nil] agent key for per-agent app identity
|
|
70
74
|
# @return [Hash] parsed response
|
|
71
|
-
def
|
|
72
|
-
post("/repos/#{repo}/
|
|
75
|
+
def create_pr_reaction(repo, pr_number, reaction, agent_key: nil)
|
|
76
|
+
post("/repos/#{repo}/issues/#{pr_number}/reactions", { content: reaction }, agent_key: agent_key)
|
|
73
77
|
end
|
|
74
78
|
|
|
75
79
|
# GET request to GitHub API.
|
|
@@ -105,11 +105,21 @@ module Brainiac
|
|
|
105
105
|
|
|
106
106
|
return [200, { status: "ignored", reason: "no worktree" }.to_json] unless worktree && File.directory?(worktree)
|
|
107
107
|
|
|
108
|
+
# Pull latest changes into worktree
|
|
109
|
+
system("git", "pull", "--ff-only", chdir: worktree)
|
|
110
|
+
|
|
111
|
+
# Try to redeploy to ephemeral Belt environment if one exists
|
|
112
|
+
ephemeral_redeployed = maybe_redeploy_ephemeral_belt_env(
|
|
113
|
+
card_info: card_info, card_number: card_number, worktree: worktree,
|
|
114
|
+
base_branch: pr.dig("base", "ref")
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Also emit the hook for other plugins (e.g., brainiac-fizzy persistent env redeploy)
|
|
108
118
|
results = Brainiac.emit(:pr_synchronized, card_number: card_number, card_info: card_info,
|
|
109
119
|
worktree: worktree, pull_request: pr, branch: branch)
|
|
110
120
|
|
|
111
|
-
if results.any?
|
|
112
|
-
[200, { status: "processed", action: "pr_sync", card: card_number }.to_json]
|
|
121
|
+
if ephemeral_redeployed || results.any?
|
|
122
|
+
[200, { status: "processed", action: "pr_sync", card: card_number, ephemeral_redeployed: ephemeral_redeployed }.to_json]
|
|
113
123
|
else
|
|
114
124
|
[200, { status: "ignored", reason: "no deployment plugin" }.to_json]
|
|
115
125
|
end
|
|
@@ -648,6 +658,12 @@ module Brainiac
|
|
|
648
658
|
|
|
649
659
|
def process_merged_pr(card_info, card_number, branch, pull_request, pr_url, pr_title, project_key, project_config, repo_path)
|
|
650
660
|
mark_work_item_merged(card_number)
|
|
661
|
+
|
|
662
|
+
# Destroy ephemeral Belt environment BEFORE worktree cleanup (infrastructure lives in worktree)
|
|
663
|
+
maybe_destroy_ephemeral_belt_env(
|
|
664
|
+
card_info: card_info, card_number: card_number, project_key: project_key
|
|
665
|
+
)
|
|
666
|
+
|
|
651
667
|
cleanup_work_item_worktrees(card_number, repo_path: repo_path,
|
|
652
668
|
primary_worktree: card_info["worktree"], primary_branch: branch)
|
|
653
669
|
|
|
@@ -730,10 +746,12 @@ module Brainiac
|
|
|
730
746
|
agent_name = resolve_work_item_agent(card_info, project_config)
|
|
731
747
|
|
|
732
748
|
Thread.new do
|
|
749
|
+
# GitHub has no reactions endpoint for PR reviews, so react on the
|
|
750
|
+
# PR itself (PRs are issues under the hood) to signal "on it".
|
|
733
751
|
if AppClient.configured?(agent_name)
|
|
734
|
-
AppClient.
|
|
752
|
+
AppClient.create_pr_reaction(repo_name, pr_number, "eyes", agent_key: agent_name)
|
|
735
753
|
else
|
|
736
|
-
run_cmd("gh", "api", "-X", "POST", "/repos/#{repo_name}/
|
|
754
|
+
run_cmd("gh", "api", "-X", "POST", "/repos/#{repo_name}/issues/#{pr_number}/reactions",
|
|
737
755
|
"-f", "content=eyes", "-H", "Accept: application/vnd.github+json", chdir: repo_path)
|
|
738
756
|
end
|
|
739
757
|
|
|
@@ -862,6 +880,71 @@ module Brainiac
|
|
|
862
880
|
|
|
863
881
|
[200, { status: "processed", action: "prod_deploy", closed_cards: closed_cards.map { |c| c[:number] }, project: project_key }.to_json]
|
|
864
882
|
end
|
|
883
|
+
|
|
884
|
+
# Destroy ephemeral Belt environment on PR merge.
|
|
885
|
+
# Must be called BEFORE worktree cleanup since infrastructure lives in the worktree.
|
|
886
|
+
def maybe_destroy_ephemeral_belt_env(card_info:, card_number:, project_key:)
|
|
887
|
+
unless defined?(BeltConfig) && defined?(BeltEnvironment)
|
|
888
|
+
LOG.debug "[EphemeralEnv] Belt utilities not available — skipping env destruction"
|
|
889
|
+
return
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
env_name = BeltConfig.ephemeral_env_for_card(card_number)
|
|
893
|
+
worktree = card_info&.dig("worktree")
|
|
894
|
+
|
|
895
|
+
unless ephemeral_env_present?(worktree: worktree, env_name: env_name)
|
|
896
|
+
LOG.debug "[EphemeralEnv] No ephemeral env '#{env_name}' found for card ##{card_number}"
|
|
897
|
+
return
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
unless worktree && File.directory?(worktree)
|
|
901
|
+
LOG.warn "[EphemeralEnv] Cannot destroy '#{env_name}' — worktree not found"
|
|
902
|
+
return
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
LOG.info "[EphemeralEnv] Destroying ephemeral environment '#{env_name}' for card ##{card_number}"
|
|
906
|
+
BeltEnvironment.destroy_environment(worktree: worktree, env_name: env_name)
|
|
907
|
+
rescue StandardError => e
|
|
908
|
+
LOG.error "[EphemeralEnv] Error destroying ephemeral env: #{e.message}"
|
|
909
|
+
end
|
|
910
|
+
|
|
911
|
+
# Redeploy to ephemeral Belt environment on PR sync (new commits pushed).
|
|
912
|
+
# Only redeploys if an ephemeral env already exists for this card.
|
|
913
|
+
def maybe_redeploy_ephemeral_belt_env(card_info:, card_number:, worktree:, base_branch: nil)
|
|
914
|
+
return false unless defined?(BeltConfig) && defined?(BeltEnvironment)
|
|
915
|
+
return false unless belt_app_worktree?(worktree)
|
|
916
|
+
|
|
917
|
+
env_name = BeltConfig.ephemeral_env_for_card(card_number)
|
|
918
|
+
|
|
919
|
+
unless ephemeral_env_present?(worktree: worktree, env_name: env_name)
|
|
920
|
+
LOG.debug "[EphemeralEnv] No ephemeral env '#{env_name}' for card ##{card_number} — skipping redeploy"
|
|
921
|
+
return false
|
|
922
|
+
end
|
|
923
|
+
|
|
924
|
+
LOG.info "[EphemeralEnv] Redeploying to ephemeral environment '#{env_name}' (PR sync)"
|
|
925
|
+
|
|
926
|
+
frontend_only = BeltEnvironment.frontend_only_changes?(worktree: worktree, base_branch: base_branch)
|
|
927
|
+
BeltEnvironment.deploy(worktree: worktree, env_name: env_name, frontend_only: frontend_only)
|
|
928
|
+
true
|
|
929
|
+
rescue StandardError => e
|
|
930
|
+
LOG.error "[EphemeralEnv] Error redeploying ephemeral env: #{e.message}"
|
|
931
|
+
false
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
# belt_app? lives on BeltEnvironment (via BeltHelpers), not on this Handler module.
|
|
935
|
+
def belt_app_worktree?(worktree)
|
|
936
|
+
BeltEnvironment.respond_to?(:belt_app?) && BeltEnvironment.belt_app?(worktree)
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
# Worktree infrastructure/<env>/ is the source of truth; tracking JSON is a fallback.
|
|
940
|
+
def ephemeral_env_present?(worktree:, env_name:)
|
|
941
|
+
if BeltEnvironment.respond_to?(:environment_configured?) &&
|
|
942
|
+
BeltEnvironment.environment_configured?(worktree: worktree, env_name: env_name)
|
|
943
|
+
return true
|
|
944
|
+
end
|
|
945
|
+
|
|
946
|
+
BeltConfig.ephemeral_env?(env_name)
|
|
947
|
+
end
|
|
865
948
|
end
|
|
866
949
|
end
|
|
867
950
|
end
|
|
@@ -14,6 +14,19 @@ module Brainiac
|
|
|
14
14
|
- ``` ```language ``` for code blocks
|
|
15
15
|
- `- item` for lists
|
|
16
16
|
|
|
17
|
+
### @Mentions (STRICT — read carefully)
|
|
18
|
+
On GitHub, an `@name` only works if it maps to a real GitHub account.
|
|
19
|
+
The other agents (Galen, GLaDOS, Threepio, etc.) are NOT GitHub users —
|
|
20
|
+
`@threepio` just pings some unrelated stranger who happens to own that
|
|
21
|
+
username. That's noisy and rude.
|
|
22
|
+
|
|
23
|
+
Rules for GitHub comments:
|
|
24
|
+
- The ONLY people you may @mention are **@ardavis** (Andy) and **@fladamd** (Adam).
|
|
25
|
+
- NEVER @mention any other agent or person. Refer to other agents by
|
|
26
|
+
plain name instead — write `Threepio` or `GLaDOS`, not `@threepio`.
|
|
27
|
+
- If you're unsure whether a name is a real GitHub account, don't @mention it.
|
|
28
|
+
Drop the `@` and use the plain name.
|
|
29
|
+
|
|
17
30
|
### Scope
|
|
18
31
|
You are responding to activity on a GitHub PR. Focus on the code changes and review feedback.
|
|
19
32
|
When posting comments, post on the PR unless specifically asked to update the card.
|