1 introduction
😈 If you are maintaining multiple applet projects and you are spending a lot of time doing this every day, go to git branch -> Execute compile -> Open applet Developer Tools -> Upload Applet.
🧐 maintains 5 mini programs (two wechat mini programs, two Alipay mini programs, and one Bytedance mini program) at the same time, and I find that I spend a lot of time publishing mini programs every day. To that end, I came up with the idea of building an automated build platform for small programs like Jenkins, handing over the task of releasing small programs to test colleagues (yes, I’m lazy).
It can be deployed to your server in 5 minutes. Click Start if it helps.
2 Go to the project page
- Click the experience
- Account: mp
- Password: 123456
2.1 the login page
2.2 the home page
2.3 Home Page With Remarks
2.4 Release Preview
2.5 Release the Experience version
3 Technical Implementation
The following focuses on the implementation of small program (wechat small program, Alipay small program, bytedance small program) publishing function, other login, preview and other functions can be viewed in my Github project. This function is divided into three parts, namely:
- Download the Github/GitLab project
- Compile the project using child processes
- Upload the compiled code
3.1 First write a configuration table, convenient subsequent extension of other small programs
const ciConfigure = {
${project name}_${applets type}
lzj_wechat: {
// appID
appId: 'wxe10f1d56da44430f'.// The application type can be: miniProgram /miniProgramPlugin /miniGame /miniGamePlugin
type: 'miniProgram'.// There are three types of project download addresses:
// Github address: 'https://github.com:${username, my username is lizijie123}/${repository name, document repository is uni-mp-study}'
// v3 version gitlab address: '${gitlab address}/${user name}/${repository name}/repository/archive.zip'
// ${gitlab/API /v4/projects/${repository id}/repository/archive '
// tips: '${gitlab project}/ API /v4/projects' return ${gitlab project}/ API /v4/projects' return ${gitlab project}/ API /v4/projects' return ${gitlab project}/ API /v4/projects' return ${gitlab project}/ API /v4/projects' return ${gitlab project
storeDownloadPath: 'https://github.com:lizijie123/uni-mp-study'.// for the gitlab project, you need to set the privateToken of gitlab, which can be obtained in the gitlab personal center
privateToken: ' '.// Applets pack build commands
buildCommand: 'npm run build:wx'.// The small program is packaged and built, and the output directory is relative to the root directory
buildProjectChildrenPath: '/dist/build/mp-weixin'.// wechat applet and Alipay applet need asymmetric encryption of the private key, privateKeyPath is the private key file relative to the root directory address, get in the wechat public platform
privateKeyPath: '/server/utils/CI/private/lzj-wechat.key'.// The same as several Settings in the wechat Small program developer tool
setting: {
es7: false.minify: false.autoPrefixWXSS: false,}},lzj_alipay: {
// Below is the alipay small program to complement and improve
},
lzj_toutiao: {
// Let's talk about bytedance}},export default ciConfigure
Copy the code
3.1 Obtaining the Github/GitLab Project
Download git projects using download-git-repo
#To install the download git -- repo
npm i download-git-repo -S
Copy the code
First encapsulates a function to calculate the project address, with the local path where the project is stored
import ciConfigure from './utils/ci-configure'
// Get the project address and local storage address
// @params miniprogramType: Small program type, corresponding to the key value in the configuration file
// @parmas branch: branch name
// @params version: version number
// @return: {projectPath: local path where the project is stored, storePath: project address}
function getStorePathAndProjectPath (miniprogramType, branch, version) {
let storePath = ' '
if (ciConfigure[miniprogramType].storeDownloadPath.includes('github')) {
storePath = `${ciConfigure[miniprogramType].storeDownloadPath}#${branch}`
} else {
storePath = `direct:${ciConfigure[miniprogramType].storeDownloadPath}? private_token=${ciConfigure[miniprogramType].privateToken}`
if (storePath.includes('v4')) {
storePath += `&ref=${branch}`
} else {
storePath += `&sha=${branch}`}}const projectPath = path.join(process.cwd(), `/miniprogram/${miniprogramType}/${version}`)
return {
storePath,
projectPath,
}
}
Copy the code
Then encapsulate a function to download the project
import * as downloadGit from 'download-git-repo'
// Download github/ GitLab project
// @parmas storePath: project address
// @params projectPath: the local path where the project is stored
function download (storePath, projectPath) {
return new Promise((resolve, reject) = > {
downloadGit(storePath, projectPath, null.err= > {
if (err) reject(err)
resolve()
})
})
}
Copy the code
3.2 Compile the project using child processes
Use ShellJS to simplify the operation of the child_process module
#Install shelljs
npm install shelljs -S
Copy the code
Encapsulates a function to execute a shell command
import * as shell from 'shelljs'
// Run the shell command
// @parmas command: shell command to be executed
// @params CWD: directory for executing the shell command
function execPromise (command, cwd) {
return new Promise(resolve= > {
shell.exec(command, {
// If the value is true, a new child process is enabled to execute shell commands. If the value is false, the current process is used to execute shell commands, blocking the node process
async: true.silent: process.env.NODE_ENV === 'development'.stdio: 'ignore',
cwd,
}, (. rest) = >{ resolve(... rest) }) }) }Copy the code
Functions that encapsulate the compiled project, which can be customized for your project
// Download the dependency package and run the compile command
// @params miniprogramType: Small program type, corresponding to the key value in the configuration file
// @params projectPath: the local path where the project is stored
async build (miniprogramType, projectPath) {
// Download the dependency package
await execPromise(`npm install`, projectPath)
await execPromise(`npm install --dev`, projectPath)
// Execute the compile command
await execPromise(ciConfigure[miniprogramType].buildCommand, projectPath)
}
Copy the code
3.3 Upload the compiled code (wechat small program version)
3.3.1 Obtaining the Asymmetric Encryption private key for uploading the code
Log in to applet background -> development -> Development Settings -> applet code upload to generate the secret key (the privateKeyPath field in the configuration file is here)
3.3.2 Continuing to implement functions
Use miniprogram-ci to upload the code
#The installation
npm install miniprogram-ci -S
Copy the code
Encapsulate the code upload function
import * as ci from 'miniprogram-ci'
// Wechat small program upload code
// @params miniprogramType: Small program type, corresponding to the key value in the configuration file
// @params projectPath: the local path where the project is stored
// @params version: version number
// @params projectDesc: description
// @params id: id of the robot
async function upload ({ miniprogramType, projectPath, version, projectDesc = ' ', identification }) {
const project = initProject(projectPath, miniprogramType)
await ci.upload({
project,
version,
desc: projectDesc,
setting: ciConfigure[miniprogramType].setting,
onProgressUpdate: process.env.NODE_ENV === 'development' ? console.log : () = > {},
robot: identification ? identification : null})}// Create a CI Projecr object
// @params projectPath: the local path where the project is stored
// @params miniprogramType: Small program type, corresponding to the key value in the configuration file
function initProject (projectPath, miniprogramType) {
return new ci.Project({
appid: ciConfigure[miniprogramType].appId,
type: ciConfigure[miniprogramType].type,
projectPath: `${projectPath}${ciConfigure[miniprogramType].buildProjectChildrenPath}`.privateKeyPath: path.join(process.cwd(), ciConfigure[miniprogramType].privateKeyPath),
ignores: ['node_modules/**/*'],})}Copy the code
3.4 Use the above encapsulated functions to do a complete process
// Upload the applet
// @params miniprogramType: Small program type, corresponding to the key value in the configuration file
// @params version: version number
// @params branch
// @params projectDesc: description
// @params projectPath: the local path where the project is stored
// @params identification: CI robot identification, for wechat applet
// @params Experience: Whether to set the current version to experience version, alipay small program
async upload ({ miniprogramType, version, branch, projectDesc, identification, experience }) {
// Get the project address and local storage address
const { storePath, projectPath } = getStorePathAndProjectPath(miniprogramType, branch, version)
// Download the project locally
download(storePath, projectPath)
// Build the project
build(miniprogramType, projectPath)
// Upload the experience version
await wechatCi.upload({
miniprogramType,
projectPath,
version,
projectDesc,
identification,
experience,
})
}
Copy the code
4 upload other small programs
4.1 Alipay applet
Use Alipay -dev to upload the code
#The installation
npm install alipay-dev -S
Copy the code
4.1.1 Obtain asymmetric encryption public and private keys for uploading code
#The public and private keys for asymmetric encryption are generated locally
npx alipaydev key create -w
Copy the code
4.1.2 Set the newly generated public key to the secret key of Alipay development tool
Set the development tool secret key -> paste the public key to the development tool public key -> save to get the toolId (toolId)(place the toolId and private key obtained here in the configuration file)
4.1.3 Continue to implement functions
Perfect the configuration file of Alipay applet
const ciConfigure = {
lzj_wechat: { 省略 },
lzj_alipay: {
/ / same as above
appId: '2021002107681948'.// The id of the tool will be generated when the public key of asymmetric encryption is set by alipay appletool
toolId: 'b6465befb0a24cbe9b9cf49b4e3b8893'./ / same as above
storeDownloadPath: 'https://github.com:lizijie123/uni-mp-study'.// For the gitlab project, you need to set the Gitlab privateToken
privateToken: ' './ / same as above
buildCommand: 'npm run build:ap'./ / same as above
buildProjectChildrenPath: '/dist/build/mp-alipay'./ / same as above
privateKeyPath: '/server/utils/CI/private/lzj-alipay.key',},lzj_toutiao: {omit},}Copy the code
Then encapsulate pay treasure small program upload code function
// Upload the experience version
// @params miniprogramType: Small program type, corresponding to the key value in the configuration file
// @params projectPath: the local path where the project is stored
// @params version: version number
// @params Experience: whether to set this version to experience version
async function upload ({ miniprogramType, projectPath, version, experience }) {
initProject(miniprogramType)
const res = await ci.miniUpload({
project: `${projectPath}${ciConfigure[miniprogramType].buildProjectChildrenPath}`.appId: ciConfigure[miniprogramType].appId,
packageVersion: version,
onProgressUpdate: process.env.NODE_ENV === 'development' ? console.log : () = > {},
experience: experience ? experience : false,})if (res.qrCodeUrl) {
return res.qrCodeUrl
}
}
// Create a CI Projecr object
// @params projectPath: the local path where the project is stored
// @params miniprogramType: Small program type, corresponding to the key value in the configuration file
function initProject (projectPath: string, miniprogramType: string) {
return new ci.Project({
appid: ciConfigure[miniprogramType].appId,
type: ciConfigure[miniprogramType].type,
projectPath: `${projectPath}${ciConfigure[miniprogramType].buildProjectChildrenPath}`.privateKeyPath: path.join(process.cwd(), ciConfigure[miniprogramType].privateKeyPath),
ignores: ['node_modules/**/*'],})}Copy the code
4.2 bytedance small program
Improve bytedance applets configuration
const ciConfigure = {
lzj_wechat: { 省略 },
lzj_alipay: { 省略 },
lzj_toutiao: {
// Bytedance applet account (the one you logged in to)
account: ' '.// Bytedance applet password (the one used when logging in)
password: ' './ / same as above
storeDownloadPath: 'https://github.com:lizijie123/uni-mp-study'./ / same as above
privateToken: ' './ / same as above
buildCommand: 'npm run build:tt'./ / same as above
buildProjectChildrenPath: '/dist/build/mp-toutiao',}}Copy the code
Use tt-IDE-CLI to upload the code
#The installation
npm install tt-ide-cli -S
Copy the code
Next, encapsulate bytedance applet upload code function. Note: Bytedance applet can only upload code using the command line
// Upload the experience version
// @params miniprogramType: Small program type, corresponding to the key value in the configuration file
// @params projectPath: the local path where the project is stored
// @params version: version number
// @params projectDesc: description
async upload ({ miniprogramType, projectPath, version, projectDesc }) {
const currentPath = process.cwd()
// Login command
const login = `npx tma login-e '${ciConfigure[miniprogramType].account}' '${ciConfigure[miniprogramType].password}'`
// Upload the command
const up = `npx tma upload -v '${version}' -c '${projectDesc ? projectDesc : 'No description yet'}' ${projectPath}${ciConfigure[miniprogramType].buildProjectChildrenPath}`
await execPromise(login, currentPath)
await execPromise(up, currentPath)
}
Copy the code
5 communicate
The project has been running in a build environment for some time now, and no longer need to be called in the middle of the work to release a small program.