Skip to content

Commit 0868841

Browse files
authored
Merge pull request #4 from versioner-io/more_annotations
More annotations
2 parents 72a6fe5 + ab0562f commit 0868841

3 files changed

Lines changed: 127 additions & 0 deletions

File tree

internal/cmd/track_build.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/spf13/viper"
1010
"github.com/versioner-io/versioner-cli/internal/api"
1111
"github.com/versioner-io/versioner-cli/internal/cicd"
12+
"github.com/versioner-io/versioner-cli/internal/github"
1213
"github.com/versioner-io/versioner-cli/internal/status"
1314
)
1415

@@ -207,10 +208,12 @@ func runBuildTrack(cmd *cobra.Command, args []string) error {
207208
if err != nil {
208209
if apiErr, ok := err.(*api.APIError); ok {
209210
// API error - exit code 2
211+
github.WriteGenericErrorAnnotation("Build", "API Error", apiErr.Error())
210212
fmt.Fprintf(os.Stderr, "API error: %s\n", apiErr.Error())
211213
os.Exit(2)
212214
}
213215
// Network or other error - exit code 2
216+
github.WriteGenericErrorAnnotation("Build", "Network Error", err.Error())
214217
fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
215218
os.Exit(2)
216219
}
@@ -223,5 +226,8 @@ func runBuildTrack(cmd *cobra.Command, args []string) error {
223226
fmt.Printf(" Version ID: %s\n", resp.VersionID)
224227
}
225228

229+
// Write GitHub Actions job summary
230+
github.WriteSuccessSummary("Build", product, statusValue, version, event.SCMSha, event.BuildURL)
231+
226232
return nil
227233
}

internal/cmd/track_deployment.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,12 @@ func runDeploymentTrack(cmd *cobra.Command, args []string) error {
241241
os.Exit(5) // Exit code 5 for preflight failures
242242
}
243243
// Other API error - exit code 4
244+
github.WriteGenericErrorAnnotation("Deployment", "API Error", apiErr.Error())
244245
fmt.Fprintf(os.Stderr, "API error: %s\n", apiErr.Error())
245246
os.Exit(4)
246247
}
247248
// Network or other error - exit code 1
249+
github.WriteGenericErrorAnnotation("Deployment", "Network Error", err.Error())
248250
fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
249251
os.Exit(1)
250252
}
@@ -258,6 +260,9 @@ func runDeploymentTrack(cmd *cobra.Command, args []string) error {
258260
fmt.Printf(" Environment ID: %s\n", resp.EnvironmentID)
259261
}
260262

263+
// Write GitHub Actions job summary
264+
github.WriteSuccessSummary("Deployment", environment, statusValue, version, event.SCMSha, event.DeployURL)
265+
261266
return nil
262267
}
263268

internal/github/annotations.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,122 @@ func WriteErrorAnnotation(statusCode int, errorCode, message, ruleName string, r
2121
writeJobSummary(statusCode, errorCode, message, ruleName, retryAfter, details)
2222
}
2323

