-
Notifications
You must be signed in to change notification settings - Fork 117
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
feat: Add and edit github connection #5263
Conversation
Some initial UXQA –
|
if (userStatus.isFetching || userRepos.isFetching) { | ||
return { | ||
isLoading: true, | ||
error: undefined, | ||
}; | ||
} |
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 be consistent with terminology. If reading isFetching
, then we should return isFetching
. If reading isLoading
, then we should return isLoading
.
} from "@rilldata/web-common/components/alert-dialog"; | ||
import { Button } from "@rilldata/web-common/components/button"; | ||
import Github from "@rilldata/web-common/components/icons/Github.svelte"; | ||
import Select from "@rilldata/web-common/components/forms/Select.svelte"; |
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.
A little out-of-scope of this PR, but it'd be nice to deprecate this in favor of ShadCN's Select component
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.
IMO this extra layer of abstraction isn't necessary & adds complexity.
Is there something wrong with using vanilla TanStack Query in the ProjectGitHubConnection.svelte
component? That's the pattern we're using most frequently throughout the codebase.
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.
Similarly, is there a reason to be adding this abstraction on top of vanilla TanStack Query? To update the GitHub repo seems like a vanilla mutation and shouldn't require too much complexity. I wonder if the bugginess I shared via Jam is a derivative of this complexity.
If we're to go down this route, I'd expect a "GithubRepoUpdater" to include a method to actually update the Github repo, but that looks to be happening outside of this abstraction in the GithubRepoSelectionDialog.svelte
component.
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 endpoint can be slow if there are a lot of repos and orgs connected. I want to avoid refetching it on window focus all the time, but only when connect to github
or choose other repos
is clicked.
Both this and GithubConnection have a check to only refetch if it was explicitly asked for (basically the connecting
check).
Naming this GithubRepoUpdater
is just a remnant of some old code.
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.
Gotcha. The vanilla TanStack approach would be to use $githubQuery.refetch()
in the component itself. Might be simpler?
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 are refetching the query right? The idea is to hide as much code outside of components as possible. We still need the check if we popped a page to select github repos or not.
This will also hopefully allow us to abstract such code out. But it will have to be follow ups
9d005a5
to
860211b
Compare
860211b
to
546266e
Compare
|
||
function handleVisibilityChange() { | ||
if (document.visibilityState !== "visible") return; | ||
void githubReposConnection.focused(); |
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 had to read this function implementation to know what it was doing. If we put the Query Observer in this component, we could use $githubUserReposQuery.refetch()
, which would be more explicit.
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.
Gotcha. The vanilla TanStack approach would be to use $githubQuery.refetch()
in the component itself. Might be simpler?
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.
Some more UXQA:
- All user-facing text that says "github" or "Github" should be "GitHub"
- After triggering the connect-to-GitHub flow via the UI, it looks like this page should say "... continue setup in your original tab."
- I get back 150 repos from the
ListGithubUserRepos
API, but theSelect
component only shows me the first 100.
|
||
function confirmConnectToGithub() { | ||
confirmDialogOpen = false; | ||
void githubConnection.check(); |
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 as well, I had to read the function implementation to understand what was going on. What about just
const githubUserStatusQuery = createAdminServiceGetGithubUserStatus();
...
window.open(
$githubUserStatusQuery.data?.grantAccessUrl,
"_blank",
)
Writing down what we discussed live:
|
d18c8e8
to
21afe75
Compare
FYI, @jkhwu updated the designs to remove a couple cases of indentation. E.g., see these new mocks: The GitHub block no longer is indented by the GitHub logo. Instead the logo is inside the button: The "select your GitHub repository" form body is no longer indented by the GitHub logo: https://www.figma.com/design/Qt6EyotCBS3V6O31jVhMQ7/RILL?node-id=14933-609154&t=PgNKhdmzo8xhGY3P-1 |
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.
UXQA:
- The "Are you sure you want to connect?" dialog flashes & proceeds without waiting for confirmation from the user. See Jam
- After going through the "choose other repos" flow, I get brought to this page that references the CLI.
Possibly related, I've been wondering – when the connect-to-GitHub flow is complete, can we somehow communicate this to the/status
page, so it knows exactly when to refetch the list of repositories? Polling doesn't feel exactly right, (but the way you've contained the polling looks good).
|
||
function openGithubRepoCreator() { | ||
// we need a popup window so we cannot use href | ||
window.open("https://github.com/new", "", "width=1024,height=600"); |
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.
Nit: we can name the window (2nd parameter) githubWindow
. I had to Google what the empty string represented.
this.openGithubConnectWindow(userStatus.grantAccessUrl); | ||
} | ||
|
||
public async refetch() { |
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 think this function is only used internally – so it could be private
?
d9c6d47
to
61504ea
Compare
88539ad
to
af24d8b
Compare
UXQA –
|
admin/server/github.go
Outdated
|
||
claims := auth.GetClaims(ctx) | ||
if !claims.ProjectPermissions(ctx, proj.OrganizationID, proj.ID).ManageProject { | ||
return nil, status.Error(codes.PermissionDenied, "does not have permission to delete project") |
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.
Nit: Incorrect error msg delete project
admin/pkg/archive/archive.go
Outdated
@@ -0,0 +1,126 @@ | |||
package archive |
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.
Nit: Should this be part of runtime/pkg
since this is also used in runtime ?
admin/server/github.go
Outdated
SingleBranch: true, | ||
}) | ||
if err != nil { | ||
if errors.Is(err, transport.ErrEmptyRemoteRepository) { |
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.
Nit : Can simplify the if-else block by switching the if condition
return fmt.Errorf("failed to copy data: %w", err) | ||
} | ||
|
||
// add back the older gitignore contents if present |
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.
If we are anyways overwriting all other files then I think it should be okay to also overwrite .gitignore
file ?
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 a requirement to not completely replace the existing file. But rather append like we do with rill init
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.
IIRC in rill init
we did not delete existing files so it made sense to not remove existing .gitignore
.
Here we are deleting all existing files 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.
@nishantmonu51 @ericokuma Thoughts on the above?
a27c050
to
ce5ea9b
Compare
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.
Looks good from backend POV apart from few nits.
admin/server/github.go
Outdated
defer os.RemoveAll(dir) | ||
|
||
// use a subfolder for working with git | ||
gitPath := filepath.Join(dir, "proj") |
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 subfolder should not be required now. We can directly use the temp_dir
.
admin/server/github.go
Outdated
defer cancel() | ||
|
||
// generate a temp dir to extract the archive | ||
dir, err := os.MkdirTemp(os.TempDir(), "dest_git_repos") |
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.
Given this is used for both upload and git flow so we can just change the name to project
or similar?
admin/server/github.go
Outdated
return err | ||
} | ||
|
||
// projPath is the target for extracting the archive |
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.
misplaced comment ?
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.
Approving from backend POV
public constructor() {} | ||
|
||
public init(githubUrl: string, subpath: string, branch: string) { | ||
this.githubUrl.set(githubUrl); | ||
this.subpath.set(subpath); | ||
this.branch.set(branch); | ||
this.isConnected = !!githubUrl; | ||
} |
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.
It'd be more idiomatic to implement the constructor, rather than create a separate init
function
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.
Ya that was ideal earlier. But it is simpler to do this than create a new instance everytime.
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 feel like the separation of concerns between the GitHubData
and GitHubConnectionUpdater
classes is blurry. It might be a matter of naming & comments, or maybe all the "update" methods (startRepoSelection
, reselectRepos
, openGitHubConnectWindow
) should live on the "Updater" class?
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.
GitHubData
is meant to be a wrapper around the user status and repos APIs. GitHubConnectionUpdater
is only around the mutation to update. Both basically move code out of components as much as possible.
!(await githubConnectionUpdater.update({ | ||
organization, | ||
project, | ||
force, | ||
instanceId: $projectQuery.data?.prodDeployment?.runtimeInstanceId ?? "", | ||
})) | ||
) { |
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.
Nit: Embedding the mutation into the conditional check makes this hard to read. I'd recommend declaring a self-describing boolean, like didUpdate
.
const githubData = new GithubData(); | ||
setGithubData(githubData); |
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.
Should setGitHubData
happen in the constructor?
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.
setGitHubData
is the component tree logic. Makes sense for it to sit here.
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.
Approving from the frontend POV 👍
Notion: https://www.notion.so/rilldata/RD-RC-1-3-Project-Status-Page-updates-dd5daf216f5a4c05886b98bc20d4f8f5