-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Webhook handler now processes installation_repositories events #3447
Conversation
3c503bc
to
a01f93c
Compare
931d80c
to
979e5c7
Compare
// We might want to ignore this case since we can only delete | ||
// repositories there were previously registered, which would | ||
// be deleted by means of "meta" and "repository" events as | ||
// well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting: we run into a race condition if, for a given repository that was removed from the org, we get a meta
before the installation_repositories
event, or vice versa. The first deletion succeeds, while the second fails.
error deleting repository from DB: error retrieving repository: sql: no rows in result set
This is not a problem right now, as it is handled correctly by logging some errors, but we do retry the deletion a handful of times, which might cause issues at scale.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the meta
event for the webhook/installation and the installation_repositories
for the repos only? Could we process one or the other? I think in either case they could be solved by a single db lookup, no? (if we are to add and the repo is already there, then skip, if we are to delete and the repo is already deleted, skip).
Either way, nice that you caught this issue already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to test what happens if we revoke access to a repository without deleting it from GitHub.
I believe that we don't get the "meta"
event in such a case, i.e. we have to handle "removed"
action for "installation_repositories"
events as well.
I'll test it manually and reply here.
// RepoReconcilerEvent is an event that is sent to the reconciler topic | ||
type RepoReconcilerEvent struct { | ||
// Project is the project that the event is relevant to | ||
Project uuid.UUID `json:"project"` | ||
// Repository is the repository to be reconciled | ||
Repository int64 `json:"repository" validate:"gte=0"` | ||
} | ||
|
||
// NewRepoReconcilerMessage creates a new repos init event | ||
func NewRepoReconcilerMessage(providerID uuid.UUID, repoID int64, projectID uuid.UUID) (*message.Message, error) { | ||
evt := &RepoReconcilerEvent{ | ||
Repository: repoID, | ||
Project: projectID, | ||
} | ||
|
||
evtStr, err := json.Marshal(evt) | ||
if err != nil { | ||
return nil, fmt.Errorf("error marshalling init event: %w", err) | ||
} | ||
|
||
msg := message.NewMessage(uuid.New().String(), evtStr) | ||
msg.Metadata.Set("provider_id", providerID.String()) | ||
return msg, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was moved here to solve a circular dependency between internal/reconcilers/reconcilers.go
and internal/service/service.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work. Left some comments inline, but overall this PR is shaping quite nicely!
|
||
installationID := event.GetInstallation().GetID() | ||
installation, err := s.store.GetInstallationIDByAppID(ctx, installationID) | ||
if errors.Is(err, sql.ErrNoRows) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we special-case this error somewhere?
I also wonder, does an unclaimed installation have an installation ID? (I think yes, but worth testing)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following, what is an unclaimed installation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The one you create without logging to minder first, e.g by going to https://github.com/apps/minder-instance/installations/new
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll test this.
} | ||
if !installation.ProjectID.Valid { | ||
return nil, errors.New("invalid project id") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should also test how these behave for an unclaimed install - I /think/ it should be OK as we create this special project (as we saw during pair-session on Friday), but worth testing.
ctx, | ||
repo, | ||
event.GetAction(), | ||
events.TopicQueueReconcileEntityAdd, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can the topic ever be something else (asking if it needs to be a parameter)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, this can only be a events.TopicQueueReconcileEntityAdd
.
Initially the routine was just one, this is a leftover.
// We might want to ignore this case since we can only delete | ||
// repositories there were previously registered, which would | ||
// be deleted by means of "meta" and "repository" events as | ||
// well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the meta
event for the webhook/installation and the installation_repositories
for the repos only? Could we process one or the other? I think in either case they could be solved by a single db lookup, no? (if we are to add and the repo is already there, then skip, if we are to delete and the repo is already deleted, skip).
Either way, nice that you caught this issue already.
Such events are triggered when a new repository is added to or removed from the list of repositories accessible to the app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we go! 🚀
|
||
installationID := event.GetInstallation().GetID() | ||
installation, err := s.store.GetInstallationIDByAppID(ctx, installationID) | ||
if errors.Is(err, sql.ErrNoRows) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following, what is an unclaimed installation?
ctx, | ||
repo, | ||
event.GetAction(), | ||
events.TopicQueueReconcileEntityAdd, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, this can only be a events.TopicQueueReconcileEntityAdd
.
Initially the routine was just one, this is a leftover.
// We might want to ignore this case since we can only delete | ||
// repositories there were previously registered, which would | ||
// be deleted by means of "meta" and "repository" events as | ||
// well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to test what happens if we revoke access to a repository without deleting it from GitHub.
I believe that we don't get the "meta"
event in such a case, i.e. we have to handle "removed"
action for "installation_repositories"
events as well.
I'll test it manually and reply here.
@@ -37,6 +37,7 @@ import ( | |||
mockmanager "github.com/stacklok/minder/internal/providers/manager/mock" | |||
ghrepo "github.com/stacklok/minder/internal/repositories/github" | |||
mockghrepo "github.com/stacklok/minder/internal/repositories/github/mock" | |||
rf "github.com/stacklok/minder/internal/repositories/github/mock/fixtures" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diff for this file should just be refactoring, I moved helper routines to this package.
topic: installations.ProviderInstallationTopic, | ||
statusCode: http.StatusOK, | ||
queued: nil, | ||
}, | ||
|
||
// installation repositories events |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the diff for this file is refactoring, relevant tests are here.
RepoEvent struct was added to avoid polluting EntityInfoWrapper further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great. I kicked the coverage tests because they seem to be failing while the "normal" unit test run succeeded, so it might be a fluke.
Summary
Such events are triggered when a new repository is added to or removed
from the list of repositories accessible to the app.
Fixes #3267
Change Type
Testing
Outline how the changes were tested, including steps to reproduce and any relevant configurations.
Attach screenshots if helpful.
Review Checklist: