Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita34b916

Browse files
committed
feat(core): add GitHub Actions pipeline monitoring
Add automatic monitoring of GitHub Actions after successful git push with real-time status notifications and timeout handling.
1 parent13b379f commita34b916

File tree

5 files changed

+212
-149
lines changed

5 files changed

+212
-149
lines changed

‎core/src/233/main/resources/META-INF/autodev-core.xml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@
333333
<projectListeners>
334334
<listenerclass="cc.unitmesh.devti.actions.rename.RenameLookupManagerListener"
335335
topic="com.intellij.codeInsight.lookup.LookupManagerListener"/>
336+
<listenerclass="cc.unitmesh.devti.observer.agent.PipelineStatusProcessor"
337+
topic="git4idea.push.GitPushListener"/>
336338
</projectListeners>
337339

338340
<extensionsdefaultExtensionNs="cc.unitmesh">

‎core/src/main/kotlin/cc/unitmesh/devti/AutoDevNotifications.kt‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ object AutoDevNotifications {
1010
returnNotificationGroupManager.getInstance().getNotificationGroup("AutoDev.notification.group")
1111
}
1212

13-
funnotify(project:Project,msg:String) {
14-
group()?.createNotification(msg,NotificationType.INFORMATION)?.notify(project)
13+
funnotify(project:Project,msg:String,type:NotificationType?) {
14+
if (type==null) {
15+
info(project, msg)
16+
}else {
17+
group()?.createNotification(msg, type)?.notify(project)
18+
}
1519
}
1620

1721
funerror(project:Project,msg:String) {

‎core/src/main/kotlin/cc/unitmesh/devti/observer/RemoteHookObserverFixed.kt‎

Lines changed: 0 additions & 144 deletions
This file was deleted.
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
packagecc.unitmesh.devti.observer.agent
2+
3+
importcc.unitmesh.devti.AutoDevNotifications
4+
importcc.unitmesh.devti.settings.devops.devopsPromptsSettings
5+
importcom.intellij.notification.NotificationType
6+
importcom.intellij.openapi.diagnostic.Logger
7+
importcom.intellij.openapi.project.Project
8+
importcom.intellij.util.concurrency.AppExecutorUtil
9+
importgit4idea.push.GitPushListener
10+
importgit4idea.push.GitPushRepoResult
11+
importgit4idea.repo.GitRepository
12+
importorg.kohsuke.github.*
13+
importjava.util.concurrent.ScheduledFuture
14+
importjava.util.concurrent.TimeUnit
15+
16+
classPipelineStatusProcessor(privatevalproject:Project) : AgentProcessor, GitPushListener {
17+
privateval log=Logger.getInstance(PipelineStatusProcessor::class.java)
18+
privatevar monitoringJob:ScheduledFuture<*>?=null
19+
privateval timeoutMinutes=30
20+
21+
overridefunonCompleted(repository:GitRepository,pushResult:GitPushRepoResult) {
22+
// 检查 push 是否成功
23+
if (pushResult.type!=GitPushRepoResult.Type.SUCCESS) {
24+
log.info("Push failed, skipping pipeline monitoring")
25+
return
26+
}
27+
28+
// 获取最新的 commit SHA
29+
val latestCommit= repository.currentRevision
30+
if (latestCommit==null) {
31+
log.warn("Could not determine latest commit SHA")
32+
return
33+
}
34+
35+
log.info("Push successful, starting pipeline monitoring for commit:$latestCommit")
36+
37+
// 获取远程仓库信息
38+
val remoteUrl= getGitHubRemoteUrl(repository)
39+
if (remoteUrl==null) {
40+
log.warn("No GitHub remote URL found")
41+
return
42+
}
43+
44+
// 开始监听流水线
45+
startMonitoring(repository, latestCommit, remoteUrl)
46+
}
47+
48+
overridefunprocess() {
49+
// AgentProcessor 接口要求的方法,这里可以为空
50+
}
51+
52+
privatefungetGitHubRemoteUrl(repository:GitRepository):String? {
53+
return repository.remotes.firstOrNull { remote->
54+
remote.urls.any { url->
55+
url.contains("github.com")
56+
}
57+
}?.urls?.firstOrNull { it.contains("github.com") }
58+
}
59+
60+
privatefunstartMonitoring(repository:GitRepository,commitSha:String,remoteUrl:String) {
61+
log.info("Starting pipeline monitoring for commit:$commitSha")
62+
63+
val startTime=System.currentTimeMillis()
64+
65+
monitoringJob=AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay({
66+
try {
67+
val elapsedMinutes= (System.currentTimeMillis()- startTime)/ (1000*60)
68+
69+
if (elapsedMinutes>= timeoutMinutes) {
70+
log.info("Pipeline monitoring timeout reached for commit:$commitSha")
71+
AutoDevNotifications.notify(
72+
project,
73+
"GitHub Action monitoring timeout (30 minutes) for commit:${commitSha.take(7)}",
74+
NotificationType.WARNING
75+
)
76+
stopMonitoring()
77+
return@scheduleWithFixedDelay
78+
}
79+
80+
val workflowRun= findWorkflowRunForCommit(remoteUrl, commitSha)
81+
if (workflowRun!=null) {
82+
val isComplete= checkWorkflowStatus(workflowRun, commitSha)
83+
if (isComplete) {
84+
stopMonitoring()
85+
}
86+
}
87+
}catch (e:Exception) {
88+
log.error("Error monitoring pipeline for commit:$commitSha", e)
89+
AutoDevNotifications.notify(
90+
project,
91+
"Error monitoring GitHub Action:${e.message}",
92+
NotificationType.ERROR
93+
)
94+
stopMonitoring()
95+
}
96+
},30,30,TimeUnit.SECONDS)// Check every 30 seconds
97+
}
98+
99+
privatefunfindWorkflowRunForCommit(remoteUrl:String,commitSha:String):GHWorkflowRun? {
100+
try {
101+
val github= createGitHubConnection()
102+
val ghRepository= getGitHubRepository(github, remoteUrl)?:returnnull
103+
104+
// 获取所有 workflows
105+
val workflows= ghRepository.listWorkflows().toList()
106+
107+
// 查找与指定 commit 相关的 workflow run
108+
for (workflowin workflows) {
109+
val runs= workflow.listRuns()
110+
.iterator()
111+
.asSequence()
112+
.take(10)// 限制检查最近的 10 个运行
113+
.find { it.headSha== commitSha }
114+
115+
if (runs!=null) {
116+
return runs
117+
}
118+
}
119+
120+
returnnull
121+
}catch (e:Exception) {
122+
log.error("Error finding workflow run for commit:$commitSha", e)
123+
returnnull
124+
}
125+
}
126+
127+
privatefuncheckWorkflowStatus(workflowRun:GHWorkflowRun,commitSha:String):Boolean {
128+
returnwhen (workflowRun.status) {
129+
GHWorkflowRun.Status.COMPLETED-> {
130+
when (workflowRun.conclusion) {
131+
GHWorkflowRun.Conclusion.SUCCESS-> {
132+
AutoDevNotifications.notify(
133+
project,
134+
"✅ GitHub Action completed successfully for commit:${commitSha.take(7)}",
135+
NotificationType.INFORMATION
136+
)
137+
true
138+
}
139+
GHWorkflowRun.Conclusion.FAILURE,
140+
GHWorkflowRun.Conclusion.CANCELLED,
141+
GHWorkflowRun.Conclusion.TIMED_OUT-> {
142+
AutoDevNotifications.notify(
143+
project,
144+
"❌ GitHub Action failed for commit:${commitSha.take(7)} -${workflowRun.conclusion}",
145+
NotificationType.ERROR
146+
)
147+
true
148+
}
149+
else-> {
150+
log.info("Workflow completed with conclusion:${workflowRun.conclusion}")
151+
false
152+
}
153+
}
154+
}
155+
GHWorkflowRun.Status.IN_PROGRESS,GHWorkflowRun.Status.QUEUED-> {
156+
log.info("Workflow still running:${workflowRun.status}")
157+
false
158+
}
159+
else-> {
160+
log.info("Unknown workflow status:${workflowRun.status}")
161+
false
162+
}
163+
}
164+
}
165+
166+
privatefuncreateGitHubConnection():GitHub {
167+
val token= project.devopsPromptsSettings?.githubToken
168+
returnif (token.isNullOrBlank()) {
169+
GitHub.connectAnonymously()
170+
}else {
171+
GitHub.connectUsingOAuth(token)
172+
}
173+
}
174+
175+
privatefungetGitHubRepository(github:GitHub,remoteUrl:String):GHRepository? {
176+
try {
177+
val repoPath= extractRepositoryPath(remoteUrl)?:returnnull
178+
return github.getRepository(repoPath)
179+
}catch (e:Exception) {
180+
log.error("Error getting GitHub repository from URL:$remoteUrl", e)
181+
returnnull
182+
}
183+
}
184+
185+
privatefunextractRepositoryPath(remoteUrl:String):String? {
186+
// Handle both HTTPS and SSH URLs
187+
val httpsPattern=Regex("https://github\\.com/([^/]+/[^/]+)(?:\\.git)?/?")
188+
val sshPattern=Regex("git@github\\.com:([^/]+/[^/]+)(?:\\.git)?/?")
189+
190+
return httpsPattern.find(remoteUrl)?.groupValues?.get(1)
191+
?: sshPattern.find(remoteUrl)?.groupValues?.get(1)
192+
}
193+
194+
privatefunstopMonitoring() {
195+
monitoringJob?.cancel(false)
196+
monitoringJob=null
197+
log.info("Pipeline monitoring stopped")
198+
}
199+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp