fetchCommitMeta fetches commit title, author, and changed file list for a single commit SHA. Uses: GET /repos/{owner}/{repo}/commits/{sha}
(ctx context.Context, repo, sha string)
| 238 | // fetchCommitMeta fetches commit title, author, and changed file list for a single commit SHA. |
| 239 | // Uses: GET /repos/{owner}/{repo}/commits/{sha} |
| 240 | func fetchCommitMeta(ctx context.Context, repo, sha string) (CommitMeta, error) { |
| 241 | ctxTimeout, cancel := context.WithTimeout(ctx, 30*time.Second) |
| 242 | defer cancel() |
| 243 | |
| 244 | cmd := exec.CommandContext(ctxTimeout, "gh", "api", |
| 245 | fmt.Sprintf("/repos/%s/commits/%s", repo, sha), |
| 246 | ) |
| 247 | |
| 248 | output, err := cmd.Output() |
| 249 | if err != nil { |
| 250 | if exitErr, ok := err.(*exec.ExitError); ok { |
| 251 | return CommitMeta{SHA: sha}, fmt.Errorf("gh api failed for commit %s: %w\nstderr: %s", sha, err, string(exitErr.Stderr)) |
| 252 | } |
| 253 | return CommitMeta{SHA: sha}, fmt.Errorf("failed to execute gh command for commit %s: %w", sha, err) |
| 254 | } |
| 255 | |
| 256 | var response struct { |
| 257 | SHA string `json:"sha"` |
| 258 | Commit struct { |
| 259 | Message string `json:"message"` |
| 260 | Author struct { |
| 261 | Name string `json:"name"` |
| 262 | Date time.Time `json:"date"` |
| 263 | } `json:"author"` |
| 264 | } `json:"commit"` |
| 265 | Files []struct { |
| 266 | Filename string `json:"filename"` |
| 267 | } `json:"files"` |
| 268 | } |
| 269 | |
| 270 | if err := json.Unmarshal(output, &response); err != nil { |
| 271 | return CommitMeta{SHA: sha}, fmt.Errorf("failed to parse commit response for %s: %w", sha, err) |
| 272 | } |
| 273 | |
| 274 | // Extract just the first line of the commit message as the title |
| 275 | title := response.Commit.Message |
| 276 | if idx := strings.IndexByte(title, '\n'); idx >= 0 { |
| 277 | title = title[:idx] |
| 278 | } |
| 279 | |
| 280 | files := make([]string, 0, len(response.Files)) |
| 281 | for _, f := range response.Files { |
| 282 | files = append(files, f.Filename) |
| 283 | } |
| 284 | |
| 285 | return CommitMeta{ |
| 286 | SHA: sha, |
| 287 | Title: title, |
| 288 | Author: response.Commit.Author.Name, |
| 289 | CommittedAt: response.Commit.Author.Date, |
| 290 | Files: files, |
| 291 | }, nil |
| 292 | } |
no test coverage detected