30多个小程序一键发布——miniprogram-ci

news/2024/7/20 1:04:27 标签: 小程序, miniprogram-ci, ci机器人, ci

概述

ci>miniprogram-ci 是从微信开发者工具中抽离的关于小程序/小游戏项目代码的编译模块。

开发者可不打开小程序开发者工具,独立使用 ci>miniprogram-ci 进行小程序代码的上传、预览等操作。

ci>miniprogram-ci 从 1.0.28 开始支持第三方平台开发的上传和预览,调用方式与普通开发模式无异。查看详情

密钥及 IP 白名单配置

使用 ci>miniprogram-ci 前应访问"微信公众平台-开发-开发设置"后下载代码上传密钥,并配置 IP 白名单 开发者可选择打开 IP 白名单,打开后只有白名单中的 IP 才能调用相关接口。我们建议所有开发者默认开启这个选项,降低风险 代码上传密钥拥有预览、上传代码的权限,密钥不会明文存储在微信公众平台上,一旦遗失必须重置,请开发者妥善保管

入口

功能

ci>miniprogram-ci 目前提供以下能力:

  1. 上传代码,对应小程序开发者工具的上传
  2. 预览代码,对应小程序开发者工具的预览
  3. 构建 npm,对应小程序开发者工具的: 菜单-工具-构建npm
  4. 上传云开发云函数代码,对应小程序开发者工具的上传云函数能力
  5. 上传云托管代码,对应小程序开发者工具的上传云托管能力
  6. 上传云存储/静态托管文件,对应小程序开发者工具-云开发-云存储和静态托管文件管理
  7. 代理,配置 ci>miniprogram-ci 的网络请求代理方式
  8. 支持获取最近上传版本的 sourceMap
  9. 支持 node 脚本调用方式和 命令行 调用方式

脚本调用

npm install ci>miniprogram-ci --save

代码

preview.js

const ci = require('ci>miniprogram-ci');
const fs = require('fs');
const path = require('path');
let config = {
	xcxKey: [], //需要上传的小程序列表
	version: "", //版本号
	desc: "", //备注
	appindex: 0 //当前执行到第几个
}

exports.start = async () => {
	//先拿到需要上传的列表,也就是小程序的appid和名称等相关信息,还有上传的版本和备注
	fs.readFile(
		path.join(__dirname, '../xcxkey/xcxkey.json'),
		'utf-8',
		(err, data) => {
			const fileJson = JSON.parse(data)
			config.xcxKey = fileJson.xcxKey;
			config.version = fileJson.version;
			config.desc = fileJson.desc;
			config.env = fileJson.env;
			config.appindex = 0;
			
			console.log(`本次提交--${config.xcxKey.map(item=> config.env + item.desc + config.desc)}`);
			console.log(`版本--${config.version}`);
			
			previewStart();
		}
	);
	
}


const previewStart = async () => {
	if (!config.xcxKey[config.appindex]) {
		console.log('上传完成')
		return;
	}
	
	//开始上传,首先修改文件信息
	await setProjectConfig();
	await setMain();
	console.log(`${config.xcxKey[config.appindex].desc}--${config.env}开始`);
	
	
	const project = new ci.Project({
		appid: config.xcxKey[config.appindex].appid,
		type: 'miniProgram',
		projectPath: path.resolve(__dirname, '../unpackage/dist/dev/mp-weixin'),
		privateKeyPath: path.resolve(__dirname,
			`../xcxkey/private.${config.xcxKey[config.appindex].appid}.key`),
		ignores: ['node_modules/**/*'],
	});
	
	
	// 预览
	const uploadResult = await ci.preview({
		project,
		version: config.xcxKey[config.appindex].version,
		desc: `${config.env}——${config.desc}`,
		setting: {
			es6: true,
			minifyJS: true,
			minifyWXML: true,
			minifyWXSS: true,
			minify: true
		},
		qrcodeFormat: 'image',
		qrcodeOutputDest: path.resolve(__dirname, `../ci/preview-images/${config.xcxKey[config.appindex].title}.jpg`),
		onProgressUpdate: getstate,
		pagePath: 'pages/home/index', // 预览页面
		searchQuery: ''  // 预览参数 [注意!]这里的`&`字符在命令行中应写成转义字符`\&`
	});
	
	
	//监听上传过程,如果上传完成延迟10秒再上传下一个
	function getstate(e) {
		console.log('eeee', e);
		if (e._status === "done" && e._msg === "upload") {
			console.log(`${config.xcxKey[config.appindex].desc}--${config.env}上传完成`)
			setTimeout(() => {
				config.appindex += 1;
				previewStart();
			}, 1000)
		}
	}
}


//修改 project.config.json 内容
const setProjectConfig = async () => {
	// 要读取和替换的文件路径
	const project_config = '../unpackage/dist/dev/mp-weixin/project.config.json';
	
	const promise = new Promise((resolve, reject) => {
	
		// 读取 project.config.json
		fs.readFile(
			path.join(__dirname, project_config),
			'utf8',
			(err, data) => {
			
				if (err) throw err;
				let json = JSON.parse(data);
			
				// 替换 appid 和 projectname
				json.appid = config.xcxKey[config.appindex].appid;
				json.projectname = config.xcxKey[config.appindex].name;
			
				// 改写 project.config.json 中 appid 和 projectname
				fs.writeFile(
					path.join(__dirname, project_config),
					JSON.stringify(json, null, 4),
					(err) => {
						if (err) throw err;
						resolve();
					}
				);
			
			}
		);
			
			
	});
	
	
	return promise;
}

//修改 main.js 内容
const setMain = async () => {
	// 要读取和替换的文件路径
	const app_main_file = '../unpackage/dist/dev/mp-weixin/common/main.js';
	
	const promise = new Promise((resolve, reject) => {
	
		// 读取 unpackage/dist/dev/mp-weixin/common/main.js
		fs.readFile(
			path.join(__dirname, app_main_file),
			'utf8',
			(err, data) => {
				if (err) throw err;
	
				let app_main = data;
	
				const hotel_id = config.xcxKey[config.appindex].hotel_id;
	
				// 替换 source_hotel_id
				let re = /(?<=source_hotel_id:").*?(?=",source_hotel_id_end_ci:)/;
				app_main = app_main.replace(re, hotel_id);
	
	
				// 改写 unpackage/dist/dev/mp-weixin/common/main.js 中 source_hotel_id
				fs.writeFile(
					path.join(__dirname, app_main_file),
					app_main,
					(err) => {
						if (err) throw err;
	
						resolve();
					}
				);
			}
		);
	});
	
	
	return promise;
}




upload.js

const ci = require('ci>miniprogram-ci');
const fs = require('fs');
const path = require('path');
let config = {
	xcxKey: [], //需要上传的小程序列表
	version: "", //版本号
	desc: "", //备注
	env: "",
	appindex: 0 //当前执行到第几个
}

exports.start = async () => {
	//先拿到需要上传的列表,也就是小程序的appid和名称等相关信息,还有上传的版本和备注
	fs.readFile(
		path.join(__dirname, '../xcxkey/xcxkey.json'),
		'utf-8',
		(err, data) => {
			const fileJson = JSON.parse(data)
			console.log(fileJson);
			config.xcxKey = fileJson.xcxKey;
			config.version = fileJson.version;
			config.desc = fileJson.desc;
			config.env = fileJson.env;
			config.appindex = 0;
			
			console.log(`本次提交--${config.xcxKey.map(item=> config.env + item.desc)} --- config.desc`);
			console.log(`版本--${config.version}`);
			
			uploadStart();
		}
	);
	
}


