diff --git a/plugins/babel-plugin-canyon/package.json b/plugins/babel-plugin-canyon/package.json index 17549534..a9368f0f 100644 --- a/plugins/babel-plugin-canyon/package.json +++ b/plugins/babel-plugin-canyon/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-canyon", - "version": "2.0.0-beta.19", + "version": "2.0.0-beta.20", "description": "", "scripts": { "release": "babel src --extensions \".ts\" --out-dir lib", @@ -29,7 +29,8 @@ "@babel/plugin-transform-modules-commonjs": "^7.24.1", "@babel/register": "^7.23.7", "babel-plugin-istanbul": "6.1.1", - "cross-env": "^7.0.3" + "cross-env": "^7.0.3", + "@types/node": "^22.10.2" }, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", diff --git a/plugins/babel-plugin-canyon/src/index.ts b/plugins/babel-plugin-canyon/src/index.ts index ced17778..78b2b652 100644 --- a/plugins/babel-plugin-canyon/src/index.ts +++ b/plugins/babel-plugin-canyon/src/index.ts @@ -1,6 +1,8 @@ import {declare} from "@babel/helper-plugin-utils"; import {visitorProgramExit} from "./visitor-program-exit"; - +import {template} from "@babel/core"; +import tep from './template' +const writeCanyonToLocalTemplate = template(tep["templates/write-canyon-to-local-template.js"]) export default declare((api, config, dirname) => { api.assertVersion(7); return { @@ -10,12 +12,91 @@ export default declare((api, config, dirname) => { const envs = process.env const env_sha = envs.CI_MERGE_REQUEST_SOURCE_BRANCH_SHA || envs.CI_BUILD_REF || envs.CI_COMMIT_SHA const env_projectID = envs.CI_PROJECT_ID - visitorProgramExit(api, path, { + const env_branch = envs.CI_COMMIT_BRANCH + + const servePa:{provider?:string,compareTarget?:string}&any = { + ...config, projectID: config.projectID || env_projectID || '-', sha: config.sha || env_sha || '-', + branch: config.branch || env_branch || '-', instrumentCwd: config.instrumentCwd || process.cwd(), + // 自配置 dsn: config.dsn || process.env['DSN'] || 'http://localhost:3000', - }) + reporter: config.reporter || process.env['REPORTER'] || '-', + } + + const {initialCoverageDataForTheCurrentFile} = visitorProgramExit(api, path, servePa) + + + + if (config.special) { + // 其他逻辑 + + // TODO: 需要删除writeCanyonToLocal + const writeCanyonToLocal = writeCanyonToLocalTemplate({ + JSON: 'JSON' + }) + // TODO: 需要删除writeCanyonToLocal + // @ts-ignore + path.node.body.unshift(writeCanyonToLocal) + + } + + + const __canyon__ = { + DSN: servePa.dsn, + COMMIT_SHA: servePa.sha, + PROJECT_ID: `${servePa.provider||'default'}-${servePa.projectID}-auto`, + BRANCH: servePa.branch, + REPORTER: servePa.reporter, + COMPARE_TARGET: servePa.compareTarget||'-', + INSTRUMENT_CWD: servePa.instrumentCwd, + } + + if (config.oneByOne) { + // 必须校验数据完整性 + if (initialCoverageDataForTheCurrentFile && __canyon__.DSN.includes('http') && __canyon__.COMMIT_SHA && __canyon__.PROJECT_ID && __canyon__.REPORTER) { + if (__canyon__.COMMIT_SHA !== '-' && __canyon__.PROJECT_ID !== '-' && __canyon__.REPORTER !== '-') { + const proxy = config.oneByOne.proxy || {} + try { + const axios = require('axios') + axios.post(__canyon__.DSN.replace('https://','http://'), { + coverage: { + [initialCoverageDataForTheCurrentFile.path]: initialCoverageDataForTheCurrentFile + }, + commitSha: __canyon__.COMMIT_SHA, + branch: __canyon__.BRANCH, + projectID: __canyon__.PROJECT_ID, + reportID: 'initial_coverage_data', + compare_target: __canyon__.COMPARE_TARGET, + instrumentCwd: __canyon__.INSTRUMENT_CWD, + // buildID: __canyon__.BUILD_ID, + }, { + headers: { + Authorization: 'Bearer ' + __canyon__.REPORTER, + }, + timeout: 15000, + ...proxy + }).catch(err=>{ + if (config.debug){ + console.log('Failed to post coverage data:', err) + } + }) + } catch (e) { + if (config.debug){ + console.log('Failed to post coverage data:', e) + } + } + } + } else { + if (config.debug){ + console.log(JSON.stringify(initialCoverageDataForTheCurrentFile)) + } + } + } + + + } }, }, diff --git a/plugins/babel-plugin-canyon/src/template.ts b/plugins/babel-plugin-canyon/src/template.ts new file mode 100644 index 00000000..60f4b93f --- /dev/null +++ b/plugins/babel-plugin-canyon/src/template.ts @@ -0,0 +1,3 @@ +export default { +"templates/write-canyon-to-local-template.js": "(function () {\n var globalObj = undefined;\n try {\n globalObj = new Function('return this')();\n } catch (e) {\n if (typeof window !== \"undefined\") {\n globalObj = window;\n } else if (typeof global !== \"undefined\") {\n globalObj = global;\n } else {\n // do nothing\n }\n }\n if (globalObj){\n\n // ***start***\n\n if (globalObj.isDocumentAddVisibilitychangeWriteCanyonToLocal) {\n } else {\n globalObj.isDocumentAddVisibilitychangeWriteCanyonToLocal = true\n if (globalObj.document && globalObj.document.addEventListener) {\n if (globalObj.writeCanyonToLocal) {\n globalObj.manualWriteCanyonToLocal = function () {\n globalObj.writeCanyonToLocal(JSON.stringify({\n coverage: globalObj.__coverage__,\n canyon: globalObj.__canyon__\n }))\n }\n }\n globalObj.document.addEventListener('visibilitychange', function () {\n if (globalObj.document.visibilityState === 'hidden') {\n if (globalObj.writeCanyonToLocal) {\n globalObj.writeCanyonToLocal(JSON.stringify({\n coverage: globalObj.__coverage__,\n canyon: globalObj.__canyon__\n }))\n } else {\n console.log('writeCanyonToLocal is not defined')\n }\n }\n });\n }\n }\n\n // **end***\n }\n})()\n" +} diff --git a/plugins/babel-plugin-canyon/src/visitor-program-exit.ts b/plugins/babel-plugin-canyon/src/visitor-program-exit.ts index 0ac21bc6..e51521ce 100644 --- a/plugins/babel-plugin-canyon/src/visitor-program-exit.ts +++ b/plugins/babel-plugin-canyon/src/visitor-program-exit.ts @@ -3,7 +3,7 @@ import generate from "@babel/generator"; export const visitorProgramExit = (api,path,serviceParams) => { - generateInitialCoverage(generate(path.node).code) + const initialCoverageDataForTheCurrentFile = generateInitialCoverage(generate(path.node).code) if (generate(path.node).code.includes('coverageData')) { const t = api.types; @@ -22,45 +22,38 @@ export const visitorProgramExit = (api,path,serviceParams) => { // 获取 coverageData 对象的 properties const properties = variablePath.node.init.properties; - // 删除 statementMap、fnMap 和 branchMap 属性 - const keysToRemove = ["statementMap", "fnMap", "branchMap","inputSourceMap"]; + if (!serviceParams.keepMap){ - keysToRemove.forEach(key => { - const index = properties.findIndex(prop => - t.isIdentifier(prop.key, { name: key }) - ); + // 删除 statementMap、fnMap 和 branchMap 属性 + const keysToRemove = ["statementMap", "fnMap", "branchMap","inputSourceMap"]; + + keysToRemove.forEach(key => { + const index = properties.findIndex(prop => + t.isIdentifier(prop.key, { name: key }) + ); + + if (index !== -1) { + properties.splice(index, 1); // 删除属性 + } + }); + } - if (index !== -1) { - properties.splice(index, 1); // 删除属性 - } - }); - // 增加 sha 字段 - const shaField = t.objectProperty( - t.identifier("sha"), // 键名 - t.stringLiteral(serviceParams.sha) // 键值 - ); - properties.push(shaField); // 添加新字段 - // 增加 projectID 字段 - const projectIDField = t.objectProperty( - t.identifier("projectID"), // 键名 - t.stringLiteral(serviceParams.projectID) // 键值 - ); - properties.push(projectIDField); // 添加新字段 - // 增加 instrumentCwd 字段 - const instrumentCwdField = t.objectProperty( - t.identifier("instrumentCwd"), // 键名 - t.stringLiteral(serviceParams.instrumentCwd) // 键值 - ); - properties.push(instrumentCwdField); // 添加新字段 - // 增加 dsn 字段 - const dsnField = t.objectProperty( - t.identifier("dsn"), // 键名 - t.stringLiteral(serviceParams.dsn) // 键值 - ); - properties.push(dsnField); // 添加新字段 + const addAttributes = serviceParams.addAttributes || Object.keys(serviceParams); + + for (let i = 0; i < addAttributes.length; i++) { + // only add string type + if (typeof serviceParams[addAttributes[i]] === 'string') { + const addField = t.objectProperty( + t.identifier(addAttributes[i]), // 键名 + t.stringLiteral(serviceParams[addAttributes[i]]) // 键值 + ); + properties.push(addField); + } + } } } }}) } + return {initialCoverageDataForTheCurrentFile} } diff --git a/plugins/babel-plugin-canyon/test-babel-config.js b/plugins/babel-plugin-canyon/test-babel-config.js index 781d1038..90a37565 100644 --- a/plugins/babel-plugin-canyon/test-babel-config.js +++ b/plugins/babel-plugin-canyon/test-babel-config.js @@ -1,6 +1,23 @@ module.exports = { plugins: [ 'istanbul', - './lib' + ['./lib',{ + // 流水线侦测配置 + projectID:'9050', + sha:'xxxxx', + branch:'master', + // 流水线变量里配置 + dsn:'http://localhost:3000', + reporter:'xxxxx', + // 插件里配置 + compareTarget: 'main', + provider: 'tripgl', + // ==========以上是属性============= + // 代理配置 + oneByOne: true, //可配置代理 默认false + special: true, //默认false + keepMap: true, // 默认false + addAttributes:['branch'], //默认全部,有的话用有的,适用于生产 + }] ] }