24+
// WriteSuccessSummary writes a GitHub Actions job summary for successful deployment tracking
25+
func WriteSuccessSummary(action, environment, status, version, scmSha, deployURL string) {
26+
// Only write summaries if running in GitHub Actions
27+
if os.Getenv("GITHUB_ACTIONS") != "true" {
28+
return
29+
}
30+
31+
summaryPath := os.Getenv("GITHUB_STEP_SUMMARY")
32+
if summaryPath == "" {
33+
return
34+
}
35+
36+
// Build the summary
37+
var summary string
38+
summary += "## 🚀 Versioner Summary\n\n"
39+
40+
// Add key information
41+
summary += fmt.Sprintf("- **Action:** %s\n", action)
42+
summary += fmt.Sprintf("- **Environment:** %s\n", environment)
43+
summary += fmt.Sprintf("- **Status:** %s\n", formatStatus(status))
44+
summary += fmt.Sprintf("- **Version:** `%s`\n", version)
45+
46+
if scmSha != "" {
47+
summary += fmt.Sprintf("- **Git SHA:** `%s`\n", scmSha)
48+
}
49+
50+
if deployURL != "" {
51+
summary += fmt.Sprintf("\n[View Deployment Run →](%s)\n", deployURL)
52+
}
53+
54+
// Write to file
55+
f, err := os.OpenFile(summaryPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
56+
if err != nil {
57+
// Silently fail - don't break the CLI if we can't write the summary
58+
return
59+
}
60+
defer f.Close()
61+
62+
_, _ = f.WriteString(summary)
63+
}
64+
65+
// WriteGenericErrorAnnotation writes a GitHub Actions error annotation for generic failures
66+
// (API errors, network errors, etc.)
67+
func WriteGenericErrorAnnotation(action, errorType, errorMessage string) {
68+
// Only write annotations if running in GitHub Actions
69+
if os.Getenv("GITHUB_ACTIONS") != "true" {
70+
return
71+
}
72+
73+
summaryPath := os.Getenv("GITHUB_STEP_SUMMARY")
74+
if summaryPath == "" {
75+
return
76+
}
77+
78+
// Write workflow command annotation
79+
title := fmt.Sprintf("Versioner %s Failed", action)
80+
escapedMessage := escapeWorkflowCommand(errorMessage)
81+
fmt.Fprintf(os.Stdout, "::error title=%s::%s\n", title, escapedMessage)
82+
83+
// Build the summary
84+
var summary string
85+
summary += fmt.Sprintf("## ❌ Versioner %s Failed\n\n", action)
86+
summary += fmt.Sprintf("### %s\n\n", errorType)
87+
summary += fmt.Sprintf("**Error:** %s\n\n", errorMessage)
88+
89+
summary += "**Possible Causes:**\n"
90+
switch errorType {
91+
case "API Error":
92+
summary += "- Invalid API key or authentication failure\n"
93+
summary += "- Validation error (check required fields)\n"
94+
summary += "- API service unavailable\n"
95+
summary += "- Rate limiting or quota exceeded\n"
96+
case "Network Error":
97+
summary += "- Network connectivity issues\n"
98+
summary += "- DNS resolution failure\n"
99+
summary += "- API endpoint unreachable\n"
100+
summary += "- Timeout or connection refused\n"
101+
default:
102+
summary += "- Check error message above for details\n"
103+
}
104+
105+
summary += "\n**Action Required:**\n"
106+
summary += "- Verify your `VERSIONER_API_KEY` is set correctly\n"
107+
summary += "- Check network connectivity to Versioner API\n"
108+
summary += "- Review error message for specific guidance\n"
109+
summary += "- Contact support if issue persists\n"
110+
111+
// Write to file
112+
f, err := os.OpenFile(summaryPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
113+
if err != nil {
114+
// Silently fail - don't break the CLI if we can't write the summary
115+
return
116+
}
117+
defer f.Close()
118+
119+
_, _ = f.WriteString(summary)
120+
}
121+
122+
// formatStatus adds an emoji to the status for visual clarity
123+
func formatStatus(status string) string {
124+
switch status {
125+
case "started", "in_progress":
126+
return "⏳ " + status
127+
case "completed", "success":
128+
return "✅ " + status
129+
case "failed":
130+
return "❌ " + status
131+
case "aborted", "cancelled":
132+
return "🚫 " + status
133+
case "pending":
134+
return "⏸️ " + status
135+
default:
136+
return status
137+
}
138+
}
139+
24140
// writeWorkflowCommand outputs a GitHub Actions workflow command for error annotation
25141
func writeWorkflowCommand(statusCode int, errorCode, message, ruleName string) {
26142
// Format: ::error title=<title>::<message>

0 commit comments

Comments
 (0)