likes
comments
collection
share

从 0 到 1 node 项目管理系统: Gitlab Api

作者站长头像
站长
· 阅读数 49

前言

DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

它是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。

此系列即是持续交付项目的教程亦可作为 node 开发的教程来使用。

阅读准备

本系列需要读者具备一定的 node 以及部分运维、项目管理流程的基础,然后配合食用效果更佳。

环境准备

开发 使用技术 Or 工具
后台开发框架 Egg
前端管理界面开发语言 React + Ant Design
数据库 Mysql
构建工具 Jenkins && GitLab CI
项目管理仓库 GitLab
应用容器 Docker

项目介绍

从 0 到 1 node 项目管理系统: Gitlab Api

本系列会围绕通用项目管理流程(上图简单概括了此项目流程),从开发-测试-构建-部署的一整套 DevOps 项目

一共包含如下 2 个系列,分为前后端两个模块

后端模块

  1. 前端构建 - Gitlab Api使用(已完成)
  2. DevOps - 搭建 Gitlab 基础平台
  3. DevOps - Gitlab CI 流水线构建
  4. DevOps - Jenkins 流水线构建
  5. DevOps - Docker 使用
  6. DevOps - 发布任务流程设计
  7. DevOps - 代码审查卡点
  8. DevOps - Node 服务质量监控

前端模块

  1. DevOps - H5 基础脚手架
  2. DevOps - React 项目开发

后期可能会根据 DevOps 项目的实际开发进度对上述系列进行调整

基础开发环境搭建准备

Gitlab 安装

本项目的开发依赖 Gitlab,所以在进行开发之前,请参考 Gitlab 安装步骤

搭建 Egg 项目

从 0 到 1 node 项目管理系统: Gitlab Api

我们选择基础的 ts egg 版本进行开发,前置工作我们就不详细解释,有需求可以参考 Egg 教程

这里介绍两个插件可以方便我们项目开发使用(egg-helper,egg-shell-decorators)

一个是方便我们写 helper 基础的 utility 函数,一个是可以使用装饰器,方便我们管理路由。

数据库选择

数据库我们使用常规的 Mysql,具体安装详情可见 Mysql 安装教程,本文就不详细描述。

Mysql 插件,我们使用 Sequelize,下一篇会有详细说明,本篇暂时不需要用到。

Hello World

在 Egg 项目正常安装完依赖之后,传统开发的第一步,跟世界打个招呼!

从 0 到 1 node 项目管理系统: Gitlab Api

Gitlab

简介

GitLab 是一个用于仓库管理系统的开源项目,使用 Git 作为代码管理工具,并在此基础上搭建起来的 web 服务。所以大部分公司都会选择使用 Gitlab 作为私有仓库管理。

认证授权

我们要使用 Gitlab Api 首先要拿到 Gitlab 的认证,才可以获得 Gitlab Api 的操作权限

GitLab Api 授权有如下几种方式:

  1. OAuth2 tokens
  2. Personal access tokens
  3. Project access tokens
  4. Session cookie
  5. GitLab CI/CD job token (Specific endpoints only)

由于我们是第三方使用Gitlab Api 所以我们选择 OAuth2 授权方式

OAuth2 授权有以下三种方式:

  1. Resource owner password credentials flow(客户端用户密码验证授权)
  2. Web application flow(Web应用程序授权)
  3. Implicit grant flow(隐式授权流)

本项目采取简单但安全性具有一定风险的第一种客户端验证授权(最好使用 Web application flow 授权方式)

封装基础 Gitlab Api 工具类

const qs = require("qs");

const baseUrl = "https://gitlab.xxxxxx.com"; // 此处替换为你自己的 gitlab 地址

export default (app) => {
  return {
    async post({url, params = {}, query = {}}) {
      const sendUrl = `${baseUrl}${url}?${qs.stringify(query)}`;
      try {
        const { data, code } = await app.curl(sendUrl, {
          dataType: "json",
          method: "POST",
          data: params,
        });
        return { data, code };
      } catch (error) {
        return error;
      }
    },
    async methodV({ url, method, params = {}, query = {} }) {
      const sendUrl = `${baseUrl}/api/v4${url}?${qs.stringify(query)}`;
      try {
        const { data, code } = await app.curl(sendUrl, {
          dataType: "json",
          method,
          data: params,
        });
        return { data, code };
      } catch (error) {
        return error;
      }
    },
  };
};

