preface

DevOps (a combination of Development and Operations) is a collection of processes, methods, and systems used to facilitate communication, collaboration, and integration among Development (application/software engineering), technical Operations, and quality assurance (QA) departments.

IT is a culture, movement, or practice that values communication and collaboration between software developers (Dev) and IT operations technicians (Ops). Build, test, and release software faster, more frequently, and more reliably by automating the software delivery and architecture change processes.

This series can be used as a continuous delivery project tutorial or as a Node development tutorial.

Reading readiness

This series requires the reader to have some basic knowledge of Node and part of the operation and maintenance, project management process, and then to eat better.

Environment to prepare

The development of Use technology Or tools
Background development framework Egg
Front-end management interface development language React + Ant Design
The database Mysql
Build tools Jenkins && GitLab CI
Project management warehouse GitLab
Application of the container Docker

Project introduction


This series will cover a complete set of DevOps projects, from development to test to build to deploy, around a common project management process (which is briefly summarized in the figure above)

It consists of the following two series: front and rear modules

The backend module

  1. Front-end build – Gitlab Api usage (completed)
  2. DevOps – Build Gitlab base platform
  3. DevOps – Gitlab CI pipeline construction
  4. Devops-jenkins pipelined construction
  5. Devops-docker use
  6. DevOps – Release task flow design
  7. DevOps – Code review points
  8. Devops-node monitors service quality

The front-end module

  1. DevOps – H5 base scaffolding
  2. Devops-react project development

The above series may be adjusted later based on the actual development progress of the DevOps project

Preparation of basic development environment

Gitlab installation

The development of this project depends on Gitlab, so please refer to the Gitlab installation steps before proceeding with development.

Build the Egg Project


We choose the basic TS Egg version for development, we will not explain the pre-work in detail, if you need to refer to the egg tutorial

Here are two plug-ins that we can use for our projects (egg-helper and egg-shell-decorators)

One is to write utility functions based on helper, and the other is to use decorators to manage routes.

Database selection

Database we use regular Mysql, specific installation details can be seen in Mysql installation tutorial, this article will not describe in detail.

Mysql plugin, we use Sequelize, which will be explained in the next article, but we don’t need to use it in this article.

Hello World

After the normal installation of the Egg project dependencies, the first step in traditional development, say hello to the world!


Gitlab

Introduction to the

GitLab is an open source project for warehouse management system. It uses Git as a code management tool and builds web services based on it. So most companies choose to use Gitlab for private warehouse management.

Certificate authority

If we want to use Gitlab Api, we must first get the certification of Gitlab, and then we can get the operation permission of Gitlab Api

The GitLab Api is licensed in the following ways:

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

Since we are a third party using Gitlab Api, we choose OAuth2 authorization mode

OAuth2 authorization is available in the following three ways:

  1. Resource Owner Password Credentials Flow (Authentication and authorization for client user passwords)
  2. Web Application Flow (Web Application Authorization)
  3. Implicit Grant Flow

This project adopts the first client authentication authorization, which is simple but has certain security risks (Web Application Flow authorization is best).

Encapsulate the base Gitlab Api utility classes

const qs = require("qs");

const baseUrl = "https://gitlab.xxxxxx.com"; // Replace this with your own Gitlab address

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;  }  },  }; }; Copy the code

Gitlab Api gets access_token url without ‘/ Api /v4’, other requests require ‘/ Api /v4’. So we’ve wrapped a methodV method to call another 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;  } } Copy the code

As above, we use http://127.0.0.1:7001/user/getUserToken postman request can get directly to the OAuth2 access_token, We then call the corresponding Open API via access_token to get the information we want.


Encapsulate the Gitlab Api request

Start by showing the directory structure of the project encapsulation API


The reason why the utility class is classified according to the GitLab API is because we will call it frequently during the operation.

Generally speaking, the Service layer is for data processing, and the Controller layer is for business processing, so it is possible to call API in actual use. Therefore, we directly put the third party call classes in helper, which is convenient for our development and use

Similarly, later Jenkins, Gitlab CI and other third-party calls will also be encapsulated in this

Start encapsulating the first frequently used project request class from the 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,  }; }; Copy the code

Directly invoked on the business side

// 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;  } } Copy the code

As shown in the figure, according to accessToken, project information of corresponding users can be normally obtained. Similarly, we can encapsulate common apis that will be used in the project in the future, such as Branch, Merge, etc.

The end of the

This project is developed from zero, the subsequent series of blogs will be launched according to the actual development progress, after the completion of the project, part of the source code will be open for your reference.

Manual doghead town building