θΏ™ζ˜―indexlocζδΎ›ηš„ζœεŠ‘οΌŒδΈθ¦θΎ“ε…₯任何密码
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
11497d4
create gitlab copies of github files
DipFlip Jul 10, 2024
341bd04
Added collector utilities for interacting with Gitlab repositories.
DipFlip Jul 10, 2024
d7dbc25
The GitHub methods have been converted to work with GitLab.
DipFlip Jul 10, 2024
7754723
Added GitLab option to the UI.
DipFlip Jul 10, 2024
33ee73b
change GitLab to Gitlab
DipFlip Jul 10, 2024
ef698ed
add gitlab file
DipFlip Jul 10, 2024
78a1421
Added GitLab as a new data connector option.
DipFlip Jul 10, 2024
b77fcc5
set to ollama
DipFlip Jul 11, 2024
8ea5fc6
Adapted the GitHub importer to work with GitLab repositories.
DipFlip Jul 11, 2024
2b12df2
Added the GitLab equivalent methods to the dataConnector.js file.
DipFlip Jul 11, 2024
076bd68
Added missing GitLab parts to the extensions/index.js file.
DipFlip Jul 11, 2024
ce80f16
Added missing GitLab parts to the extensions/index.js file.
DipFlip Jul 11, 2024
3392c77
Added GitLab endpoints to match the existing GitHub endpoints in serv…
DipFlip Jul 11, 2024
5cf3065
Replaced the GitLab RepoLoader's dependency on axios with the built-i…
DipFlip Jul 11, 2024
4ed56f5
Simplified the GitLab implementation to more closely match the GitHub…
DipFlip Jul 11, 2024
79f66b0
Refactor GitLabRepo implementation to match GitHub methods and endpoints
DipFlip Jul 22, 2024
fc85307
update loading of files within subfolders
DipFlip Jul 22, 2024
13b9aca
give logo a white background
DipFlip Jul 22, 2024
a1da17c
fix subfolder naming
DipFlip Jul 22, 2024
a253ce6
revert unecessary change
DipFlip Jul 22, 2024
f8653a3
correct gitlab repo name
DipFlip Jul 22, 2024
0c2b02e
run yarn lint
DipFlip Jul 22, 2024
7ce0b82
remove aider addition in gitignore
DipFlip Jul 22, 2024
9e69aa6
revert change to .env.example
DipFlip Jul 22, 2024
d4416dc
Merge branch 'master' into 812-gitlab-connector
timothycarambat Jul 22, 2024
ba83191
enable collecting multiple repos
DipFlip Jul 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions collector/extensions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,60 @@ function extensions(app) {
}
);

app.post(
"/ext/gitlab-repo",
[verifyPayloadIntegrity, setDataSigner],
async function (request, response) {
try {
const { loadGitlabRepo } = require("../utils/extensions/GitlabRepo");
const { success, reason, data } = await loadGitlabRepo(
reqBody(request),
response,
);
response.status(200).json({
success,
reason,
data,
});
} catch (e) {
console.error(e);
response.status(200).json({
success: false,
reason: e.message || "A processing error occurred.",
data: {},
});
}
return;
}
);

app.post(
"/ext/gitlab-repo",
[verifyPayloadIntegrity, setDataSigner],
async function (request, response) {
try {
const { loadGitlabRepo } = require("../utils/extensions/GitlabRepo");
const { success, reason, data } = await loadGitlabRepo(
reqBody(request),
response,
);
response.status(200).json({
success,
reason,
data,
});
} catch (e) {
console.error(e);
response.status(200).json({
success: false,
reason: e.message || "A processing error occurred.",
data: {},
});
}
return;
}
);

// gets all branches for a specific repo
app.post(
"/ext/github-repo/branches",
Expand Down Expand Up @@ -85,6 +139,67 @@ function extensions(app) {
}
);

app.post(
"/ext/gitlab-repo/branches",
[verifyPayloadIntegrity],
async function (request, response) {
try {
const GitlabRepoLoader = require("../utils/extensions/GitlabRepo/RepoLoader");
const allBranches = await new GitlabRepoLoader(
reqBody(request)
).getRepoBranches();
response.status(200).json({
success: true,
reason: null,
data: {
branches: allBranches,
},
});
} catch (e) {
console.error(e);
response.status(400).json({
success: false,
reason: e.message,
data: {
branches: [],
},
});
}
return;
}
);

