Skip to content
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

[gitlab] get rid of UnhandledPromiseRejectionWarning #10148

Merged
merged 1 commit into from
Jun 8, 2022
Merged
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
84 changes: 46 additions & 38 deletions components/server/ee/src/prebuilds/gitlab-app.ts
Original file line number Diff line number Diff line change
@@ -32,49 +32,55 @@ export class GitLabApp {

@postConstruct()
protected init() {
/**
* see https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#configure-your-webhook-receiver-endpoint
Copy link
Member

Choose a reason for hiding this comment

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

🧡

* for recommendation on creating webhook receivers:
*
* - ignore unrecognized event payloads
* - never return 500 status responses if the event has been handled
* - prefer to return 200; indicate that the webhook is asynchronous by returning 201
* - to support fast response times, perform I/O or computationally intensive operations asynchronously
*/
this._router.post("/", async (req, res) => {
const event = req.header("X-Gitlab-Event");
if (event === "Push Hook") {
const context = req.body as GitLabPushHook;
const span = TraceContext.startSpan("GitLapApp.handleEvent", {});
span.setTag("request", context);
log.debug("GitLab push hook received", { event, context });
let user: User | undefined;
try {
user = await this.findUser({ span }, context, req);
} catch (error) {
TraceContext.setError({ span }, error);
log.error("Cannot find user.", error, {});
}
if (!user) {
res.statusCode = 503;
res.send();
span.finish();
return;
}
try {
await this.handlePushHook({ span }, context, user);
} catch (err) {
TraceContext.setError({ span }, err);
throw err;
} finally {
span.finish();
}
} else {
log.debug("Unknown GitLab event received", { event });
const secretToken = req.header("X-Gitlab-Token");
const context = req.body as GitLabPushHook;
if (event !== "Push Hook" || !secretToken) {
log.warn("Unhandled GitLab event.", { event, secretToken: !!secretToken });
res.status(200).send("Unhandled event.");
return;
}
res.send("OK");

const span = TraceContext.startSpan("GitLapApp.handleEvent", {});
span.setTag("request", context);
log.debug("GitLab push event received.", { event, context });
let user: User | undefined;
try {
user = await this.findUser({ span }, context, secretToken);
} catch (error) {
log.error("Cannot find user.", error, { context });
TraceContext.setError({ span }, error);
}
if (!user) {
// If the webhook installer is no longer found in Gitpod's DB
// we should send a UNAUTHORIZED signal.
span.finish();
res.status(401).send("Unauthorized.");
return;
}
/** no await */ this.handlePushHook({ span }, context, user).catch((error) => {
console.error(`Couldn't handle request.`, error, { headers: req.headers });
TraceContext.setError({ span }, error);
});

span.finish();
res.status(201).send("Prebuild request handled.");
Copy link
Member Author

Choose a reason for hiding this comment

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

BTW, this actually can be used to check the handling of the event on GitLab's side. quite handy!

the 201 is to signal the async handling on Gitpod's side.

});
}

protected async findUser(ctx: TraceContext, context: GitLabPushHook, req: express.Request): Promise<User> {
protected async findUser(ctx: TraceContext, context: GitLabPushHook, secretToken: string): Promise<User> {
const span = TraceContext.startSpan("GitLapApp.findUser", ctx);
try {
const secretToken = req.header("X-Gitlab-Token");
span.setTag("secret-token", secretToken);
if (!secretToken) {
throw new Error("No secretToken provided.");
}
const [userid, tokenValue] = secretToken.split("|");
const user = await this.userDB.findUserById(userid);
if (!user) {
@@ -119,9 +125,11 @@ export class GitLabApp {
const projectAndOwner = await this.findProjectAndOwner(context.repository.cloneUrl, user);
if (projectAndOwner.project) {
/* tslint:disable-next-line */
/** no await */ this.projectDB.updateProjectUsage(projectAndOwner.project.id, {
lastWebhookReceived: new Date().toISOString(),
});
/** no await */ this.projectDB
.updateProjectUsage(projectAndOwner.project.id, {
lastWebhookReceived: new Date().toISOString(),
})
.catch((e) => log.error(e));
}

const config = await this.prebuildManager.fetchConfig({ span }, user, context);