Skip to content

Commit

Permalink
UI: autodetect pasted URL
Browse files Browse the repository at this point in the history
  • Loading branch information
manics committed Dec 10, 2023
1 parent 819bba8 commit 6be5552
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 10 deletions.
30 changes: 21 additions & 9 deletions binderhub/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,15 +455,10 @@ def get_builder_volumes(self):

return volumes, volume_mounts

def submit(self):
def get_env(self):
"""
Submit a build pod to create the image for the repository.
Progress of the build can be monitored by listening for items in
the Queue passed to the constructor as `q`.
Get the Kubernetes environment variables for the build pod.
"""
volumes, volume_mounts = self.get_builder_volumes()

env = [
client.V1EnvVar(name=key, value=value)
for key, value in self.extra_envs.items()
Expand All @@ -472,16 +467,23 @@ def submit(self):
env.append(
client.V1EnvVar(name="GIT_CREDENTIAL_ENV", value=self.git_credentials)
)

if self.registry_credentials:
env.append(
client.V1EnvVar(
name="CONTAINER_ENGINE_REGISTRY_CREDENTIALS",
value=json.dumps(self.registry_credentials),
)
)
return env

def make_pod(self):
"""
Make a Kubernetes pod specification for the build pod.
"""
volumes, volume_mounts = self.get_builder_volumes()
env = self.get_env()

self.pod = client.V1Pod(
pod = client.V1Pod(
metadata=client.V1ObjectMeta(
name=self.name,
labels={
Expand Down Expand Up @@ -528,6 +530,16 @@ def submit(self):
affinity=self.get_affinity(),
),
)
return pod

def submit(self):
"""
Submit a build pod to create the image for the repository.
Progress of the build can be monitored by listening for items in
the Queue passed to the constructor as `q`.
"""
self.pod = self.make_pod()

try:
_ = self.api.create_namespaced_pod(
Expand Down
6 changes: 6 additions & 0 deletions binderhub/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ def generate_config(self):
"repo_providers"
].items():
config[repo_provider_class_alias] = repo_provider_class.labels
config[repo_provider_class_alias][
"display_name"
] = repo_provider_class.display_name
config[repo_provider_class_alias][
"regex_detect"
] = repo_provider_class.regex_detect
return config

async def get(self):
Expand Down
28 changes: 28 additions & 0 deletions binderhub/repoproviders.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ class RepoProvider(LoggingConfigurable):
config=True,
)

regex_detect = List(
[],
help="""
List of regexes to detect repository parameters from URLs.
""",
)

unresolved_ref = Unicode()

git_credentials = Unicode(
Expand Down Expand Up @@ -192,6 +199,15 @@ def is_valid_sha1(sha1):
class FakeProvider(RepoProvider):
"""Fake provider for local testing of the UI"""

name = Unicode("Fake")

display_name = "Fake GitHub"

regex_detect = [
r"^https://github.com/(?<repo>[^/]+/[^/]+)(/blob/(?<ref>[^/]+)(/(?<filepath>.+))?)?$",
r"^https://github.com/(?<repo>[^/]+/[^/]+)(/tree/(?<ref>[^/]+)(/(?<urlpath>.+))?)?$",
]

labels = {
"text": "Fake Provider",
"tag_text": "Fake Ref",
Expand Down Expand Up @@ -627,6 +643,11 @@ def _default_git_credentials(self):
return rf"username=binderhub\npassword={self.private_token}"
return ""

regex_detect = [
r"^https://gitlab.com/(?<repo>[^/]+/[^/]+)(/-/blob/(?<ref>[^/]+)(/(?<filepath>.+))?)?$",
r"^https://gitlab.com/(?<repo>[^/]+/[^/]+)(/-/tree/(?<ref>[^/]+)(/(?<urlpath>.+))?)?$",
]

labels = {
"text": "GitLab.com repository or URL",
"tag_text": "Git ref (branch, tag, or commit)",
Expand Down Expand Up @@ -780,6 +801,11 @@ def _default_git_credentials(self):
return rf"username={self.access_token}\npassword=x-oauth-basic"
return ""

regex_detect = [
r"^https://github.com/(?<repo>[^/]+/[^/]+)(/blob/(?<ref>[^/]+)(/(?<filepath>.+))?)?$",
r"^https://github.com/(?<repo>[^/]+/[^/]+)(/tree/(?<ref>[^/]+)(/(?<urlpath>.+))?)?$",
]

labels = {
"text": "GitHub repository name or URL",
"tag_text": "Git ref (branch, tag, or commit)",
Expand Down Expand Up @@ -973,6 +999,8 @@ class GistRepoProvider(GitHubRepoProvider):
help="Flag for allowing usages of secret Gists. The default behavior is to disallow secret gists.",
)

regex_detect = [r"^https://gist.github.com/(?<repo>[^/]+/[^/]+)(/(?<ref>[^/]+))?$"]

labels = {
"text": "Gist ID (username/gistId) or URL",
"tag_text": "Git commit SHA",
Expand Down
35 changes: 34 additions & 1 deletion binderhub/static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BinderRepository } from "@jupyterhub/binderhub-client";
import { updatePathText } from "./src/path";
import { nextHelpText } from "./src/loading";
import { updateFavicon } from "./src/favicon";
import { detect } from "./src/autodetect";

import "xterm/css/xterm.css";

Expand Down Expand Up @@ -166,7 +167,39 @@ function indexMain() {
updatePathText();
updateRepoText(BASE_URL);

$("#repository").on("keyup paste change", function () {
// If the user pastes a URL into the repository field try to autodetect
// In all other cases don't do anything to avoid overwriting the user's input
$("#repository").on("paste", function (ev) {
const event = ev.originalEvent;
const pastedText = (event.clipboardData || window.clipboardData)
?.getData("text")
.trim();
if (pastedText) {
const fields = detect(pastedText);
console.log(fields);
if (fields) {
$("#provider_prefix-selected").text(fields.display_name);
$("#provider_prefix").val(fields.provider);
$("#repository").val(fields.repo);
if (fields.ref) {
$("#ref").val(fields.ref);
}
if (fields.path) {
$("#filepath").val(fields.path);
$("#url-or-file-selected").text(
fields.pathType === "filepath" ? "File" : "URL",
);
}
updatePathText();
event.preventDefault();
updateRepoText(BASE_URL);
}
}
// else autodetect failed, let the paste go through
updateUrls(BADGE_BASE_URL);
});

$("#repository").on("keyup change", function () {
updateUrls(BADGE_BASE_URL);
});

Expand Down
27 changes: 27 additions & 0 deletions binderhub/static/js/src/autodetect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getConfigDict } from "./repo";

export function detect(text) {
// Assumes configDict was already loaded by another module
const configDict = getConfigDict();
for (const provider in configDict) {
const regex_detect = configDict[provider].regex_detect || [];
for (const regex of regex_detect) {
const m = text.match(regex);
if (m?.groups.repo) {
return {
provider: provider,
display_name: configDict[provider].display_name,
repo: m.groups.repo,
ref: m.groups.ref,
path: m.groups.filepath || m.groups.urlpath || null,
pathType: m.groups.filepath
? "filepath"
: m.groups.urlpath
? "urlpath"
: null,
};
}
}
}
return null;
}
4 changes: 4 additions & 0 deletions binderhub/static/js/src/repo.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ export function updateRepoText(baseUrl) {
setLabels();
}
}

export function getConfigDict() {
return configDict;
}

0 comments on commit 6be5552

Please sign in to comment.