Skip to content

Update GitLab REST client library #18523

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

Merged
merged 7 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions components/server/leeway.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ COPY components-server--app /installer/
WORKDIR /app
RUN /installer/install.sh

# NodeJS v16.19
FROM cgr.dev/chainguard/node@sha256:95bb4763acb8e9702c956e093932be97ab118db410a0619bb3fdd334c9198006
FROM cgr.dev/chainguard/node:18.17.1@sha256:fbaecf4d6ac9883699078c0b501aad22c866f9ce039d009212c0eed260914875
ENV NODE_OPTIONS="--unhandled-rejections=warn --max_old_space_size=2048"

EXPOSE 3000
Expand Down
2 changes: 1 addition & 1 deletion components/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"@authzed/authzed-node": "^0.12.1",
"@bufbuild/connect": "^0.8.1",
"@bufbuild/connect-express": "^0.8.1",
"@gitbeaker/node": "^35.7.0",
"@gitbeaker/rest": "^39.12.0",
"@gitpod/content-service": "0.1.5",
"@gitpod/gitpod-db": "0.1.5",
"@gitpod/gitpod-protocol": "0.1.5",
Expand Down
52 changes: 22 additions & 30 deletions components/server/src/gitlab/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { injectable, inject } from "inversify";
import { User } from "@gitpod/gitpod-protocol";