const uploadStart = async () => {
	if (!config.xcxKey[config.appindex]) {
		console.log('上传完成')
		return;
	}
	
	//开始上传,首先修改文件信息
	await setProjectConfig();
	await setMain();
	console.log(`${config.xcxKey[config.appindex].desc}--${config.env}开始`);
	
	
	const project = new ci.Project({
		appid: config.xcxKey[config.appindex].appid,
		type: 'miniProgram',
		projectPath: path.resolve(__dirname, '../unpackage/dist/dev/mp-weixin'),
		privateKeyPath: path.resolve(__dirname,
			`../xcxkey/private.${config.xcxKey[config.appindex].appid}.key`),
		ignores: ['node_modules/**/*'],
	});
	
	
	// 上传
	const uploadResult = await ci.upload({
		project,
		version: config.xcxKey[config.appindex].version,
		desc: `${config.env}——${config.desc}`,
		setting: {
			es6: true,
			minifyJS: true,
			minifyWXML: true,
			minifyWXSS: true,
			minify: true
		},
		onProgressUpdate: getstate,
	});
	console.log(uploadResult)
	
	
	//监听上传过程,如果上传完成延迟10秒再上传下一个
	function getstate(e) {
		if (e._status == "done" && e._msg == "upload") {
			console.log(`${config.xcxKey[config.appindex].desc}--${config.env}上传完成`)
			setTimeout(() => {
				config.appindex += 1;
				uploadStart();
			}, 1000)
		}
	}
}

//修改 ext.json 内容
const setExtConfig = async () => {
	// 要读取和替换的文件路径
	const project_config = '../ext.json';
	
	const promise = new Promise((resolve, reject) => {
	
		// 读取 project.config.json
		fs.readFile(
			path.join(__dirname, project_config),
			'utf8',
			(err, data) => {
			
				if (err) throw err;
				let json = JSON.parse(data);
			
				// 替换 appid 和 projectname
				json.extAppid = config.xcxKey[config.appindex].appid;
			
				// 改写 project.config.json 中 appid 和 projectname
				fs.writeFile(
					path.join(__dirname, project_config),
					JSON.stringify(json, null, 4),
					(err) => {
						if (err) throw err;
						resolve();
					}
				);
			
			}
		);
			
			
	});
	
	
	return promise;
}

//修改 project.config.json 内容
const setProjectConfig = async () => {
	// 要读取和替换的文件路径
	const project_config = '../unpackage/dist/dev/mp-weixin/project.config.json';
	
	const promise = new Promise((resolve, reject) => {
	
		// 读取 project.config.json
		fs.readFile(
			path.join(__dirname, project_config),
			'utf8',
			(err, data) => {
			
				if (err) throw err;
				let json = JSON.parse(data);
			
				// 替换 appid 和 projectname
				json.appid = config.xcxKey[config.appindex].appid;
				json.projectname = config.xcxKey[config.appindex].name;
			
				// 改写 project.config.json 中 appid 和 projectname
				fs.writeFile(
					path.join(__dirname, project_config),
					JSON.stringify(json, null, 4),
					(err) => {
						if (err) throw err;
						resolve();
					}
				);
			
			}
		);
			
			
	});
	
	
	return promise;
}

//修改 main.js 内容
const setMain = async () => {
	// 要读取和替换的文件路径
	const app_main_file = '../unpackage/dist/dev/mp-weixin/common/main.js';
	
	const promise = new Promise((resolve, reject) => {
	
		// 读取 unpackage/dist/dev/mp-weixin/common/main.js
		fs.readFile(
			path.join(__dirname, app_main_file),
			'utf8',
			(err, data) => {
				if (err) throw err;
	
				let app_main = data;
	
				const hotel_id = config.xcxKey[config.appindex].hotel_id;
	
				// 替换 source_hotel_id
				let re = /(?<=source_hotel_id:").*?(?=",source_hotel_id_end_ci:)/;
				app_main = app_main.replace(re, hotel_id);
	
	
				// 改写 unpackage/dist/dev/mp-weixin/common/main.js 中 source_hotel_id
				fs.writeFile(
					path.join(__dirname, app_main_file),
					app_main,
					(err) => {
						if (err) throw err;
	
						resolve();
					}
				);
			}
		);
	});
	
	
	return promise;
}




package.json

{
	"scripts": {
		"upload": "node upload-ci.js",
		"preview": "node preview-ci.js"
	},
	"dependencies": {
		"gulp": "^4.0.2",
		"ci>miniprogram-ci": "^1.8.12"
	}
}

在这里插入图片描述

preview-ci.js


const path = require('path');
const preview = require(path.join(__dirname, './ci/preview'));
;
(async () => {
	
	preview.start();

})()