上面封装的请求方法有两种,稍微注意一下,Gitlab Api 获取 access_token 的 url 前缀是不带 '/api/v4',而其他的请求是需要带上 '/api/v4', 所以我们多封装了一个 methodV 方法来请求其他的 Api。

// Service User
import { Service } from "egg";

export default class User extends Service {
  public async getUserToken({ username, password }) {
    const { data: token } = await this.ctx.helper.utils.http.post({
      url: "/oauth/token",
      params: {
        grant_type: "password",
        username,
        password,
      },
    });
    if (token && token.access_token) {
      return token;
    }
    return false;
  }
}

// Controller User
import { Controller } from "egg";
import { Post, Prefix } from "egg-shell-decorators";

@Prefix("user")
export default class UserController extends Controller {
  @Post("/getUserToken")
  public async getUserToken() {
    const { ctx } = this;
    const { params } = ctx.body;
    const { username, password } = params;
    const userToken = await ctx.service.user.getUserToken({
      username,
      password,
    });
    ctx.body = userToken;
  }
}

如上,我们直接使用 postman 请求 http://127.0.0.1:7001/user/getUserToken 可以获取到 OAuth2 access_token,然后通过 access_token 调用对应的 open api 即可拿到我们想要的信息。

从 0 到 1 node 项目管理系统: Gitlab Api

封装 Gitlab Api 请求

首先展示一下项目封装 api 的目录结构

从 0 到 1 node 项目管理系统: Gitlab Api

这里之所以会根据 gitlab api 的分类做成工具类是因为在后面的操作过程中,我们会频繁的调用它。

而一般来说 service 层是做数据处理,Controller 层是做业务处理,在实际使用中都会遇到调用 api 的可能。所以我们直接把第三方的调用类都放在 helper 里面,方便我们开发使用

同样,后期的 Jenkins、Gitlab CI 等第三方调用也会封装于此

根据 project api 开始封装第一个经常用使用的项目请求类

import AJAX from "../../utils/http";

module.exports = (app) => {
  const getProjects = async ({ pageSize, pageNum, accessToken }) => {
    const { data: projectList } = await AJAX(app).methodV({
      url: "/projects",
      method: 'GET',
      query: {
        per_page: pageSize,
        page: pageNum,
        access_token: accessToken,
      },
    });
    return { projectList };
  };

  const createProjects = async ({ gitParams }) => {
    const status = await AJAX(app).methodV({
      url: "/projects",
      method: 'POST',
      params: {
        ...gitParams,
      },
    });
    return status;
  };

  const deleteProtectedBranches = async (projectId: number) => {
    const url = `/projects/${projectId}/protected_branches/master`;
    const status = await AJAX(app).methodV({
      url,
      method: 'DELETE',
    });
    return status;
  };

  const protectedBranches = async (projectId: number) => {
    const url = `/projects/${projectId}/protected_branches`;
    const status = await AJAX(app).methodV({
      url,
      method: 'POST',
      params: {
        name: "master",
        push_access_level: 0,
        merge_access_level: 40,
      },
    });
    return status;
  };

  return {
    getProjects,
    createProjects,
    deleteProtectedBranches,
    protectedBranches,
  };
};

业务侧直接调用

// Service
import { Service } from "egg";

export default class Project extends Service {
  public async getProjectList({ pageSize = 100, pageNum = 1, accessToken }) {
    const {
      projectList,
    } = await this.ctx.helper.api.gitlab.project.getProjects({
      pageSize,
      pageNum,
      accessToken,
    });
    return projectList;
  }
}

// Controller
import { Controller } from "egg";
import { Post, Prefix } from "egg-shell-decorators";

@Prefix("project")
export default class ProjectController extends Controller {
  @Post("/getProjectList")
  public async getProjectList() {
    const { ctx } = this;
    const { params } = ctx.body;
    const { pageSize, pageNum, accessToken } = params;
    const projectList = await ctx.service.project.getProjectList({
      pageSize,
      pageNum,
      accessToken,
    });
    ctx.body = projectList;
  }
}
从 0 到 1 node 项目管理系统: Gitlab Api

如图,根据 accessToken 已经可以正常的拿到对应用户的项目信息,同理我们可以封装项目未来会使用到的常用 api,如 branch、merge 等。

尾声

此项目是从零开发,后续此系列博客会根据实际开发进度推出,项目完成之后,会开放部分源码供各位同学参考。

手动狗头镇楼

从 0 到 1 node 项目管理系统: Gitlab Api

转载自:https://juejin.cn/post/6855129008066002958
评论
请登录