batches: support distinct GH App installs for commit signing across namespaces #53212
Conversation
5f3759b to
c1ee1c9
Compare
|
Codenotify: Notifying subscribers in CODENOTIFY files for diff 8af181a...41f3297.
|
754ed2c to
f6c951c
Compare
pjlast
left a comment
There was a problem hiding this comment.
Not much to add, just see comment on table constraint 🙏
Oh hmm, I don't know how thoroughly I looked at that. I love your test org by the way. 😂 I'll look into that. Is the account that you're signed into on GitHub when you opened those links an owner of that org? It might 404 if your account isn't allowed to administer that installation. |
Haha thank yoou ♀️ Oh I'm not the owner of that org, I believe it allowed me to sign a commit through that org though with this setup. Let me test again, I have to step away but will test through this again when I'm back. Even so, we should maybe add more messaging around this edge case, right? |
Yeah that would be expected to me. A normal user should still be able authenticate with the installation, they just won't be able to administer it (and hence might not be able to see the install page for it on GitHub)
Probably! But we won't be able to know if the current user is an org owner or not. We have this note on the "Creation" page about installing apps on orgs: "Only organization owners can register GitHub Apps." Maybe I could add a note like that at the top of the "Installations" list? Like "Only organization owners can manage installations for organizations."? |
That sounds like a great solution to me! I just tested again (video below) with 3 orgs, one I'm just a member of, not an owner. The org settings aren't available, but everything else from SG batches commit signing works well. I think this disclaimer would be 👌🏻 Screen.Recording.2023-06-13.at.4.50.48.PM.mov |
|
Great, thank you for testing and confirming that. 😄 I'll follow up on that. |
… installations (#53790) @st0nebraker [pointed out](https://github.com/sourcegraph/sourcegraph/pull/53212#pullrequestreview-1475310777) in a previous PR that the "View on GitHub" link for GitHub App installations only works if you are able to administer that installation, e.g. that you are an org owner for the org where it's installed, if it's on an org, or that you are the user. If we had this information, we could just hide the button for installations the user can't actually view, but since we don't, we thought it could help to add a note instead. ## Test plan Just an in-product docs change. Verified the text appears on the GitHub App page. <!-- All pull requests REQUIRE a test plan: https://docs.sourcegraph.com/dev/background-information/testing_principles --> <br> Backport be1ff32 from #53611 Co-authored-by: Kelli Rockwell <kelli@sourcegraph.com>
Closes https://github.com/sourcegraph/sourcegraph/issues/53280.
Adds support for installing a Batches domain GitHub App on multiple accounts and then locating the appropriate installation by
repo namespace == account namein order to authenticate theChangesetSourcefor duplicating and signing commits.Walkthrough
I'm the master of producing chunky PRs lately so here's another code walkthrough to ease the burden of reviewing this. Remember that more than half the files changed are just for stupid
loggerplumbing and nothing else. 🙈 We'll go back to front again.new migrations - [code]
github_app_installstable. It also creates an index based on theaccount_login, since that's how we'll look up the right install for a given commit signing interaction.app_idandinstallation_id. This enables us to easily update records with the same SQLINSERTstatement we use to add a new one.github_apps/store- [code]Installnow takes a fully formedghtypes.GitHubAppInstallationas an input and performs an upsert (insert or update) of the record.GetLatestInstallIDhas been replaced with the more relevantGetInstallID, which looks up installations by app ID and account/namespace name and returns the installation ID of the latest record that matches.BulkInstallwas removed because it was easier to just loop and upsert individual records.SyncInstallationsis a new method that performs the logic that was originally in the installation backfill worker. This allows us to tap into it in another place. The logic has been enhanced slight as well:worker/installation_backfill- [code]store.SyncInstallations. The test has largely been migrated to thestorepackage tests instead.batches/sources- [code]withGitHubAppAuthenticatornow takesaccountas an additional argument and uses it to look up the installation for both the right app ID and account name when creating the installation authenticator.batches.graphql- [code]GitHubAppConfigurationtype with the sameGitHubApptype from the GH Apps GraphQL schema, since we're increasingly needing more and more properties of the App in the Batches space and it was beginning to feel redundant. Now thecommitSigningConfigurationfield will resolve to a fullGitHubApprather than our shallow copy of one.anything in
frontend/internal/batchesloggeror maybe anEnterpriseDBaround. It was extremely painful to write, but hopefully less painful to skim. 🙂code_host.go, where we now nest agithubapp.NewGitHubAppResolverfor the commit signing configuration.graphqlbackend.graphqlbackend.go- [code]NewSchemaWithBatchChangesResolverto provide both as resolvers, and updatedNewSchemato accept a slice of resolvers instead of just one. This had a bit of a ripple effect in that I had to update everyone who calls this method to call it with a slice now. 😅githubappauth/resolver.go- [code]Installationsfield on aGitHubApp, this resolver would requery GitHub itself for the Installations every time. Now we take the Installations we have stored in the DB to resolve this field faster.store.SyncInstallationswheneverInstallationsis called, so the set of Installations for theGitHubAppwill be updated immediately after if they are out-of-date. This has the added benefit of providing us a way to trigger a "manual sync" of GitHub App Installations if needed.Installationsis also now guarded behind async.Oncemechanism to ensure the function is only executed once for a given GraphQL request.githubappauth/middleware.go[code]/setuphandler will now fetch the whole GitHub App Installation before saving it in the DB, to ensure we can populate all the necessary metadata.GitHubAppPage- [code]/site-admin/batch-changes/github-apps/:id.Demo
Prior to this PR, we would just pretend that whatever GitHub App installation we had would work for any repositories on that code host. That would mean that publishing changesets on repositories from separate orgs wouldn't just not produce signed commits, it would actually just outright fail to publish.
In the demo, I start out with a new GitHub App, which I only install to my personal user account namespace. I test that when I publish two changesets, one to a repo in my user namespace and one to a repo in the
sourcegraph-testingnamespace, they both succeed to publish. In this case, thesourcegraph-testingone just falls back on normal batch change user credentials, yielding an unsigned commit but one which is authored by me. However, thecourier-newone is able to authenticate with as the GH App installation for that account and duplicate the commit, yielding the signed one!Then, I make the GH App publish and install it for
sourcegraph-testing. I modify the branch name for my batch spec to trigger new changesets to be published and publish the two again. This time, both succeed and have signed commits.Screen.Recording.2023-06-09.at.3.56.31.PM.mov
Test plan
Updated unit tests where applicable. Manual testing of the whole flow.