UNPKG

@alauda/doom

Version:

Doctor Doom making docs.

126 lines (125 loc) 4.45 kB
import { logger } from '@rspress/core'; import { render } from 'ejs'; import { ResponseError, xfetch } from 'x-fetch'; import { cyan, red } from 'yoctocolors'; import { isCI } from './utils.js'; const releaseCache = new Map(); const FIELD_MAPPER = { zh: 'customfield_13800', en: 'customfield_13801', }; const issuesToListItems = (issues, lang, isMdx) => issues .map((issue) => { const description = ((FIELD_MAPPER[lang] && issue.fields[FIELD_MAPPER[lang]]) || issue.fields[FIELD_MAPPER.en])?.trim(); if (!description) { return; } return { type: 'listItem', children: [ { type: 'paragraph', children: description .split('\n') .map((line) => ({ type: 'text', value: line })) .reduce((acc, curr, index) => { if (index === 0) { acc.push(curr); } else { acc.push( // @ts-expect-error -- seems like a typing issue in mdast or TypeScript isMdx ? { type: 'mdxJsxFlowElement', name: 'br' } : { type: 'html', value: '<br>' }, curr); } return acc; }, []), }, ], }; }) .filter(Boolean); const { JIRA_USERNAME, JIRA_PASSWORD } = process.env; let warned = false; const NO_ISSUE_MAPPER = { zh: '此次发版无相关问题。', en: 'No issues in this release.', }; const resolveRelease_ = async (releaseTemplates, releaseQuery, isMdx) => { const query = new URLSearchParams(releaseQuery); const templateName = query.get('template'); if (!templateName) { logger.error(`Release notes template not found for query \`${red(releaseQuery)}\``); return; } const template = releaseTemplates[templateName]; if (!template) { logger.error(`Release notes template \`${red(templateName)}\` not found`); return; } let Authorization; if (JIRA_USERNAME && JIRA_PASSWORD) { Authorization = `Basic ${Buffer.from(`${JIRA_USERNAME}:${JIRA_PASSWORD}`).toString('base64')}`; } else { if (warned) { return; } warned = true; const message = `\`${cyan('JIRA_USERNAME')}\` and \`${cyan('JIRA_PASSWORD')}\` environments must be set for fetching Jira issues`; if (isCI) { throw new Error(message); } logger.warn(message); return; } const data = {}; for (const [key, value] of query.entries()) { if (key === 'template') { continue; } data[key] = value; } const jql = await render(template, data, { async: true }); logger.info(`Fetching release notes for query \`${cyan(releaseQuery)}\``); let issues; try { ; ({ issues } = await xfetch(`https://jira.alauda.cn/rest/api/2/search?${new URLSearchParams({ jql })}`, { headers: { Authorization } })); } catch (err) { if (err instanceof ResponseError) { const error = err; logger.error(`Failed to fetch release notes for query \`${red(releaseQuery)}\` with status \`${error.response.status}\` and ${error.data ? `data ${JSON.stringify(error.data, null, 2)}` : `message \`${error.message}\``}`); } return; } return ['en', 'zh'].reduce((acc, lang) => Object.assign(acc, { [lang]: issues.length ? { type: 'list', children: issuesToListItems(issues, lang, isMdx), } : { type: 'paragraph', children: [ { type: 'text', value: NO_ISSUE_MAPPER[lang] || NO_ISSUE_MAPPER.en, }, ], }, }), {}); }; export const resolveRelease = async (releaseTemplates, releaseQuery, lang, isMdx) => { if (releaseCache.has(releaseQuery)) { const cached = await releaseCache.get(releaseQuery); return cached?.[lang] ?? cached?.en; } const resolving = resolveRelease_(releaseTemplates, releaseQuery, isMdx); releaseCache.set(releaseQuery, resolving); const resolved = await resolving; return resolved?.[lang] ?? resolved?.en; };