From b59f89fb4df44b848a7c802127e88999b1ccfde8 Mon Sep 17 00:00:00 2001 From: Nikolay Kostyurin Date: Wed, 25 Sep 2024 21:13:22 +0200 Subject: [PATCH] feat: add glab-status cli util --- bun.lockb | Bin 137125 -> 158921 bytes package.json | 22 +++++-- src/cli.ts | 47 +++++++++++++++ src/display.ts | 151 +++++++++++++++++++++++++++++++++++++++++++++++++ src/git.ts | 33 +++++++++++ src/gitlab.ts | 102 +++++++++++++++++++++++++++++++++ src/index.ts | 6 +- tsup.config.ts | 16 +++--- 8 files changed, 360 insertions(+), 17 deletions(-) create mode 100644 src/cli.ts create mode 100644 src/display.ts create mode 100644 src/git.ts create mode 100644 src/gitlab.ts diff --git a/bun.lockb b/bun.lockb index 239dfb734814eb3342a2d75cb7e18f7175bdce6c..7096906f122b294b35a4905129e94e894b06d123 100755 GIT binary patch delta 48704 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∓Cyfj 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 delta 42322 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 https://gitlab.com/-/user_settings/personal_access_tokens") + ); + process.exit(1); +} + +try { + const git = new Git(); + const gitlab = new GitLab(process.env.GITLAB_TOKEN); + const myProjects = await gitlab.myProjectsByName(await git.repoName()); + const branch = await git.branch(); + + for (const project of myProjects) { + const pipeline = await project.pipelineBy(branch); + + if (pipeline) { + new Display( + new DisplayCommit(await project.commitBy(pipeline.sha), pipeline), + new DisplayMergeRequest(await project.mergeRequestBy(branch)), + new DisplayEnvironment(await project.environmentsBy(branch)), + new DisplayPipelineJobs(await project.pipelineJobsBy(pipeline.id)) + ); + } else { + console.error("No pipelines found for this project."); + } + } +} catch (error: unknown) { + if (error instanceof Error) { + console.error("Error fetching pipeline status:", error.message); + } + console.error(error); +} diff --git a/src/display.ts b/src/display.ts new file mode 100644 index 0000000..e327a87 --- /dev/null +++ b/src/display.ts @@ -0,0 +1,151 @@ +import colors from "picocolors"; +import { parseISO, formatRelative } from "date-fns"; + +export class Display { + rows: string[] = []; + constructor(...args: unknown[]) { + const rows = args[0]; + + if (rows instanceof Display) { + (args as Display[]).forEach((display) => display.display()); + } else if (Array.isArray(rows)) { + this.rows = rows; + } + } + + display() { + this.rows.forEach((row) => console.log(row)); + } +} + +export class DisplayEnvironment extends Display { + constructor(environment: { external_url: string }) { + super([ + colors.bold("Environment"), + `> ${colors.blue(environment.external_url)}`, + "", + ]); + } +} + +export class DisplayMergeRequest extends Display { + constructor(mr: { + merged_at: string; + state: string; + title: string; + iid: string; + web_url: string; + }) { + const mrid = colors.red(`#${mr.iid}`); + const date = colors.green( + `(${formatRelative(parseISO(mr.merged_at), new Date())})` + ); + const statusEmojis = { + opened: colors.greenBright("✅ Opened"), + closed: colors.redBright("❌ Closed"), + merged: colors.greenBright("✅ Merged"), + } as Record; + + const status = statusEmojis[mr.state] || ""; + + super([ + colors.bold("Merge Request"), + `${mrid} - ${mr.title} - ${status} ${date}`, + `> ${colors.blue(mr.web_url)}`, + "", + ]); + } +} + +export class DisplayCommit extends Display { + static statusEmojis = { + created: colors.whiteBright("⚙️ Created"), + waiting_for_resource: colors.yellowBright("⏳ Waiting for resource"), + preparing: colors.yellowBright("🔄 Preparing"), + pending: colors.yellowBright("💤 Pending"), + running: colors.whiteBright("🚀 Running"), + success: colors.greenBright("✅ Success"), + failed: colors.redBright("❌ Failed"), + canceled: colors.redBright("🛑 Canceled"), + skipped: colors.yellowBright("⏭️ Skipped"), + manual: colors.blueBright("👤 Manual"), + scheduled: colors.blueBright("📅 Scheduled"), + } as Record; + + constructor( + commit: { + created_at: string; + short_id: string; + title: string; + author_name: string; + }, + pipeline: { status: string; web_url: string } + ) { + const sha = colors.red(`${commit.short_id}`); + const author = colors.blueBright(`<${commit.author_name}>`); + const date = colors.green( + `(${formatRelative(parseISO(commit.created_at), new Date())})` + ); + const title = colors.whiteBright(commit.title); + + super([ + colors.bold("Commit"), + `${sha} - ${title} ${date} ${author} - ${ + DisplayCommit.statusEmojis[pipeline.status] + }`, + `> ${colors.blue(pipeline.web_url)}`, + "", + ]); + } +} + +type PipelineJob = { + status: string; + stage: string; + duration: number; + name: string; +}; + +export class DisplayPipelineJobs extends Display { + static statusMap = { + success: "🟢", + failed: "🔴", + canceled: "🟠", + skipped: "🟡", + pending: "🟣", + running: "🔵", + created: "⚪", + } as Record; + + constructor(pipelineJobs: PipelineJob[] = []) { + const stages = pipelineJobs + .filter((item) => item.status !== "manual") + .reduce((acc, item) => { + const items = (acc[item.stage] = acc[item.stage] || []); + items.push(item); + return acc; + }, {} as Record); + + super( + Object.entries(stages) + .map(([stage, stages]) => { + return [ + colors.bold(stage), + stages + .map((stage) => { + const secs = colors.gray(`(${Math.round(stage.duration)}s)`); + const status = + DisplayPipelineJobs.statusMap[stage.status] || + stage.status || + ""; + + return String(`${status} ${stage.name} ${secs}`).trim(); + }) + .join(" "), + "", + ].flat(); + }) + .flat() + ); + } +} diff --git a/src/git.ts b/src/git.ts new file mode 100644 index 0000000..25652e8 --- /dev/null +++ b/src/git.ts @@ -0,0 +1,33 @@ +import { $ } from "bun"; + +export class Git { + cwd: string; + + constructor(cwd = process.cwd()) { + this.cwd = cwd; + } + + async branch() { + const stdout = await $`git rev-parse --abbrev-ref HEAD` + .cwd(this.cwd) + .text(); + + return stdout.trim(); + } + + async remoteUrl() { + const stdout = await $`git ls-remote --get-url`.cwd(this.cwd).text(); + + return stdout + .trim() + .replace(/^git@(.*?):/, "https://$1/") + .replace(/[A-z0-9\-]+@/, "") + .replace(/\.git$/, ""); + } + + async repoName() { + const projectName = (remoteUrl: string) => remoteUrl.split("/").pop(); + + return projectName(await this.remoteUrl()); + } +} diff --git a/src/gitlab.ts b/src/gitlab.ts new file mode 100644 index 0000000..a0d9303 --- /dev/null +++ b/src/gitlab.ts @@ -0,0 +1,102 @@ +export class GitlabProject { + GITLAB_API_PIPELINES_URL = `/projects/:id/pipelines`; + GITLAB_API_PIPELINE_JOBS_URL = `/projects/:id/pipelines/:pipeline_id/jobs`; + GITLAB_API_COMMIT_URL = `/projects/:id/repository/commits/:sha`; + GITLAB_API_PROJECT_MRS_URL = `/projects/:id/merge_requests`; + GITLAB_API_ENVS_URL = `/projects/:id/environments`; + + constructor(gitlab, projectId) { + this.gitlab = gitlab; + this.projectId = projectId; + } + + async commitBy(sha) { + return this.gitlab._get( + this.GITLAB_API_COMMIT_URL.replace(":id", this.projectId).replace( + ":sha", + sha + ) + ); + } + + async pipelineBy(branch) { + return this.gitlab + ._get(this.GITLAB_API_PIPELINES_URL.replace(":id", this.projectId), { + ref: branch, + per_page: 1, + }) + .then((pipelines) => pipelines[0]); + } + + async mergeRequestBy(branch) { + return this.gitlab + ._get(this.GITLAB_API_PROJECT_MRS_URL.replace(":id", this.projectId), { + source_branch: branch, + }) + .then((mrs) => mrs[0]); + } + + async environmentsBy(branch) { + return this.gitlab + ._get(this.GITLAB_API_ENVS_URL.replace(":id", this.projectId), { + search: branch, + }) + .then((envs) => envs[0]); + } + + async pipelineJobsBy(pipelineId) { + return this.gitlab._get( + this.GITLAB_API_PIPELINE_JOBS_URL.replace(":id", this.projectId).replace( + ":pipeline_id", + pipelineId + ) + ); + } +} + +export class GitLab { + BASE_URL = "https://gitlab.com/api/v4"; + GITLAB_API_PROJECTS_URL = `/projects`; + + constructor(token) { + this.token = token; + } + + async _get(url, params = {}) { + return fetch( + `${this.BASE_URL}${url}?${new URLSearchParams(params).toString()}`, + { + headers: { "Private-Token": this.token }, + params, + } + ).then((res) => res.json()); + } + + async projectsByName(name) { + return this._get(this.GITLAB_API_PROJECTS_URL, { + search: name, + per_page: 100, + }).then((projects) => + projects.map((item) => ({ + id: item.id, + name: item.name, + ssh_url_to_repo: item.ssh_url_to_repo, + http_url_to_repo: item.http_url_to_repo, + web_url: item.web_url, + })) + ); + } + + async myProjectsByName(name) { + const filterProjects = (projects, name) => + projects.filter( + (project) => + project.ssh_url_to_repo.includes(name) || + project.http_url_to_repo.includes(name) + ); + + return filterProjects(await this.projectsByName(name), name).map( + (project) => new GitlabProject(this, project.id) + ); + } +} diff --git a/src/index.ts b/src/index.ts index 2ce5fee..9862934 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ -export default function hello() { - return 'world' -} +export * from "./display"; +export * from "./git"; +export * from "./gitlab"; diff --git a/tsup.config.ts b/tsup.config.ts index aa3d29d..138e1d3 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,19 +1,19 @@ -import { defineConfig } from 'tsup' +import { defineConfig } from "tsup"; export default defineConfig(() => ({ - entry: ['src/index.ts'], - format: ['cjs', 'esm'], + entry: ["src/index.ts", "src/cli.ts"], + format: ["cjs", "esm"], external: [], splitting: false, clean: true, cjsInterop: true, dts: true, - target: ['node18'], + target: ["node18"], shims: true, - tsconfig: './tsconfig.json', + tsconfig: "./tsconfig.json", outExtension({ format }) { return { - js: format === 'cjs' ? '.cjs' : format === 'esm' ? `.mjs` : '.js', - } + js: format === "cjs" ? ".cjs" : format === "esm" ? `.mjs` : ".js", + }; }, -})); \ No newline at end of file +}));