From e86205547a9c9a0dfc14e1b888e91cdfde84b9fd Mon Sep 17 00:00:00 2001 From: d-rk Date: Mon, 24 Jan 2022 20:12:30 +0100 Subject: [PATCH] Add GitLab engine (#19) Co-authored-by: Art Chaidarun --- README.md | 3 ++- config.yaml | 7 ++++++ src/engines/gitlab.ts | 52 +++++++++++++++++++++++++++++++++++++++++++ src/engines/index.ts | 2 ++ src/util.ts | 29 ++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/engines/gitlab.ts diff --git a/README.md b/README.md index f35b969..989241a 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,12 @@ The full list of supported data sources: - [Dropbox](https://www.dropbox.com/) files and folders - [Figma](https://www.figma.com/) files, projects, and teams - [GitHub](https://github.com/) PRs, issues, and repo metadata +- [GitLab](https://gitlab.com/) merge-requests - [Google Drive](https://www.google.com/drive/) docs, spreadsheets, etc. - [Google Groups](https://groups.google.com/) groups - [Greenhouse](https://www.greenhouse.io/) job posts - [Guru](https://www.getguru.com/) cards -- [Hound](https://github.com/hound-search/hound)-indexed code +- [Hound](https://github.com/hound-search/hound) indexed code - [Jenkins](https://www.jenkins.io/) job names - [Jira](https://www.atlassian.com/software/jira) issues - [Lingo](https://www.lingoapp.com/) assets diff --git a/config.yaml b/config.yaml index 8311b68..7a9d299 100644 --- a/config.yaml +++ b/config.yaml @@ -93,6 +93,13 @@ engines: # GitHub personal access token token: abcdef0123456789abcdef0123456789abcdef01 + # GitLab Merge Requests + gitlab: + # GitLab API origin (optional, defaults to https://gitlab.com) + origin: https://gitlab.com + # GitLab personal access token + token: abcdef0123456789abcdef0123456789abcdef01 + # Greenhouse job posts greenhouse: # Board token diff --git a/src/engines/gitlab.ts b/src/engines/gitlab.ts new file mode 100644 index 0000000..dc3e541 --- /dev/null +++ b/src/engines/gitlab.ts @@ -0,0 +1,52 @@ +import axios, { AxiosInstance } from "axios"; +import * as marked from "marked"; + +import { getUnixTime, trimLines } from "../util"; + +let client: AxiosInstance | undefined; + +const engine: Engine = { + id: "gitlab", + init: ({ + origin = "https://gitlab.com", + token, + }: { + origin: string; + token: string; + }) => { + const axiosClient = axios.create({ + baseURL: `${origin}/api/v4`, + headers: { Authorization: `bearer ${token}` }, + }); + client = axiosClient; + }, + name: "GitLab", + search: async q => { + if (!client) { + throw Error("Engine not initialized"); + } + + // https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests + const data: { + description: string; + title: string; + updated_at: string; + web_url: string; + }[] = ( + await client.get("/merge_requests", { + params: { scope: "all", search: q }, + }) + ).data; + + return data.map(mr => ({ + modified: getUnixTime(mr.updated_at), + snippet: `
${marked( + trimLines(mr.description, q), + )}
`, + title: mr.title, + url: mr.web_url, + })); + }, +}; + +export default engine; diff --git a/src/engines/index.ts b/src/engines/index.ts index 8df0fd9..ac195b7 100644 --- a/src/engines/index.ts +++ b/src/engines/index.ts @@ -4,6 +4,7 @@ import drive from "./drive"; import dropbox from "./dropbox"; import figma from "./figma"; import github from "./github"; +import gitlab from "./gitlab"; import greenhouse from "./greenhouse"; import groups from "./groups"; import guru from "./guru"; @@ -28,6 +29,7 @@ const engines: Engine[] = [ dropbox, figma, github, + gitlab, greenhouse, groups, guru, diff --git a/src/util.ts b/src/util.ts index 8b00737..ed81c9b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -87,6 +87,35 @@ export const fuzzyIncludes = (() => { fuzzify(haystack ?? "").includes(fuzzify(needle)); })(); +/** + * Trims the result to at most `MAX_ROWS` lines. This method is used to + * restrict the length of a search result snippet, so that the UI stays clear. + * The method tries to trim the lines in a way such that at least the first + * match to the query stays visible. + */ +export const trimLines = (result: string, q: string): string => { + const MAX_ROWS = 8; + const halfRows = MAX_ROWS / 2; + + result = result.trim(); + const lines = result.split("\n"); + if (lines.length <= MAX_ROWS) { + return result; + } + + const matchIdx = lines.findIndex(line => fuzzyIncludes(line, q)); + let startIdx = Math.max(0, matchIdx - halfRows); + let endIdx = Math.min(lines.length, matchIdx + halfRows); + + if (startIdx === 0) { + endIdx = MAX_ROWS; + } else if (endIdx === lines.length) { + startIdx = lines.length - MAX_ROWS; + } + + return lines.slice(startIdx, endIdx).join("\n"); +}; + /** * Converts a date string such as "2020-06-30T21:06:25.166Z" to a Unix * timestamp in seconds.