import { Gitlab } from "@gitbeaker/node";
import { Gitlab } from "@gitbeaker/rest";
import {
Projects,
Users,
Expand All @@ -19,10 +19,12 @@ import {
MergeRequests,
Issues,
RepositoryFiles,
NamespaceSchema,
UserSchema,
ExpandedUserSchema,
ProjectSchema,
SimpleProjectSchema,
} from "@gitbeaker/core";
import { ProjectExtendedSchema } from "@gitbeaker/core/dist/types/resources/Projects";
import { NamespaceSchema } from "@gitbeaker/core/dist/types/resources/Namespaces";
import { UserExtendedSchema, UserSchema } from "@gitbeaker/core/dist/types/resources/Users";
import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
import { GitLabScope } from "./scopes";
import { AuthProviderParams } from "../auth/auth-provider";
Expand Down Expand Up @@ -60,21 +62,11 @@ export class GitLabApi {
const response = (await operation(userApi)) as R;
return response as R;
} catch (error) {
if (error && typeof error?.response?.status === "number" && error?.response?.status !== 200) {
return new GitLab.ApiError(`GitLab responded with code ${error.response.status}`, error);
}
if (error && error?.name === "HTTPError") {
// e.g.
// {
// "name": "HTTPError",
// "timings": { },
// "description": "404 Commit Not Found"
// }

return new GitLab.ApiError(
`GitLab Request Error: ${error?.description?.name || JSON.stringify(error?.description)}`,
error,
);
const status = error?.cause?.response?.status;
const statusText = error?.cause?.response?.statusText;
if (error && typeof status === "number" && status !== 200) {
const description = error?.cause?.description || `${status} - ${statusText}`;
return new GitLab.ApiError(`GitLab responded: ${description}`, status);
}
throw error;
} finally {
Expand All @@ -90,9 +82,7 @@ export class GitLabApi {
path: string,
): Promise<string | undefined> {
const projectId = `${org}/${name}`;
const result = await this.run<string>(user, (api) =>
api.RepositoryFiles.showRaw(projectId, path, { ref: commitish }),
);
const result = await this.run<string>(user, (api) => api.RepositoryFiles.showRaw(projectId, path, commitish));
if (GitLab.ApiError.is(result)) {
return undefined; // e.g. 404 error, because the file isn't found
}
Expand All @@ -116,10 +106,8 @@ export namespace GitLab {
RepositoryFiles: RepositoryFiles;
}
export class ApiError extends Error {
readonly httpError: { name: string; description: string } | undefined;
constructor(msg?: string, httpError?: any) {
constructor(msg?: string, readonly code?: number) {
super(msg);
this.httpError = httpError;
this.name = "GitLabApiError";
}
}
Expand All @@ -128,16 +116,16 @@ export namespace GitLab {
return !!something && something.name === "GitLabApiError";
}
export function isNotFound(error: ApiError): boolean {
return !!error.httpError?.description.startsWith("404");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen the startsWith of undefined before, and it was related to GitLab contexts. 🙏🏻 hopefully that's the cause

return error.code === 404;
}
export function isInternalServerError(error: ApiError): boolean {
return !!error.httpError?.description.startsWith("500");
return error.code === 500;
}
}
/**
* https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/projects.md#get-single-project
*/
export interface Project extends ProjectExtendedSchema {
interface ProjectFiltered extends Omit<ProjectSchema, "permissions"> {
visibility: "public" | "private" | "internal";
archived: boolean;
path: string; // "diaspora-project-site"
Expand All @@ -148,15 +136,19 @@ export namespace GitLab {
"id" | "name" | "path" | "kind" | "full_path" | "avatar_url" | "web_url" | "avatar_url" | "parent_id"
>;
owner: Pick<UserSchema, "id" | "name" | "created_at" | "avatar_url">;
permissions: Permissions;
merge_requests_enabled: boolean;
issues_enabled: boolean;
open_issues_count: number;
forks_count: number;
star_count: number;
forked_from_project?: Project;
forked_from_project?: ProjectSchema;
default_branch: string;
web_url: string;
}
// workaround for https://github.com/microsoft/TypeScript/issues/36981
export type Project = ProjectFiltered & SimpleProjectSchema;

export interface TreeObject {
id: string;
mode: string;
Expand Down Expand Up @@ -227,7 +219,7 @@ export namespace GitLab {
merge_requests_count: number;
}
// https://docs.gitlab.com/ee/api/users.html#list-current-user-for-normal-users
export interface User extends UserExtendedSchema {
export interface User extends ExpandedUserSchema {
email: string;
state: "active" | string;
}
Expand Down
2 changes: 1 addition & 1 deletion components/server/src/gitlab/file-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class GitlabFileProvider implements FileProvider {
path: string,
): Promise<string> {
const result = await this.gitlabApi.run<GitLab.Commit[]>(user, async (g) => {
return g.Commits.all(`${repository.owner}/${repository.name}`, { path, ref_name: revisionOrBranch });
return g.Commits.all(`${repository.owner}/${repository.name}`, { path, refName: revisionOrBranch });
});

if (GitLab.ApiError.is(result)) {
Expand Down
4 changes: 2 additions & 2 deletions components/server/src/gitlab/gitlab-app-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { AuthProviderInfo, ProviderRepository, User } from "@gitpod/gitpod-protocol";
import { inject, injectable } from "inversify";
import { Gitlab } from "@gitbeaker/node";
import { Gitlab } from "@gitbeaker/rest";
import { GitLab } from "./api";
import { TokenProvider } from "../user/token-provider";

Expand Down Expand Up @@ -36,7 +36,7 @@ export class GitLabAppSupport {
// also cf. https://docs.gitlab.com/ee/api/members.html#valid-access-levels
//
const projectsWithAccess = await api.Projects.all({
min_access_level: "40",
minAccessLevel: 40,
perPage: 100,
});
for (const project of projectsWithAccess) {
Expand Down
2 changes: 1 addition & 1 deletion components/server/src/gitlab/gitlab-auth-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class GitLabAuthProvider extends GenericAuthProvider {
host: this.baseURL,
});
const getCurrentUser = async () => {
const response = await api.Users.current();
const response = await api.Users.showCurrentUser();
return response as unknown as GitLab.User;
};
const unconfirmedUserMessage = "Please confirm your GitLab account and try again.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ class TestGitlabContextParser {
chai.assert.fail();
} catch (e) {
if (GitLab.ApiError.is(e)) {
expect(e.httpError?.description).equals("404 Commit Not Found");
expect(e.code).equals(404);
} else {
chai.assert.fail("Unknown Error: " + JSON.stringify(e));
}
Expand Down
4 changes: 2 additions & 2 deletions components/server/src/gitlab/gitlab-context-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export class GitlabContextParser extends AbstractContextParser implements IConte
}

const result = await this.gitlabApi.run<GitLab.TreeObject[]>(user, async (g) => {
return g.Repositories.tree(`${owner}/${repoName}`, {
return g.Repositories.allRepositoryTrees(`${owner}/${repoName}`, {
ref: branchOrTag.name,
path: path.dirname(branchOrTag.fullPath),
});
Expand Down Expand Up @@ -421,7 +421,7 @@ export class GitlabContextParser extends AbstractContextParser implements IConte
): Promise<IssueContext> {
const ctxPromise = this.handleDefaultContext(user, host, owner, repoName);
const result = await this.gitlabApi.run<GitLab.Issue>(user, async (g) => {
return g.Issues.show(`${owner}/${repoName}`, nr);
return g.Issues.show(nr, { projectId: `${owner}/${repoName}` });
});
if (GitLab.ApiError.is(result)) {
throw await NotFoundError.create(await this.tokenHelper.getCurrentToken(user), user, host, owner, repoName);
Expand Down
5 changes: 2 additions & 3 deletions components/server/src/gitlab/gitlab-file-provider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,8 @@ class TestFileProvider {
const project = await api.run<GitLab.Project>(this.user, (g) =>
g.Projects.create({
name: `test_project_${i}`,
path: `test_project_${i}`,
namespace_id: 57982169,
initialize_with_readme: true,
namespaceId: 57982169,
initializeWithReadme: true,
description: "generated project to test pagination",
}),
);
Expand Down
4 changes: 2 additions & 2 deletions components/server/src/gitlab/gitlab-repository-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ export class GitlabRepositoryProvider implements RepositoryProvider {
const projectId = `${owner}/${repo}`;
const result = await this.gitlab.run<GitLab.Commit[]>(user, async (g) => {
return g.Commits.all(projectId, {
ref_name: ref,
per_page: maxDepth,
refName: ref,
perPage: maxDepth,
page: 1,
});
});
Expand Down
3 changes: 1 addition & 2 deletions components/ws-manager-bridge/leeway.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ COPY components-ws-manager-bridge--app /installer/
WORKDIR /app
RUN /installer/install.sh

# NodeJS v16.19
FROM cgr.dev/chainguard/node@sha256:95bb4763acb8e9702c956e093932be97ab118db410a0619bb3fdd334c9198006
FROM cgr.dev/chainguard/node:18.17.1@sha256:fbaecf4d6ac9883699078c0b501aad22c866f9ce039d009212c0eed260914875
ENV NODE_OPTIONS=--unhandled-rejections=warn
EXPOSE 3000
COPY --from=builder --chown=node:node /app /app/
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
"workspaces": {
"packages": [
"components/*",
"components/ee/*",
"components/*/typescript",
"components/*/typescript-*",
"components/supervisor/frontend",
"charts/"
"components/supervisor/frontend"
]
}
}
Loading