github.com/massongit/reviewdog@v0.0.0-20240331071725-4a16675475a8/doghouse/server/storage/installation.go (about) 1 package storage 2 3 import ( 4 "context" 5 6 "cloud.google.com/go/datastore" 7 ) 8 9 // GitHubInstallation represents GitHub Apps Installation data. 10 // Installation is per org or user account, not repository. 11 type GitHubInstallation struct { 12 InstallationID int64 // https://github.com/settings/installations/<InstallationID> 13 AccountName string // https://github/<AccountName>. Org or user account. 14 AccountID int64 // GitHub ID of <AccountName>. 15 } 16 17 // GitHubInstallationStore represents GitHubInstallation storage interface. 18 type GitHubInstallationStore interface { 19 // Put upserts GitHub InstallationID entity. If InstallationID is not 20 // updated, the whole entity won't be saved. 21 Put(ctx context.Context, inst *GitHubInstallation) error 22 // Get get GitHubInstallation entity by account name. 23 // - If the entity is found, return inst with ok is true. 24 // - If the entity is not found, ok is false. 25 // - If error occurs, it returns err. 26 Get(ctx context.Context, accountName string) (ok bool, inst *GitHubInstallation, err error) 27 } 28 29 // GitHubInstallationDatastore is store of GitHubInstallation by Datastore of 30 // Google Appengine. 31 type GitHubInstallationDatastore struct{} 32 33 func (g *GitHubInstallationDatastore) newKey(accountName string) *datastore.Key { 34 const kind = "GitHubInstallation" 35 return datastore.NameKey(kind, accountName, nil) 36 } 37 38 // Put save GitHubInstallation. It reduces datastore write call as much as possible. 39 func (g *GitHubInstallationDatastore) Put(ctx context.Context, inst *GitHubInstallation) error { 40 d, err := datastoreClient(ctx) 41 if err != nil { 42 return err 43 } 44 _, err = d.RunInTransaction(ctx, func(t *datastore.Transaction) error { 45 var foundInst GitHubInstallation 46 var ok bool 47 err := t.Get(g.newKey(inst.AccountName), &foundInst) 48 if err != datastore.ErrNoSuchEntity { 49 ok = true 50 } 51 if err != nil { 52 return err 53 } 54 // Insert if not found or installation ID is different. 55 if !ok || foundInst.InstallationID != inst.InstallationID { 56 _, err = t.Put(g.newKey(inst.AccountName), inst) 57 return err 58 } 59 return nil // Do nothing. 60 }) 61 return err 62 } 63 64 func (g *GitHubInstallationDatastore) Get(ctx context.Context, accountName string) (ok bool, inst *GitHubInstallation, err error) { 65 key := g.newKey(accountName) 66 inst = new(GitHubInstallation) 67 d, err := datastoreClient(ctx) 68 if err != nil { 69 return false, nil, err 70 } 71 if err := d.Get(ctx, key, inst); err != nil { 72 if err == datastore.ErrNoSuchEntity { 73 return false, nil, nil 74 } 75 return false, nil, err 76 } 77 return true, inst, nil 78 }