предисловие
В предыдущем блоге базовый пакет API GitLab был проведен через яйцо. Эта статья введет проект проекта (Back-End-End-End) вокруг процесса DevOps, который требует, чтобы читатели имели определенный резерв знаний.
Эта серия представляет собой учебное пособие по проектам непрерывной доставки, которое также можно использовать в качестве руководства по разработке узлов, полного набора проектов DevOps от разработки-тестирования-сборки-развертывания.
Включает в себя следующие 2 серии всего, которые разделены на два модуля: передний и задний
внутренний модуль
- DevOps — использование Gitlab Api (завершено, нажмите, чтобы перейти)
- DevOps — создание базовой платформы DevOps (выполнено на 30 %).
- DevOps — сборка конвейера Gitlab CI
- DevOps — Jenkins Pipeline Builds
- DevOps — использование Docker
- DevOps — проектирование задач по выпуску
- DevOps — проверка кода застряла
- DevOps — мониторинг качества обслуживания узлов
Интерфейсный модуль
- DevOps — основные шаблоны H5
- DevOps — разработка React-проектов
Вышеуказанная серия может быть скорректирована позже в соответствии с фактическим ходом разработки проекта DevOps.
DevOps-дизайн
Кратко проанализируйте структуру процесса разработки данного проекта, а затем выполните следующие шаги (Сценарий написан, вам решать, как его сыграть.)
Анализ требований проекта (цель и результат разработки системы)
- От разработки проекта до тестирования сборки и развертывания полный набор процессов,Упростить стоимость доставки
- Входит в процесс НИОКРконцепция энергоэффективности(время НИОКР-тестирование-общее время доставки-количество ошибок и время ремонта), в качестве справочного стандарта для повышения эффективности проекта (слишком много влияющих факторов, только для справки)
- Разумные баллы тестовой карты, уменьшение недействительного теста, снижение тестовой нагрузки, улучшениеКачество замкнутого цикла процесса
- Обеспечьте онлайн-мониторинг, проанализируйте скорость использования и частоту ошибок каждой версии, улучшитеКачество НИОКР проекта
- Обеспечивает функцию быстрого отката указанной версии, чтобы гарантировать, что новая версия может быть аварийно завершена.быстрое восстановлениеСлужить
Данный проект разрабатывается с нуля.Перед формальной разработкой необходимо уточнить требования, чтобы избежать серьезных недочетов в конструкции и вызвать трудности при дальнейшей разработке или расширении(Дорога может идти медленно, но не сбивайтесь с пути).
Разработка процесса
Как показано на рисунке выше, процесс выпуска предыдущей статьи можно дополнительно уточнить по следующим четырем категориям:
- Процесс выпуска единого проекта (для выполнения одного требования требуется только один проект)
- Если есть проблема в производственной среде, функция быстрого отката
- Интегрированный процесс выпуска проекта (требование может включать несколько проектов, участвующих в разработке и выпуске)
- Процесс выпуска исправления ошибок (нет спроса, необходимо быстро исправить известные, но не срочные исправления ошибок в режиме онлайн)
Дизайн потока задач на самом деле очень сложен.Чтобы ускорить доставку первой версии, поток задач сначала закрепляется за вышеуказанными четырьмя категориями, чтобы уменьшить объем разработки, и будет добавлен или изменен определенный процесс. позже.
Дизайн базы данных
Использование продолжения
sequenceize предоставляет инструмент sequenceize-cli для реализации миграций, мы также можем добавить sequenceize-cli в проект egg (подробности см.продолжение операции).
Если вы ссылаетесь на предыдущий блог, вы уже настроили среду, вы можете использоватьnpm install --save-dev sequelize-cli
Установите инструмент sequenceize-cli, а затем используйте следующую конфигурацию для создания необходимых таблиц.
use strict';
const path = require('path');
module.exports = {
config: path.join(__dirname, 'database/config.json'),
'migrations-path': path.join(__dirname, 'database/migrations'),
'seeders-path': path.join(__dirname, 'database/seeders'),
'models-path': path.join(__dirname, 'app/model'),
};
Выше приведена конфигурация .sequelizerc, поместите ее в корневой каталог проекта.
npx sequelize init:config
npx sequelize init:migrations
После выполнения будут сгенерированы файл database/config.json и каталог database/migrations.Измените содержимое в database/config.json и измените его на конфигурацию базы данных, используемую в проекте:
{
"development": { // 本地数据库,其他环境数据库,照着例子自己改
"username": "root",
"password": "123456",
"database": "devops_dev",
"host": "127.0.0.1",
"dialect": "mysql"
},
}
пройти сноваnpx sequelize migration:generate --name=init-users
для создания таблиц базы данных
module.exports = { // 为了减少工作量,权限我们直接使用 gitlab 的,所以我们只需要落库以下字段
up: async (queryInterface, Sequelize) => {
const { INTEGER, DATE, STRING } = Sequelize;
await queryInterface.createTable('users', {
id: { type: INTEGER, primaryKey: true, },
name: STRING(30),
username: STRING(30),
email: STRING(100),
avatar_url: STRING(200),
web_url: STRING(200),
created_at: DATE,
updated_at: DATE,
});
},
down: async queryInterface => {
await queryInterface.dropTable('users');
},
};
Наконец, выполните миграцию, чтобы внести изменения в базу данных.
# 升级数据库
npx sequelize db:migrate
# 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
# npx sequelize db:migrate:undo
# 可以通过 `db:migrate:undo:all` 回退到初始状态
# npx sequelize db:migrate:undo:all
Таблица основ проектирования
Сохраните данные, обычно используемые проектом и ответвлением gitlab, в локальную базу данных, а затем добавьте поля в соответствии с требованиями проекта.Примерная структура таблицы показана на рисунке выше.
В сочетании с приведенным выше дизайном процесса проекта объясните взаимосвязь структуры таблицы.
- Проект таблицы проекта будет управлять несколькими ветвями, и вы можете запросить статус всех ветвей в рамках текущего проекта (независимо от того, предлагается ли он или нет, существует ли он в процессе)
- Создайте процесс (эквивалентный требованиям), связанный с разработкой нескольких ветвей
- После создания процесса необходимо выполнить все шаги до конца (Dev-Test-Prerelease-Production)
- Когда ветвь связана с процессом, она одновременнозапирание, больше не будет добавляться в другие процессы (Требование блокировки и изоляции, чтобы гарантировать отсутствие вмешательства в процесс разработки)
- На этапе тестирования процесса можно выполнить несколько тестов для разных ветвей (сложные требования проходят черезТестируйте партиями, достичь ожидаемой цели)
- Когда состояние всех ветвей в процессе прошло тест, состояние процесса перейдет на следующий этап, в противном случае оно останется на этапе тестирования.
Таблица тестовых записей не выставлена.На данный момент вышеперечисленные функции были сначала разработаны, а затем модифицированы в сочетании с последующим управлением филиалом.
DevOps-разработка
Добавить глобальный возвращаемый параметр интерфейса
import { Controller } from "egg";
export default class BaseController extends Controller {
get user() {
return this.ctx.user;
}
success(data) {
this.ctx.body = {
code: 0,
data,
};
}
error({ code, data, message }) {
// 根据业务返回不同的错误 code,提供给前端做业务判断处理
this.ctx.body = {
code,
data,
message,
};
}
}
Определите базовый класс глобального возвращаемого параметра, бизнес-контроллер наследует базовый класс, а внешний интерфейс может делать бизнес-оценки на основе возвращаемого значения кода.
Проверка разрешений JWT
В предыдущей статье был представлен метод получения access_token от Gitlab для работы открытого API, но нам все равно нужно хранить информацию о пользователе из локальной базы данных, что нам удобно использовать в дальнейшем
Проверка разрешения проекта, используйте простой jwt, сохраните данные пользователя и access_token, а затем улучшите после выполнения цели первого этапа
Для конкретного использования egg-jwt, пожалуйста, обратитесь к (яйцо-jwt использование), код на стороне бизнеса напрямую прикреплен здесь для справки:
const excludeUrl = ["/user/getUserToken"]; // 请求白名单,过滤不需要校验的请求路径
export default () => {
const jwtAuth = async (ctx, next) => {
if (excludeUrl.includes(ctx.request.url)) {
return await next();
}
const token = ctx.request.header.authorization;
if (token) {
try {
// 解码token
const deCode = ctx.app.jwt.verify(
token.replace("Bearer ", ""), // jwt 中间件验证的时候,需要去掉 Bearer
ctx.app.config.jwt.secret
);
ctx.user = deCode;
await next();
} catch (error) {
ctx.status = 401;
ctx.body = {
code: 401,
message: error.message,
};
}
return;
}
ctx.status = 401;
ctx.body = {
code: 401,
message: "验证失败",
};
return;
};
return jwtAuth;
};
Вышеупомянутый глобальный перехват промежуточного программного обеспечения разрешений jwt.После проверки разрешения данные пользователя сохраняются в ctx для последующих вызовов бизнес-стороны. Конкретное использование промежуточного программного обеспечения может относиться кпромежуточное ПО EGG
// Controller
import { Post, Prefix } from "egg-shell-decorators";
import BaseController from "./base";
@Prefix("user")
export default class UserController extends BaseController {
@Post("/getUserToken")
public async getUserToken({
request: {
body: { params },
},
}) {
const { ctx, app } = this;
const { username, password } = params;
// gitlab 获取 access_token
const userToken = await ctx.service.user.getUserToken({
username,
password,
});
// gitlab 获取用户信息
const userInfo = await ctx.service.user.getUserInfo({
accessToken: userToken.access_token,
});
// 用户数据本地落库
ctx.service.user.saveUser({
userInfo,
});
// 将用户信息及 token 使用 jwt 注册
const token = app.jwt.sign(
{
userToken,
userInfo,
},
app.config.jwt.secret
);
ctx.set({ authorization: token }); // 设置 headers
this.success(userInfo);
}
}
// Service
import { Service } from "egg";
export default class User extends Service {
// 使用 gitlab api 获取 access_token
public async getUserToken({ username, password }) {
const { data: token } = await this.ctx.helper.utils.http.post(
"/oauth/token",
{
grant_type: "password",
username,
password,
}
);
if (token && token.access_token) {
return token;
}
return false;
}
// 使用 gitlab api 获取 gitlab 用户信息
public async getUserInfo({ accessToken }) {
const userInfo = await this.ctx.helper.api.gitlab.user.getUserInfo({
accessToken,
});
return userInfo;
}
// 用户信息落库
public async saveUser({ userInfo }) {
const { ctx } = this;
const {
id,
name,
username,
email,
avatar_url: avatarUrl,
web_url: webUrl,
} = userInfo;
// 查询用户是否已经落库
const exist = await ctx.model.User.findOne({
where: {
id,
},
raw: true,
});
if (exist) return;
// 创建用户信息
ctx.model.User.create({
id,
name,
username,
email,
avatarUrl,
webUrl,
});
}
}
Вышеприведенный пример использования jwt на стороне сервера.При перехвате глобального промежуточного ПО нужная информация может быть проанализирована для последующего использования.Для примера на стороне клиента мы объясним это отдельно в проекте реакции.
Вышеприведенный пример и введение в создание таблицы базы данных и операции с пользователями и разрешениями.Следующая статья в этой серии и другие основные потоки задач будут запущены после разработки.Ожидается, что это займет около 2 недель.
конец
Этот проект разработан с нуля. Последующая серия блогов будет запущена в соответствии с фактическим прогрессом разработки. После завершения проекта часть исходного кода будет открыта для вашего ознакомления.
Если у вас есть какие-либо вопросы или идеи по содержанию статьи, вы можете добавить WeChat Cookieboty для общения.
Также обратите внимание на официальный аккаунт Cookieboty1024, добро пожаловать в лагерь роста фронтовика
Ручная собака городской дом