Skip to content

Commit

Permalink
Merge pull request #125 from glensc/docker-image-remove-example
Browse files Browse the repository at this point in the history
Add RegistryCleanup demo
  • Loading branch information
glensc committed Feb 21, 2024
2 parents 43594d9 + 7d7f468 commit 5e37607
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 2 deletions.
4 changes: 3 additions & 1 deletion demo/src/demo.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { logger, main } from "gitlab-webhook-listener-bot";
import { logger, main, GitlabClient } from "gitlab-webhook-listener-bot";
import { RenovateRebase } from "./handlers/RenovateRebase";
import { EventLogger } from "./handlers/EventLogger";
import { ProjectCreateEvent } from "./handlers/ProjectCreateEvent";
import { RegistryCleanup } from "./handlers/RegistryCleanup";

main({
logger,
handlers: [
new EventLogger(logger),
new ProjectCreateEvent(logger),
new RenovateRebase(logger),
new RegistryCleanup(new GitlabClient(process.env.GITLAB_URL || "", process.env.GITLAB_TOKEN || ""), logger),
],
async livenessProbe() {
logger.debug("Called livenessProbe");
Expand Down
67 changes: 67 additions & 0 deletions demo/src/handlers/RegistryCleanup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
GitlabClient,
LoggerInterface,
MergeRequestHandler,
MergeRequestPayload,
WebhookEvent,
slugify,
} from "gitlab-webhook-listener-bot";

/**
* Delete docker build images when merge request is closed or merged.
*/
export class RegistryCleanup extends MergeRequestHandler {
public constructor(
private readonly gitlab: GitlabClient,
logger: LoggerInterface,
) {
super(logger);
}

public isValid({ payload }: WebhookEvent<MergeRequestPayload>): boolean {
const {
object_attributes: {
action,
},
} = payload;

return (
["close", "merge"].includes(action)
);
}

public async handle({ payload }: WebhookEvent<MergeRequestPayload>): Promise<void> {
const {
object_attributes: {
iid: mr_id,
title,
action,
source_branch,
},
project: {
id: project_id,
path_with_namespace: project_path,
},
} = payload;

this.logger.info(`Deleting docker images related to the merge request ${source_branch} (action: ${action}): ${project_path}!${mr_id}: ${title}`);

await this.cleanupAutoDevopsImages(project_id, slugify(source_branch));
}

/**
* Delete auto-devops images
*/
private async cleanupAutoDevopsImages(project_id: number, source_branch: string): Promise<void> {
const repository = await this.gitlab.getRegistryRepositoryByName(project_id, source_branch);

this.logger.debug(`Found auto-devops repository: ${JSON.stringify(repository)}`);

if (!repository) {
return;
}

this.logger.info("Deleting repository", repository);
await this.gitlab.removeRegistryRepositoryById(project_id, repository.id);
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"ngrok": "ngrok --config ngrok.yml start app",
"prepublishOnly": "set -e; pnpm install; pnpm build",
"set-version": "pnpm version --new-version $APP_VERSION --no-git-tag-version",
"start": "cd demo; pnpm install; pnpm start"
"start": "set -e; pnpm build; cd demo; pnpm install; pnpm start"
},
"engines": {
"node": ">=18"
Expand Down
28 changes: 28 additions & 0 deletions src/gitlab/GitlabClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Gitlab } from "@gitbeaker/rest";

type ProjectId = string | number;

export class GitlabClient {
protected readonly api: InstanceType<typeof Gitlab<false>>;

Expand All @@ -12,4 +14,30 @@ export class GitlabClient {
token,
});
}

async getRegistryRepositoryByName(projectId: ProjectId, name: string) {
// NOTE: There doesn't appear to be a method that would not involve fetching all repositories
let repositories;

try {
repositories = await this.api.ContainerRegistry.allRepositories({ projectId });
} catch (e: any) {
// forbidden in case feature not enabled
if (e.cause.description === "403 Forbidden") {
return null;
}

throw e;
}

return repositories.filter(repository => repository.name === name)[0];
}

async removeRegistryRepositoryById(projectId: ProjectId, repositoryId: number) {
const code = await this.api.ContainerRegistry.removeRepository(projectId, repositoryId);

if ((code as any as number) !== 202) {
throw new Error(`Unexpected code: ${code}`);
}
}
}

0 comments on commit 5e37607

Please sign in to comment.