предисловие
Базовая конструкция платформы, часть 1Представьте дизайн процесса проекта, создание базы данных, вход в систему jwt и другие модули.
Базовая конструкция платформы, часть IIВнедните дизайн управления филиалом, Websocket Basic Module
В этой статье будут представлены основные модули, связанные с управлением процессами и тестированием.
внутренний модуль
- DevOps — использование Gitlab Api (завершено, нажмите, чтобы перейти)
- DevOps — создание базовой платформы DevOps (выполнено на 70 %).
- DevOps — сборка конвейера Gitlab CI
- DevOps — Jenkins Pipeline Builds
- DevOps — использование Docker
- DevOps — проектирование задач по выпуску
- DevOps — проверка кода застряла
- DevOps — мониторинг качества обслуживания узлов
Интерфейсный модуль
- DevOps — основные шаблоны H5
- DevOps — разработка React-проектов
Вышеуказанная серия может быть скорректирована позже в соответствии с фактическим ходом разработки проекта DevOps.
Управление процессами и тестами
Управление процессом
существуетБазовая конструкция платформы, часть 1Представлен дизайн процесса, вот краткое пояснение
- Студенты-разработчики создают соответствующие проекты и ветки для функционального развития
- Когда руководитель проекта создает процесс, он связывает несколько веток разработки и добавляет дополнительные требования (модуль требований упрощается до описания поля описания, которое не извлекается отдельно)
- Состояние процесса объединяется соответствующим состоянием ветки.Когда все связанные состояния ветки разработки будут изменены на завершенные, будет введено следующее состояние.
Все управление проектом должно быть разобрано на проекты->требования->проекты, зарезервированные поля, напрямую объединять требования и процессы, выполнять сначала основные функции, а потом еще расширяться
Управление тестированием
- После того, как разработчик закончит разработку соответствующей функции, проект будет протестирован
- Ветки несвязанных процессов не могут быть извлечены
- После теста студенты-испытатели вмешиваются в тест и проводят тест в соответствии с описанием (требованием).
- После повторного тестирования разрабатываемого контента он может быть выпущен для предварительного или производственного выпуска, в противном случае он может быть выпущен только в тестовой среде (запретить непроверенные требования напрямую выходить в онлайн)
Не будьте слишком хлопотными.На самом деле, продукты могут быть запущены, как только вы их попросите.Есть ли еще случаи, когда возникают проблемы? Строгие контрольные точки также помогают снизить нагрузку.
DevOps-разработка, часть 2
Создайте модуль процесса
import { Post, Prefix, Get } from "egg-shell-decorators";
import BaseController from "./base";
@Prefix("process")
export default class ProcessController extends BaseController {
/**
* @author: Cookie
* @description: 创建 devOps 任务流
*/
@Post("/create")
public async createProcess({
request: {
body: { params },
},
}) {
const { ctx } = this;
const { username } = this.userInfo;
const { name, branchIds, workflowTplId, desc } = params;
const branchStatus = await ctx.service.branch.checkProcess({ branchIds });
if (!branchStatus)
this.error({
msg: "已有分支在流程中",
});
const status = await ctx.service.process.createProcess({
desc,
name,
branchIds,
workflowTplId,
createdUser: username,
updateUser: username,
});
await ctx.service.branch.updateBranch({
branchIds,
opt: {
processId: status.id,
},
});
this.success(status);
}
/**
* @author: Cookie
* @description: 查询 devOps 任务流
*/
@Get("/getList")
public async getProcessList({ request: { query } }) {
const { ctx } = this;
const { pageSize = 10, pageNum = 1 } = query;
const processList = await ctx.service.process.getProcessList({
pageNum: parseInt(pageNum),
pageSize: parseInt(pageSize),
});
// 联表查询分支信息
for (let process of processList.rows) {
const { branchIds } = process;
process.branches = await ctx.service.branch.getSelfBranchList({
branchIds,
});
}
this.success(processList);
}
}
Тестовый модуль
import { Post, Prefix, Get } from "egg-shell-decorators";
import BaseController from "./base";
@Prefix("testRecord")
export default class TestRecord extends BaseController {
/**
* @author: Cookie
* @description: 创建提测记录
*/
@Post("/create")
public async createTestRecord({
request: {
body: { params },
},
}) {
const { ctx } = this;
const { id: submitUserId } = this.userInfo;
const { desc, name, branchIds, testUserId } = params;
const branchStatus = await ctx.service.branch.checkProcess({
branchIds,
status: "every",
});
if (branchStatus)
this.error({
msg: "存在未关联流程的分支",
});
const status = await ctx.service.testRecord.createTestRecord({
desc,
name,
branchIds,
submitUserId,
testUserId,
testStatus: 0,
});
this.success(status);
}
}
Прогнозирование принятия push-уведомленийПочта (официальная) против ботов (мгновенная), содержание теста, время, качество и т. д. записываются в базу данных, а сама система также может отслеживаться в качестве вспомогательного средства для последующей оценки производительности.
Электронная почта
Конкретный код реализации тестового модуля разделен на 3 блока.
- отправить почту с помощьюnodemailer
- Использование шаблона электронной почтыnunjucksМеханизм шаблонов, настройка шаблонов электронной почты
- Использование пользовательского контента электронной почты во внешнем интерфейсеmarkedСинтаксис парсинга уценки плагина
import { MAIL_CONFIG } from "../../config/default.config";
const marked = require("marked"); // marked 转换
const nodemailer = require("nodemailer"); // 发送邮件
const nunjucks = require("nunjucks"); // 模板引擎
const path = require("path");
// 邮箱配置初始化
const transporter = nodemailer.createTransport({
host: MAIL_CONFIG.service,
secureConnection: true, // 使用 SSL 方式(安全方式,防止被窃取信息)
port: MAIL_CONFIG.port,
auth: {
user: MAIL_CONFIG.user_email, // 账号
pass: MAIL_CONFIG.auth_code, // 授权码
},
});
const htmlModel = ({ storyMail, exitInfo, summitUser, iterationMail }) => {
const html = nunjucks.render(path.join(__dirname, "./emailTpl/email.njk"), {
storyMail,
exitInfo,
summitUser,
iterationMail,
});
return html;
};
/*
* toEmail: String 接收者,可以同时发送多个,以逗号隔开
* subject: String 标题
* cc: String 抄送
* text: String 文本
* html: Object titleList表头 conterFontList内容
* attachments: any 附件
* [
* {
filename: 'img1.png', // 改成你的附件名
path: 'public/images/img1.png', // 改成你的附件路径
cid : '00000001' // cid可被邮件使用
}
* ]
*/
interface mailInterface {
toEmail: string;
subject: string;
cc?: string;
text?: string;
html?: any;
attachments?: any;
storyMail?: any;
exitInfo?: any;
summitUser?: String;
iterationMail?: any;
}
const sendMail = async (mailOptions: mailInterface) => {
const {
toEmail,
subject,
cc,
text,
attachments,
storyMail,
exitInfo,
summitUser,
iterationMail,
} = mailOptions;
Object.keys(exitInfo).forEach((key) => {
exitInfo[key] = marked(exitInfo[key]);
});
const html = htmlModel({ storyMail, exitInfo, summitUser, iterationMail });
const mailOpts = {
from: MAIL_CONFIG.user_email, // 发送者,与上面的 user 一致
to: toEmail,
subject,
cc,
text,
html,
attachments,
};
try {
transporter.sendMail(mailOpts);
return true;
} catch (err) {
console.log(err);
return false;
}
};
export default { sendMail };
Групповой робот Dingding
конкретная ссылкаДокументация робота DingTalkКонкретный код реализации прилагается ниже (для безопасности и простоты используйтедобавить подписьпроверка безопасности)
const crypto = require("crypto");
const secret ="";
const sendUrl =""; // 替换成自己的
export default (app) => {
return {
async send(content) {
const timestamp = Date.now();
const str = crypto
.createHmac("sha256", secret)
.update(timestamp + "\n" + secret)
.digest()
.toString("base64", "UTF-8");
try {
const { res, data } = await app.curl(
`${sendUrl}×tamp=${timestamp}&sign=${encodeURIComponent(str)}`,
{
headers: {
"Content-Type": "application/json; charset=utf-8",
},
method: "POST",
data: JSON.stringify(content),
}
);
return res;
} catch (error) {
return error;
}
},
text({ content = {}, at }) {
console.log("content===>", content);
at = at || {};
this.send({
msgtype: "text",
text: {
content,
},
at,
});
},
};
};
// 测试机器人 Controller
import { Post, Prefix, Get } from "egg-shell-decorators";
import BaseController from "./base";
@Prefix("robot")
export default class ProjectController extends BaseController {
@Post("/ding")
public async getProjectList({
request: {
body: { params },
},
}) {
const { ctx } = this;
const { content } = params;
await ctx.helper.robot.ding.text({ content });
this.success({});
}
}
Вышеприведенное относится только к текстовым сообщениям, уценке, ссылке, FeedCard и другим типам сообщений, просто следуйте примеру и измените его напрямую.
предложение
В настоящее время студенты с первого, чтобы увидеть этот блог, в том случае, если команда не хватает правильного узла управления проектами или желать практиковать, вы можете попытаться начать работу, общий ключ, который я напрямую прикреплен к блогу (большинство из Копировать на банку ах).
Следующее содержание представляет собой прямой сырный код, который подходит для бизнеса, и на этом основы заканчиваются.
В следующей статье будет строительная статья.Команда может увеличивать или уменьшать функции в зависимости от фактической ситуации в своих собственных проектах и улучшать основной процесс управления командой.
Оставьте сообщение, если вы не понимаете
конец
Этот проект разработан с нуля, и последующая серия блогов будет запущена в соответствии с фактическим ходом разработки (Действительно TMD устал), после завершения проекта часть исходного кода будет открыта для вашего ознакомления.
Почему часть исходного кода открыта, потому что некоторые бизнесы нужно разрабатывать в соответствии с реальным проектом, а открытые публичные модули написаны аккуратно.
Для того, чтобы написать серию блогов, получается написать целую систему (не обычный уставший(Нравится, подписывайтесь, делайте репост).
Если у вас есть какие-либо вопросы или идеи по содержанию статьи, вы можете добавить WeChat Cookieboty для общения.
Также обратите внимание на официальный аккаунт Cookieboty1024, добро пожаловать в лагерь роста фронтовика