// gets all branches for a specific GitLab repo
app.post(
"/ext/gitlab-repo/branches",
[verifyPayloadIntegrity],
async function (request, response) {
try {
const GitlabRepoLoader = require("../utils/extensions/GitlabRepo/RepoLoader");
const allBranches = await new GitlabRepoLoader(
reqBody(request)
).getRepoBranches();
response.status(200).json({
success: true,
reason: null,
data: {
branches: allBranches,
},
});
} catch (e) {
console.error(e);
response.status(400).json({
success: false,
reason: e.message,
data: {
branches: [],
},
});
}
return;
}
);

app.post(
"/ext/youtube-transcript",
[verifyPayloadIntegrity],
Expand Down
162 changes: 162 additions & 0 deletions collector/utils/extensions/GitlabRepo/RepoLoader/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
const https = require("https");
const UrlPattern = require("url-pattern");

class RepoLoader {
constructor(args = {}) {
this.ready = false;
this.repo = args?.repo;
this.branch = args?.branch;
this.accessToken = args?.accessToken || null;
this.ignorePaths = args?.ignorePaths || [];

this.projectId = null;
this.branches = [];
}

#validGitlabUrl() {
const pattern = new UrlPattern("https\\://gitlab.com/(:projectId(*))", {
segmentValueCharset: "a-zA-Z0-9-._~%/+",
});
const match = pattern.match(this.repo);
if (!match) return false;

this.projectId = encodeURIComponent(match.projectId);
return true;
}

async #validBranch() {
await this.getRepoBranches();
if (!!this.branch && this.branches.includes(this.branch)) return;

console.log(
"[Gitlab Loader]: Branch not set! Auto-assigning to a default branch."
);
this.branch = this.branches.includes("main") ? "main" : "master";
console.log(`[Gitlab Loader]: Branch auto-assigned to ${this.branch}.`);
return;
}

async #validateAccessToken() {
if (!this.accessToken) return;
try {
await this.#makeRequest("https://gitlab.com/api/v4/user");
} catch (e) {
console.error(
"Invalid Gitlab Access Token provided! Access token will not be used",
e.message
);
this.accessToken = null;
}
}

async init() {
if (!this.#validGitlabUrl()) return;
await this.#validBranch();
await this.#validateAccessToken();
this.ready = true;
return this;
}

async recursiveLoader() {
if (!this.ready) throw new Error("[Gitlab Loader]: not in ready state!");

if (this.accessToken)
console.log(
`[Gitlab Loader]: Access token set! Recursive loading enabled!`
);

const files = await this.getRepositoryTree();
const docs = [];

for (const file of files) {
if (this.ignorePaths.some((path) => file.path.includes(path))) continue;
const content = await this.fetchSingleFile(file.path);
if (content) {
docs.push({
pageContent: content,
metadata: { source: file.path },
});
}
}

return docs;
}

#branchPrefSort(branches = []) {
const preferredSort = ["main", "master"];
return branches.reduce((acc, branch) => {
if (preferredSort.includes(branch)) return [branch, ...acc];
return [...acc, branch];
}, []);
}

async getRepoBranches() {
if (!this.#validGitlabUrl() || !this.projectId) return [];
await this.#validateAccessToken();

try {
const data = await this.#makeRequest(
`https://gitlab.com/api/v4/projects/${this.projectId}/repository/branches`
);
this.branches = JSON.parse(data).map((branch) => branch.name);
return this.#branchPrefSort(this.branches);
} catch (err) {
console.log(`RepoLoader.branches`, err);
return [];
}
}

async getRepositoryTree() {
try {
const data = await this.#makeRequest(
`https://gitlab.com/api/v4/projects/${this.projectId}/repository/tree?ref=${this.branch}&recursive=true&per_page=100`
);
return JSON.parse(data).filter((item) => item.type === "blob");
} catch (e) {
console.error(`RepoLoader.getRepositoryTree`, e);
return [];
}
}

async fetchSingleFile(sourceFilePath) {
try {
const data = await this.#makeRequest(
`https://gitlab.com/api/v4/projects/${
this.projectId
}/repository/files/${encodeURIComponent(sourceFilePath)}/raw?ref=${
this.branch
}`
);
return data;
} catch (e) {
console.error(`RepoLoader.fetchSingleFile`, e);
return null;
}
}

#makeRequest(url) {
return new Promise((resolve, reject) => {
const options = {
headers: this.accessToken ? { "PRIVATE-TOKEN": this.accessToken } : {},
};

https
.get(url, options, (res) => {
let data = "";
res.on("data", (chunk) => (data += chunk));
res.on("end", () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(data);
} else {
reject(
new Error(`Request failed with status code ${res.statusCode}`)
);
}
});
})
.on("error", reject);
});
}
}

module.exports = RepoLoader;
Loading