-
Notifications
You must be signed in to change notification settings - Fork 6
feat: feed submission issue creation improvement #1536
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -327,7 +327,17 @@ async function createGithubIssue( | |
| if (formData.country && formData.country in countries) { | ||
| const country = countries[formData.country as TCountryCode]; | ||
| const continent = continents[country.continent].toLowerCase(); | ||
| if (continent != null) labels.push(continent); | ||
| if (continent != null) labels.push(`region/${continent}`); | ||
| } | ||
|
|
||
| if (formData.authType !== "None - 0") { | ||
| labels.push("auth required"); | ||
| } | ||
|
|
||
| if (!isValidZipUrl(formData.feedLink)) { | ||
| if (!await isValidZipDownload(formData.feedLink)) { | ||
| labels.push("invalid"); | ||
| } | ||
| } | ||
|
|
||
| try { | ||
|
|
@@ -345,6 +355,19 @@ async function createGithubIssue( | |
| }, | ||
| } | ||
| ); | ||
|
|
||
| const issueNodeId = response.data.node_id; | ||
| const projectId = "PVT_kwDOAnHxDs4Ayxl6"; | ||
| const statusFieldId = "PVTSSF_lADOAnHxDs4Ayxl6zgorIUI"; | ||
| const backlogOptionId = "8e14ac56"; | ||
|
Comment on lines
+360
to
+362
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These hardcoded variables should be hidden as ENV variables ex
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, we could also use 1Password to store them, there's an SDK for Javascript. |
||
| await addIssueToProjectV2( | ||
| issueNodeId, | ||
| githubToken, | ||
| projectId, | ||
| statusFieldId, | ||
| backlogOptionId | ||
| ); | ||
|
|
||
| return response.data.html_url; | ||
| } catch (error) { | ||
| logger.error("Error creating GitHub issue:", error); | ||
|
|
@@ -441,3 +464,132 @@ export function buildGithubIssueBody( | |
| return content; | ||
| } | ||
| /* eslint-enable */ | ||
|
|
||
| /** | ||
| * Parses the provided URL to check if it is a valid ZIP file URL | ||
| * @param {string | undefined | null } url The direct download URL | ||
| * @return {boolean} Whether the URL is a valid ZIP file URL | ||
| */ | ||
| function isValidZipUrl(url: string | undefined | null): boolean { | ||
| if (!url) return false; | ||
| try { | ||
| const parsed = new URL(url); | ||
| return parsed.pathname.toLowerCase().endsWith(".zip"); | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Checks if URL points to a valid ZIP file by making HEAD request | ||
| * @param {string | undefined | null } url The download URL | ||
| * @return {boolean} Whether the URL downloads a valid ZIP file | ||
| */ | ||
| async function isValidZipDownload( | ||
| url: string | undefined | null | ||
| ): Promise<boolean> { | ||
| try { | ||
| if (!url) return false; | ||
| const response = await axios.head(url, {maxRedirects: 2}); | ||
| const contentType = response.headers["content-type"]; | ||
| const contentDisposition = response.headers["content-disposition"]; | ||
|
|
||
| if (contentType && contentType.includes("zip")) return true; | ||
| if (contentDisposition && contentDisposition.includes("zip")) return true; | ||
| return false; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
|
Comment on lines
+468
to
+503
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As this file is getting large, bring these functions out into a helper file ex |
||
|
|
||
| /** | ||
| * Adds a GitHub issue to a project with a specific status | ||
| * @param {string} issueNodeId The ID of the created issue | ||
| * @param {string} githubToken GitHub token | ||
| * @param {string} projectId The ID of the project | ||
| * @param {string} statusFieldId The ID of the Status field | ||
| * @param {string} statusOptionId The ID of the status option | ||
| */ | ||
| async function addIssueToProjectV2( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same idea with this function, bring it outside |
||
| issueNodeId: string, | ||
| githubToken: string, | ||
| projectId: string, | ||
| statusFieldId: string, | ||
| statusOptionId: string | ||
| ) { | ||
| try { | ||
| const addToProjectMutation = ` | ||
| mutation($projectId: ID!, $contentId: ID!) { | ||
| addProjectV2ItemById( | ||
| input: {projectId: $projectId, contentId: $contentId} | ||
| ) { | ||
| item { id } | ||
| } | ||
| } | ||
| `; | ||
|
|
||
| const addToProjectResponse = await axios.post( | ||
| "https://api.github.com/graphql", | ||
| { | ||
| query: addToProjectMutation, | ||
| variables: { | ||
| projectId, | ||
| contentId: issueNodeId, | ||
| }, | ||
| }, | ||
| { | ||
| headers: { | ||
| Authorization: `bearer ${githubToken}`, | ||
| Accept: "application/vnd.github.v3+json", | ||
| }, | ||
| } | ||
| ); | ||
|
|
||
| const itemId = addToProjectResponse.data.data.addProjectV2ItemById.item.id; | ||
|
|
||
| const updateStatusMutation = ` | ||
| mutation( | ||
| $projectId: ID! | ||
| $itemId: ID! | ||
| $fieldId: ID! | ||
| $value: ProjectV2FieldValue! | ||
| ) { | ||
| updateProjectV2ItemFieldValue( | ||
| input: { | ||
| projectId: $projectId | ||
| itemId: $itemId | ||
| fieldId: $fieldId | ||
| value: $value | ||
| } | ||
| ) { | ||
| projectV2Item { id } | ||
| } | ||
| } | ||
| `; | ||
|
|
||
| await axios.post( | ||
| "https://api.github.com/graphql", | ||
| { | ||
| query: updateStatusMutation, | ||
| variables: { | ||
| projectId, | ||
| itemId, | ||
| fieldId: statusFieldId, | ||
| value: { | ||
| singleSelectOptionId: statusOptionId, | ||
| }, | ||
| }, | ||
| }, | ||
| { | ||
| headers: { | ||
| Authorization: `bearer ${githubToken}`, | ||
| Accept: "application/vnd.github.v3+json", | ||
| }, | ||
| } | ||
| ); | ||
|
|
||
| logger.info("Successfully added issue to Feed Submissions Backlog"); | ||
| } catch (error) { | ||
| logger.error("Error adding issue to Feed Submissions Backlog:", error); | ||
| } | ||
| } | ||
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.
For GTFS feeds, the expectation is that the resource's content is a ZIP file. However, many URLs don't have a
zipsuffix. I would remove this condition in favor of data_type == GTFS and not authentication required (since the key will not be available when we check the resource).