Skip to content

Commit d46bf71

Browse files
committed
fix: resolve build errors on github-deployment-status branch
1 parent ad17c13 commit d46bf71

File tree

3 files changed

+46
-75
lines changed

3 files changed

+46
-75
lines changed

svc/ctrl/worker/deploy/status_reporter_pr_comment.go

Lines changed: 42 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package deploy
22

33
import (
44
"fmt"
5-
"regexp"
65
"strings"
76
"time"
87

@@ -20,13 +19,15 @@ const (
2019
prCommentRowMarkerFmt = "<!-- row:%s:%s -->"
2120
)
2221

23-
// rowPattern matches a full table row line that starts with a row marker.
24-
var rowPattern = regexp.MustCompile(`(?m)^\| <!-- row:\S+ --> .+\|$`)
22+
// findResult bundles the comment ID and body for restate.Run serialisation.
23+
type findResult struct {
24+
ID int64
25+
Body string
26+
}
2527

2628
// prCommentReporter creates and updates a shared PR comment with one row per
27-
// deployment, similar to the Vercel deployment comment. Multiple deploy
28-
// workflows running concurrently for the same PR each manage their own row.
29-
// All GitHub API calls are fire-and-forget.
29+
// app/env combination. Multiple deploy workflows for the same PR each manage
30+
// their own row. All GitHub API calls are fire-and-forget.
3031
type prCommentReporter struct {
3132
github githubclient.GitHubClient
3233
installationID int64
@@ -40,8 +41,8 @@ type prCommentReporter struct {
4041
logURL string
4142
environmentURL string
4243

43-
prNumber int // resolved lazily
44-
commentID int64 // set after Create
44+
prNumber int
45+
commentID int64
4546
}
4647

4748
type prCommentReporterConfig struct {
@@ -74,8 +75,6 @@ func newPRCommentReporter(cfg prCommentReporterConfig) *prCommentReporter {
7475
}
7576
}
7677

77-
// Create looks up the PR, finds or creates the shared comment, and adds this
78-
// deployment's row.
7978
func (r *prCommentReporter) Create(ctx restate.ObjectSharedContext) {
8079
if r.installationID == 0 || r.repo == "" || r.branch == "" {
8180
return
@@ -92,99 +91,79 @@ func (r *prCommentReporter) Create(ctx restate.ObjectSharedContext) {
9291
}
9392
r.prNumber = prNumber
9493

95-
// Look for an existing deployment comment on this PR.
9694
existing, err := restate.Run(ctx, func(_ restate.RunContext) (findResult, error) {
97-
id, body, err := r.github.FindBotComment(r.installationID, r.repo, r.prNumber, prCommentMainMarker)
98-
return findResult{ID: id, Body: body}, err
95+
id, body, findErr := r.github.FindBotComment(r.installationID, r.repo, r.prNumber, prCommentMainMarker)
96+
return findResult{ID: id, Body: body}, findErr
9997
}, restate.WithName("find existing deploy comment"), restate.WithMaxRetryDuration(30*time.Second))
10098
if err != nil {
10199
logger.Error("failed to search for existing deploy comment", "error", err)
102100
}
103101

104-
row := r.buildRow("Queued")
102+
row := r.buildRow("Queued")
105103

106104
if existing.ID != 0 {
107-
// Add or replace our row in the existing comment.
108105
r.commentID = existing.ID
109106
body := r.upsertRow(existing.Body, row)
110-
111107
_ = restate.RunVoid(ctx, func(_ restate.RunContext) error {
112108
return r.github.UpdateIssueComment(r.installationID, r.repo, r.commentID, body)
113-
}, restate.WithName("add row to existing deploy comment"), restate.WithMaxRetryDuration(30*time.Second))
109+
}, restate.WithName("add row to deploy comment"), restate.WithMaxRetryDuration(30*time.Second))
114110
return
115111
}
116112

117-
// No existing comment — create one.
118113
body := r.buildFullComment(row)
119-
commentID, err := restate.Run(ctx, func(_ restate.RunContext) (int64, error) {
114+
commentID, createErr := restate.Run(ctx, func(_ restate.RunContext) (int64, error) {
120115
return r.github.CreateIssueComment(r.installationID, r.repo, r.prNumber, body)
121-
}, restate.WithName("create PR deployment comment"), restate.WithMaxRetryDuration(30*time.Second))
122-
if err != nil {
123-
logger.Error("failed to create PR comment", "error", err, "pr", r.prNumber)
116+
}, restate.WithName("create deploy comment"), restate.WithMaxRetryDuration(30*time.Second))
117+
if createErr != nil {
118+
logger.Error("failed to create PR comment", "error", createErr, "pr", r.prNumber)
124119
return
125120
}
126121
r.commentID = commentID
127122
}
128123

129-
// findResult is a helper to return both ID and Body from restate.Run.
130-
type findResult struct {
131-
ID int64
132-
Body string
133-
}
134-
135-
// Report updates this deployment's row in the shared PR comment.
136124
func (r *prCommentReporter) Report(ctx restate.ObjectSharedContext, state string, description string) {
137125
if r.commentID == 0 {
138126
return
139127
}
140128

141-
statusEmoji, statusLabel := r.stateToDisplay(state)
142-
row := r.buildRow(statusEmoji + " " + statusLabel)
129+
row := r.buildRow(stateLabel(state))
143130

144-
// Re-read current comment body so we don't clobber other deployments' rows.
131+
// Re-read current body so we don't clobber other apps' rows.
145132
current, err := restate.Run(ctx, func(_ restate.RunContext) (findResult, error) {
146-
id, body, err := r.github.FindBotComment(r.installationID, r.repo, r.prNumber, prCommentMainMarker)
147-
return findResult{ID: id, Body: body}, err
148-
}, restate.WithName("read deploy comment for update"), restate.WithMaxRetryDuration(30*time.Second))
133+
id, body, findErr := r.github.FindBotComment(r.installationID, r.repo, r.prNumber, prCommentMainMarker)
134+
return findResult{ID: id, Body: body}, findErr
135+
}, restate.WithName("read deploy comment"), restate.WithMaxRetryDuration(30*time.Second))
149136
if err != nil || current.ID == 0 {
150137
return
151138
}
152139

153140
body := r.upsertRow(current.Body, row)
154-
155141
_ = restate.RunVoid(ctx, func(_ restate.RunContext) error {
156142
return r.github.UpdateIssueComment(r.installationID, r.repo, r.commentID, body)
157-
}, restate.WithName(fmt.Sprintf("update PR comment row: %s", state)), restate.WithMaxRetryDuration(30*time.Second))
143+
}, restate.WithName(fmt.Sprintf("update deploy comment: %s", state)), restate.WithMaxRetryDuration(30*time.Second))
158144
}
159145

160-
// rowMarker returns the unique key for this app/env combination.
161146
func (r *prCommentReporter) rowMarker() string {
162147
return fmt.Sprintf(prCommentRowMarkerFmt, r.appSlug, r.envSlug)
163148
}
164149

165-
// buildRow produces a single markdown table row with this deployment's info.
166150
func (r *prCommentReporter) buildRow(status string) string {
167-
rowMarker := r.rowMarker()
168-
169151
nameLabel := r.projectSlug
170152
if r.appSlug != "default" {
171153
nameLabel += " / " + r.appSlug
172154
}
173155

174-
now := time.Now().UTC().Format("Jan 2, 2006 3:04pm")
175-
176156
preview := "—"
177157
if r.environmentURL != "" {
178158
preview = fmt.Sprintf("[Visit Preview](%s)", r.environmentURL)
179159
}
180160

181-
inspect := fmt.Sprintf("[Inspect](%s)", r.logURL)
182-
183-
return fmt.Sprintf("| %s **%s** (%s) | %s | %s | %s | %s |",
184-
rowMarker, nameLabel, r.envSlug, status, preview, inspect, now)
161+
return fmt.Sprintf("| %s **%s** (%s) | %s | %s | [Inspect](%s) | %s |",
162+
r.rowMarker(), nameLabel, r.envSlug, status,
163+
preview, r.logURL,
164+
time.Now().UTC().Format("Jan 2, 2006 3:04pm"))
185165
}
186166

