blog

0ノードから1ノードまでのプロジェクト管理システム:Gitlab Api

DevOpsとは、開発、技術運用、品質保証部門間のコミュニケーション、コラボレーション、統合を促進するために使用される一連のプロセス、手法、システムの総称です。 ソフトウェア開発者」と「IT運用技術者...

Jan 3, 2021 · 7 min. read
シェア

はじめに

DevOpsとは、開発、技術運用、品質保証部門間のコミュニケーション、コラボレーション、統合を促進する一連のプロセス、手法、システムの総称です。

ソフトウェア開発者」と「IT運用技術者」の間のコミュニケーションとコラボレーションを重視する文化、運動、または実践です。ソフトウェアデリバリとアーキテクチャ変更のプロセスを自動化することで、ソフトウェアの構築、テスト、リリースをより速く、より頻繁に、より信頼できるものにします。

継続的デリバリープロジェクトのためのこの一連のチュートリアルは、ノード開発のためのチュートリアルとしても使用できます。

読むための準備

このシリーズは、読者がいくつかのノードを持っている必要があり、運用と保守の一部、基礎のプロジェクト管理プロセス、およびその後、より良い結果の消費と。

環境の準備

プロジェクトの紹介

このシリーズでは、開発-テスト-ビルド-デプロイからDevOpsプロジェクト一式まで、一般的なプロジェクト管理プロセスに焦点を当てます。

2つのシリーズがあり、フロントエンドとバックエンドのモジュールに分かれています。

バックエンドモジュール

フロントエンドモジュール

  1. DevOps - H5 Foundation Scaffolding
  2. DevOps - React プロジェクト開発

上記のシリーズは、DevOpsプロジェクトの実際の開発進捗に応じて、後日調整される可能性があります。

基本的な開発環境の準備

Gitlab

Eggプロジェクトのビルド

プロジェクト開発に簡単に使えるプラグインを2つ紹介します。

ひとつはヘルパー・ベース用のユーティリティ関数を簡単に書けるようにすること、もうひとつはデコレーターを使ってルートの管理を簡単にできるようにすることです。

データベース選択

データベースは従来のMysqlを使用し、具体的なインストールの詳細は Mysql インストールチュートリアル記載されています。

OAuth2 tokens使用するMysqlプラグインについては、次の記事で詳しく説明します。

Hello World

Eggプロジェクトが依存関係を適切にインストールした後、伝統的な開発の最初のステップは世界に挨拶することです!

Gitlab

はじめに

GitLabは、コード管理ツールとしてGitを使い、その上にウェブサービスを構築した倉庫管理システムのオープンソースプロジェクトです。そのため、ほとんどの企業はプライベートリポジトリ管理として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

Gitlab Apiはサードパーティによって利用されているため、OAuth2認証方式が選択されています。

OAuth2の認証には3つの方法があります:

  1. Resource owner password credentials flow
  2. Web application flow
  3. Implicit grant flow

このプロジェクトでは、シンプルでありながらセキュリティリスクが高い第一クライアント認証を採用しています。

Gitlabの基本的なApiツールキットのパッケージ化

const qs = require("qs");
const baseUrl = "https://..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;
 }
 },
 };
};

上記には二つのリクエストメソッドがカプセル化されています。 他のリクエストには '/api/v4'が必要ですが、access_token の Gitlab Api URL には '/api/v4'がつかないことに注意しましょう

// 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:7100"/user/getUserTokenをリクエストしてOAuth2のaccess_tokenを取得し、access_token経由で対応するopen apiを呼び出して欲しい情報を取得することができます。

Gitlab Api Requestsのパッケージ化

まず、プロジェクトのパッケージ化されたapiのディレクトリ構造を示します。

なぜこれを gitlab api の分類に基づいたツールクラスとしたかというと、この後の作業でこのクラスを何度も呼び出すことになるからです。

一般的に、サービスレイヤーはデータ処理、コントローラレイヤーは業務処理を行うレイヤーであり、実際の利用ではapiを呼び出す可能性が出てきます。そこで、サードパーティを呼び出すクラスはすべてヘルパーに直接入れるようにしました。

同様に、JenkinsやGitlab CIなどのサードパーティの呼び出しは、このようにラップされます。

プロジェクト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;
 }
}

図のように、accessTokenによって、対応するユーザーのプロジェクト情報を普通に取得することができます。同様に、ブランチやマージなど、プロジェクトが今後使用する共通のAPIをカプセル化することができます。

エピローグ

マニュアル犬頭町役場

Read next

No articles found.

No articles found.