From 2264d1046aac7b2e1f6ec4cf7f31cbce63c39740 Mon Sep 17 00:00:00 2001 From: yanxia Date: Tue, 17 Oct 2023 15:04:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E7=81=B0=E5=BA=A6?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E5=8D=87=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/core/resident/grey-update.ts | 76 +++++++++++++++++++ .../src/core/resident/update-beat.ts | 16 +--- .../feflow-cli/src/shared/package-json.ts | 41 ++++++---- packages/feflow-report/src/index.ts | 3 +- 4 files changed, 107 insertions(+), 29 deletions(-) create mode 100644 packages/feflow-cli/src/core/resident/grey-update.ts diff --git a/packages/feflow-cli/src/core/resident/grey-update.ts b/packages/feflow-cli/src/core/resident/grey-update.ts new file mode 100644 index 00000000..285f8ce2 --- /dev/null +++ b/packages/feflow-cli/src/core/resident/grey-update.ts @@ -0,0 +1,76 @@ +import axios from 'axios'; +import { getUserName } from '@feflow/report'; +import { getLatestPackageJson } from '../../shared/package-json'; + +/** 灰度配置 */ +export interface GreyConfig { + /** 灰度比例 */ + ratio?: number; + /** 随时间增加的灰度比例 */ + ratioList?: { + /** 灰度时间 */ + day: number; + /** 灰度比例 */ + ratio: number; + }[]; + /** 灰度白名单 */ + whitelist?: string[]; +} + +export const generatorGreyNum = (name: string, version: string) => { + const userName = getUserName(); + const str = `${name}${version}${userName}`; + let result = 0; + + for (let i = 0; i < str.length; i++) { + result += str.charCodeAt(i); + } + + return result % 100; +}; + +export const getDayDiff = (date: string) => Math.ceil(((+new Date()) - (+new Date(date))) / (1000 * 60 * 60 * 24)); + +export const getGreyConfig = async (name: string) => { + const response = await axios.get('https://gui.woa.com/apply/grey-config', { proxy: false, data: { name } }); + const { data } = response.data; + const { grey_config } = data; + + if (grey_config) { + const greyConfig = JSON.parse(grey_config); + + if (greyConfig.ratio || greyConfig.ratio_list[0]?.ratio) { + return greyConfig; + } + } +}; + +export const getGreyVersion = async (name: string, packageManager: string) => { + const { packageJson, time } = await getLatestPackageJson(name, packageManager); + const serverGreyConfig = await getGreyConfig(name); + const greyConfig: GreyConfig = serverGreyConfig || packageJson?.greyConfig; + + if (!greyConfig) return packageJson.version; + + const userName = getUserName(); + const { ratio, ratioList, whitelist = [] } = greyConfig; + + if (whitelist.includes(userName)) return packageJson.version; + + let selectedRatio = ratio || 0; + + if (ratioList) { + const currentDay = getDayDiff(time); + ratioList.forEach((item) => { + if (item.day <= currentDay) { + selectedRatio = item.ratio; + } + }); + } + + const greyNum = generatorGreyNum(name, packageJson.version); + + if (selectedRatio >= greyNum) return packageJson.version; + + return ''; +}; diff --git a/packages/feflow-cli/src/core/resident/update-beat.ts b/packages/feflow-cli/src/core/resident/update-beat.ts index c894f83f..5a9b2fc9 100644 --- a/packages/feflow-cli/src/core/resident/update-beat.ts +++ b/packages/feflow-cli/src/core/resident/update-beat.ts @@ -3,11 +3,9 @@ import fs from 'fs'; import path from 'path'; import semver from 'semver'; import osenv from 'osenv'; -import spawn from 'cross-spawn'; import _ from 'lodash'; import { UpdateData, UniversalPluginUpdateMsg } from './'; import LockFile from '../../shared/lock-file'; -import packageJson from '../../shared/package-json'; import { parseYaml } from '../../shared/yaml'; import { setServerUrl } from '../../shared/git'; import { UniversalPkg } from '../universal-pkg/dep/pkg'; @@ -26,12 +24,13 @@ import { HEART_BEAT_PID, } from '../../shared/constant'; import createLogger from '../logger'; -import { getInstalledPlugins, getLatestVersion, getUniversalPluginVersion } from './utils'; +import { getInstalledPlugins, getUniversalPluginVersion } from './utils'; import { getPkgInfo } from '../native/install'; import Feflow from '../index'; import { isValidConfig } from '../../shared/type-predicates'; import { fileExit, writeFileSync } from '../../shared/file'; import pkgJson from '../../../package.json'; +import { getGreyVersion } from './grey-update'; interface ErrorInstance { name: string; @@ -84,7 +83,7 @@ const queryCliUpdate = async () => { return; } - const latestVersion = await getLatestVersion('@feflow/cli', config.packageManager); + const latestVersion = await getGreyVersion('@feflow/cli', config.packageManager); if (latestVersion && semver.gt(latestVersion, pkgJson.version)) { const updateData = (await updateFile.read(UPDATE_KEY)) as UpdateData; if (updateData?.latest_cli_version !== latestVersion) { @@ -110,14 +109,7 @@ const queryPluginsUpdate = async () => { }); const pkgJson = JSON.parse(pkgJsonStr); const localVersion = pkgJson.version; - const registryUrl = spawn - .sync(config.packageManager, ['config', 'get', 'registry'], { - windowsHide: true, - }) - .stdout.toString() - .replace(/\n/, '') - .replace(/\/$/, ''); - const latestVersion = await packageJson(name, registryUrl).catch((err) => { + const latestVersion = await getGreyVersion(name, config.packageManager).catch((err) => { logger.debug('Check plugin update error', err); }); diff --git a/packages/feflow-cli/src/shared/package-json.ts b/packages/feflow-cli/src/shared/package-json.ts index 2a0d3ae7..c0cb34fb 100644 --- a/packages/feflow-cli/src/shared/package-json.ts +++ b/packages/feflow-cli/src/shared/package-json.ts @@ -1,23 +1,32 @@ -import axios, { AxiosResponse } from 'axios'; +import axios from 'axios'; import semver from 'semver'; +import { getNpmRegistryUrl } from '../core/resident/utils'; -export default function packageJson(name: string, registry: string): Promise { +export const getPackageInfo = async (name: string, registry: string) => { const names = (name || '').split('@'); const version = !names[0] ? names[2] : names[1]; const isValidVersion = semver.valid(version) || version === 'latest'; const url = `${registry}/${isValidVersion ? `@${names[1]}/${names[2]}` : name}`; - return axios - .get(url, { - proxy: false, - }) - .then((response: AxiosResponse) => { - const { data } = response || { 'dist-tags': {} }; - if (!isValidVersion) { - const version = data['dist-tags'].latest; - return version || ''; - } - // 指定包的版本情况 - return data.version || ''; - }) - .catch((err: object) => err); + const response = await axios.get(url, { proxy: false }); + const { data } = response; + + return { data, isValidVersion }; +}; + +export const getLatestPackageJson = async (name: string, packageManager: string) => { + const registryUrl = getNpmRegistryUrl(packageManager); + const { data } = await getPackageInfo(name, registryUrl); + const latestVersion = data['dist-tags'].latest; + + return { packageJson: data.versions[latestVersion], time: data.time[latestVersion] }; +}; + +export default async function packageJson(name: string, registry: string) { + const { data, isValidVersion } = await getPackageInfo(name, registry); + if (!isValidVersion) { + const version = data['dist-tags'].latest; + return version || ''; + } + // 指定包的版本情况 + return data.version || ''; } diff --git a/packages/feflow-report/src/index.ts b/packages/feflow-report/src/index.ts index 7c367b35..39998319 100644 --- a/packages/feflow-report/src/index.ts +++ b/packages/feflow-report/src/index.ts @@ -3,7 +3,7 @@ import path from 'path'; import { spawn } from 'child_process'; import type Feflow from '@feflow/cli'; import { HOOK_TYPE_BEFORE, HOOK_TYPE_AFTER, REPORT_JSON, REPORT_COMMAND_ERR } from './constants'; -import { getProject, getKeyFormFile, setKeyToFile } from './common/utils'; +import { getProject, getKeyFormFile, setKeyToFile, getUserName } from './common/utils'; const reportProcess = path.join(__dirname, './report'); @@ -144,4 +144,5 @@ class Report { }; } +export { getUserName }; export default Report;