resolveGitReference takes a user-provided ref and sha and resolves them into a definitive commit SHA and its corresponding fully-qualified reference. The resolution logic follows a clear priority: 1. If a specific commit `sha` is provided, it takes precedence and is used directly, and all referenc
(ctx context.Context, githubClient *github.Client, owner, repo, ref, sha string)
| 205 | // Any unexpected (non-404) errors during the resolution process are returned |
| 206 | // immediately. All API errors are logged with rich context to aid diagnostics. |
| 207 | func resolveGitReference(ctx context.Context, githubClient *github.Client, owner, repo, ref, sha string) (*raw.ContentOpts, bool, error) { |
| 208 | // 1) If SHA explicitly provided, it's the highest priority. |
| 209 | if sha != "" { |
| 210 | return &raw.ContentOpts{Ref: "", SHA: sha}, false, nil |
| 211 | } |
| 212 | |
| 213 | // 1a) If sha is empty but ref looks like a SHA, return it without changes |
| 214 | if looksLikeSHA(ref) { |
| 215 | return &raw.ContentOpts{Ref: "", SHA: ref}, false, nil |
| 216 | } |
| 217 | |
| 218 | originalRef := ref // Keep original ref for clearer error messages down the line. |
| 219 | |
| 220 | // 2) If no SHA is provided, we try to resolve the ref into a fully-qualified format. |
| 221 | var reference *github.Reference |
| 222 | var resp *github.Response |
| 223 | var err error |
| 224 | var fallbackUsed bool |
| 225 | |
| 226 | switch { |
| 227 | case originalRef == "": |
| 228 | // 2a) If ref is empty, determine the default branch. |
| 229 | reference, err = resolveDefaultBranch(ctx, githubClient, owner, repo) |
| 230 | if err != nil { |
| 231 | return nil, false, err // Error is already wrapped in resolveDefaultBranch. |
| 232 | } |
| 233 | ref = reference.GetRef() |
| 234 | case strings.HasPrefix(originalRef, "refs/"): |
| 235 | // 2b) Already fully qualified. The reference will be fetched at the end. |
| 236 | case strings.HasPrefix(originalRef, "heads/") || strings.HasPrefix(originalRef, "tags/"): |
| 237 | // 2c) Partially qualified. Make it fully qualified. |
| 238 | ref = "refs/" + originalRef |
| 239 | default: |
| 240 | // 2d) It's a short name, so we try to resolve it to either a branch or a tag. |
| 241 | branchRef := "refs/heads/" + originalRef |
| 242 | reference, resp, err = githubClient.Git.GetRef(ctx, owner, repo, branchRef) |
| 243 | |
| 244 | if err == nil { |
| 245 | ref = branchRef // It's a branch. |
| 246 | } else { |
| 247 | // The branch lookup failed. Check if it was a 404 Not Found error. |
| 248 | ghErr, isGhErr := err.(*github.ErrorResponse) |
| 249 | if isGhErr && ghErr.Response.StatusCode == http.StatusNotFound { |
| 250 | tagRef := "refs/tags/" + originalRef |
| 251 | reference, resp, err = githubClient.Git.GetRef(ctx, owner, repo, tagRef) |
| 252 | if err == nil { |
| 253 | ref = tagRef // It's a tag. |
| 254 | } else { |
| 255 | // The tag lookup also failed. Check if it was a 404 Not Found error. |
| 256 | ghErr2, isGhErr2 := err.(*github.ErrorResponse) |
| 257 | if isGhErr2 && ghErr2.Response.StatusCode == http.StatusNotFound { |
| 258 | if originalRef == "main" { |
| 259 | reference, err = resolveDefaultBranch(ctx, githubClient, owner, repo) |
| 260 | if err != nil { |
| 261 | return nil, false, err // Error is already wrapped in resolveDefaultBranch. |
| 262 | } |
| 263 | // Update ref to the actual default branch ref so the note can be generated |
| 264 | ref = reference.GetRef() |