187-
// buildFullComment wraps the header, table, and a single row into a new comment.
188167
func (r *prCommentReporter) buildFullComment(firstRow string) string {
189168
var b strings.Builder
190169
b.WriteString(prCommentMainMarker)
@@ -198,55 +177,48 @@ func (r *prCommentReporter) buildFullComment(firstRow string) string {
198177
}
199178

200179
// upsertRow replaces an existing row for this app/env or appends a new one.
201-
func (r *prCommentReporter) upsertRow(existingBody string, newRow string) string {
202-
rowMarker := r.rowMarker()
180+
func (r *prCommentReporter) upsertRow(body string, newRow string) string {
181+
marker := r.rowMarker()
182+
lines := strings.Split(body, "\n")
203183

204-
if strings.Contains(existingBody, rowMarker) {
205-
// Replace the existing row (the whole line containing our marker).
206-
lines := strings.Split(existingBody, "\n")
184+
if strings.Contains(body, marker) {
207185
for i, line := range lines {
208-
if strings.Contains(line, rowMarker) {
186+
if strings.Contains(line, marker) {
209187
lines[i] = newRow
210-
break
188+
return strings.Join(lines, "\n")
211189
}
212190
}
213-
return strings.Join(lines, "\n")
214191
}
215192

216-
// Append new row after the last table row.
217-
// Find the last line that starts with "| " (table row).
218-
lines := strings.Split(existingBody, "\n")
193+
// Append after the last table row (any line starting with "|" that isn't the separator).
219194
lastRowIdx := -1
220195
for i, line := range lines {
221-
if strings.HasPrefix(line, "|") && !strings.Contains(line, ":--") && i > 0 {
196+
if i > 0 && strings.HasPrefix(line, "|") && !strings.Contains(line, ":--") {
222197
lastRowIdx = i
223198
}
224199
}
225-
226200
if lastRowIdx >= 0 {
227-
// Insert after the last row.
228201
result := make([]string, 0, len(lines)+1)
229202
result = append(result, lines[:lastRowIdx+1]...)
230203
result = append(result, newRow)
231204
result = append(result, lines[lastRowIdx+1:]...)
232205
return strings.Join(result, "\n")
233206
}
234207

235-
// Fallback: just append.
236-
return existingBody + newRow + "\n"
208+
return body + newRow + "\n"
237209
}
238210

239-
func (r *prCommentReporter) stateToDisplay(state string) (string, string) {
211+
func stateLabel(state string) string {
240212
switch state {
241213
case "pending":
242-
return "⏳", "Queued"
214+
return "Queued"
243215
case "in_progress":
244-
return "🔨", "Building"
216+
return "Building"
245217
case "success":
246-
return "✅", "Ready"
218+
return "Ready"
247219
case "failure", "error":
248-
return "❌", "Failed"
220+
return "Failed"
249221
default:
250-
return "⏳", "In Progress"
222+
return "In Progress"
251223
}
252224
}

svc/ctrl/worker/github/client.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ func (c *Client) FindPullRequestForBranch(installationID int64, repo string, bra
372372
apiURL := fmt.Sprintf("https://api.github.com/repos/%s/pulls?state=open&head=%s:%s&per_page=1",
373373
repo, strings.Split(repo, "/")[0], url.PathEscape(branch))
374374

375-
prs, err := httpclient.Request[[]ghPullRequest](c.httpClient, http.MethodGet, apiURL, headers, nil, http.StatusOK)
375+
prs, err := request[[]ghPullRequest](c.httpClient, http.MethodGet, apiURL, headers, nil, http.StatusOK)
376376
if err != nil {
377377
return 0, err
378378
}
@@ -392,7 +392,7 @@ func (c *Client) CreateIssueComment(installationID int64, repo string, prNumber
392392

393393
apiURL := fmt.Sprintf("https://api.github.com/repos/%s/issues/%d/comments", repo, prNumber)
394394

395-
comment, err := httpclient.Request[ghIssueComment](c.httpClient, http.MethodPost, apiURL, headers, map[string]string{
395+
comment, err := request[ghIssueComment](c.httpClient, http.MethodPost, apiURL, headers, map[string]string{
396396
"body": body,
397397
}, http.StatusCreated)
398398
if err != nil {
@@ -410,7 +410,7 @@ func (c *Client) UpdateIssueComment(installationID int64, repo string, commentID
410410

411411
apiURL := fmt.Sprintf("https://api.github.com/repos/%s/issues/comments/%d", repo, commentID)
412412

413-
return httpclient.Do(c.httpClient, http.MethodPatch, apiURL, headers, map[string]string{
413+
return doRequest(c.httpClient, http.MethodPatch, apiURL, headers, map[string]string{
414414
"body": body,
415415
}, http.StatusOK)
416416
}
@@ -431,7 +431,7 @@ func (c *Client) FindBotComment(installationID int64, repo string, prNumber int,
431431
Body string `json:"body"`
432432
}
433433

434-
comments, err := httpclient.Request[[]ghCommentWithBody](c.httpClient, http.MethodGet, apiURL, headers, nil, http.StatusOK)
434+
comments, err := request[[]ghCommentWithBody](c.httpClient, http.MethodGet, apiURL, headers, nil, http.StatusOK)
435435
if err != nil {
436436
return 0, "", err
437437
}

svc/ctrl/worker/github/http.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ func statusCheck(client *http.Client, method string, url string, headers map[str
126126

127127
return resp.StatusCode == expectedStatus, nil
128128
}
129-
130129
// githubHeaders returns common GitHub API headers with the given bearer token.
131130
func githubHeaders(token string) map[string]string {
132131
h := map[string]string{

0 commit comments

Comments
 (0)