MCPcopy Create free account
hub / github.com/github/gh-aw / getRepositoryFeatures

Function getRepositoryFeatures

pkg/workflow/repository_features_validation.go:191–251  ·  view source on GitHub ↗

getRepositoryFeatures gets repository features with caching to amortize API calls

(repo string, verbose bool)

Source from the content-addressed store, hash-verified

189
190// getRepositoryFeatures gets repository features with caching to amortize API calls
191func getRepositoryFeatures(repo string, verbose bool) (*RepositoryFeatures, error) {
192 // Check cache first using sync.Map
193 if cached, exists := repositoryFeaturesCache.Load(repo); exists {
194 features, ok := cached.(*RepositoryFeatures)
195 if !ok {
196 repositoryFeaturesCache.Delete(repo)
197 return nil, fmt.Errorf("invalid repository feature cache entry for %s: expected *RepositoryFeatures, got %T", repo, cached)
198 }
199 repositoryFeaturesLog.Printf("Using cached repository features for: %s", repo)
200 return features, nil
201 }
202
203 repositoryFeaturesLog.Printf("Fetching repository features from API for: %s", repo)
204
205 // Fetch from API
206 features := &RepositoryFeatures{}
207
208 // Check discussions
209 hasDiscussions, err := checkRepositoryHasDiscussionsUncached(repo)
210 if err != nil {
211 return nil, fmt.Errorf("failed to check discussions: %w", err)
212 }
213 features.HasDiscussions = hasDiscussions
214
215 // Check issues
216 hasIssues, err := checkRepositoryHasIssuesUncached(repo)
217 if err != nil {
218 return nil, fmt.Errorf("failed to check issues: %w", err)
219 }
220 features.HasIssues = hasIssues
221
222 // Cache the result using sync.Map's LoadOrStore for atomic caching
223 // This handles the race condition where multiple goroutines might fetch the same repo
224 actual, loaded := repositoryFeaturesCache.LoadOrStore(repo, features)
225 actualFeatures, ok := actual.(*RepositoryFeatures)
226 if !ok {
227 repositoryFeaturesCache.Delete(repo)
228 return nil, fmt.Errorf("invalid repository feature cache entry for %s: expected *RepositoryFeatures, got %T", repo, actual)
229 }
230
231 repositoryFeaturesLog.Printf("Cached repository features for: %s (discussions: %v, issues: %v)", repo, actualFeatures.HasDiscussions, actualFeatures.HasIssues)
232
233 // Only log the success messages if this is the first time we're caching these features
234 // and we haven't logged them before (checking loaded flag and logged cache)
235 if !loaded {
236 // Mark as logged atomically
237 // Log success messages only if we haven't logged them before
238 if _, alreadyLogged := repositoryFeaturesLoggedCache.LoadOrStore(repo, true); !alreadyLogged && verbose {
239 if actualFeatures.HasDiscussions {
240 fmt.Fprintln(os.Stderr, console.FormatInfoMessage(
241 fmt.Sprintf("✓ Repository %s has discussions enabled", repo)))
242 }
243 if actualFeatures.HasIssues {
244 fmt.Fprintln(os.Stderr, console.FormatInfoMessage(
245 fmt.Sprintf("✓ Repository %s has issues enabled", repo)))
246 }
247 }
248 }

Callers 2

checkRepositoryHasIssuesFunction · 0.85

Calls 7

FormatInfoMessageFunction · 0.92
LoadMethod · 0.80
DeleteMethod · 0.80
ErrorfMethod · 0.45
PrintfMethod · 0.45

Tested by

no test coverage detected