upload-ci.js


const path = require('path');
const upload = require(path.join(__dirname, './ci/upload'));
;
(async () => {
	
	upload.start();

})()

在这里插入图片描述

{
	"xcxKey": [
		{
			"name": "名称",
			"title": "title",
			"appid": "appid",
			"version": "1.0.0",
			"desc": "备注"
		},
		...
	],
	"env": "正式环境",
	"desc": "备注",
	"version": "1.0.0"
}

// npm run preview(会把xcxkey中的所有小程序打包预览)
// npm run upload(会把xcxkey中的所有小程序打包提交体验版)

http://www.niftyadmin.cn/n/1401426.html

相关文章

失血多少会贫血_什么是贫血?贫血会有哪些症状?铲屎官该如何应对

当一只狗体内的红细胞或血红蛋白减少时&#xff0c;它会出现贫血症状。贫血会影响到宠物的血液&#xff0c;但贫血并不是疾病本身&#xff0c;而是疾病、创伤导致的结果。什么是贫血&#xff1f;红细胞是血液的组成部分&#xff0c;在狗的骨髓中产生。血红蛋白&#xff0c;通常…

undertale人物_【undertale】精美人物图包 (Red篇)

想看到更多的图包 记得点关注&#xff01;有人想要 我就发 简单粗暴 嗯&#xff0c;就这样by WhiteSkyPony注意&#xff01;图包部分来自百度搜索&#xff0c;只为分享&#xff0c;没有版权&#xff0c;若有侵权&#xff0c;那么删除。---------------------------------------…

2 imwrite中文路径_AE是该使用中文版还是英文版?如何中英文版本切换?

想要了解更多后期知识吗&#xff1f;想要获取更多资源吗&#xff1f;置顶影视设计师关于AE是选择英文版还是中文版&#xff0c;想必对于新手来说是一个很头疼的问题吧。选择英文版吧&#xff0c;英语水平摆在这&#xff0c;本来AE就有点难&#xff0c;学习起来实在太不方便了&a…

apache模块载入命令_Apache模块动态加载和静态加载

静态&#xff1a;在使用./configure 编译的时候&#xff0c;如果不指定某个模块为动态&#xff0c;即没有使用&#xff1a;enable-mods-sharedmodule或者enable-moduleshared 这个2个中的一个&#xff0c;那么所有的默认模块为静态。那么何谓静态&#xff1f;其实就是编译的时候…

python程序结构教程第四版答案_Python简单程序结构练习题

1.猜数游戏。在程序中预设一个0~9之间的整数&#xff0c;让用户通过键盘输入所猜数字&#xff0c;如果大于预设的数&#xff0c;显示“遗憾&#xff0c;太大了”&#xff1b;如果小于预设的数&#xff0c;显示“遗憾&#xff0c;太小了”&#xff1b;如此循环&#xff0c;直至猜…

中点坐标公式 矩形_2019年连云港市第16题——矩形、圆、相切、最值

2019年连云港市第16题——矩形、圆、相切、最值2019年连云港市第8题——矩形、折叠、射影定理、外接圆2019南宁第18题——平移、等边三角形、勾股定理2019南宁第12题——圆、相似、将军饮马型最值问题2019孝感第16题——反比例函数、A型相似、三角形的面积2019孝感第10题——正…

电脑壁纸尺寸比例_怎么设置桌面壁纸尺寸比例

很多人都用自己喜欢的图片照片做桌面壁纸&#xff0c;但是自己的照片一般和屏幕分辨率都不匹配&#xff0c;虽然可以选择”平铺&#xff0c;居中&#xff0c;适应“等方式&#xff0c;但有时可能填不满&#xff0c;显示不完整&#xff0c;或者变形&#xff0c;总之不尽人意。下…

php mysql 函数大全_php之mysql函数大全

MySQL5.1中文手册mysql5.1manual.chm_1198091997.chmPHP5中文手册php5manual.chm_11980919971.chm<1>. 连接数据库服务器(databaseserver)的函数(2个)&#xff1a;(1).mysql_connect()格式&#xff1a;int mysql_connect(string [hostname] [:port],string[username],str…