Background#
Due to repository migration and pipeline permission issues, the repository used by the pipeline cannot directly submit PRs on the page. Therefore, when colleagues from the partner need to modify the SaaS backend code for release, the frontend has to perform a code merge locally each time, which is very cumbersome and inefficient. Since the repository and branch pulled each time are fixed, we thought of writing a script in Node to automatically pull the code by calling the interface.
Technology Stack Selection#
Since the current requirement is very simple, which is just basic synchronization, it essentially runs the following command line:
git checkout dev
git pull --no-rebase
git pull bkop dev_databus --no-rebase
git push
Based on this, the following key technologies were mainly adopted:- Node.js: A JavaScript runtime environment that runs on the server side.
- Express: A fast, unopinionated web application framework that supports our API services.
- Child Process: Used to execute shell commands.
- PM2: A process manager for Node applications with built-in load balancing features.
Solution Overview#
Directory Structure and Dependency Installation#
First, create the project directory and initialize a new npm project within it, then install the required dependencies.
mkdir git-auto-pilot && cd $_
npm init -y
npm install express child-process-promise
Here, the child-process-promise
library is used to replace the native exec
function to improve the elegance of error handling and support Promise syntax.
Creating the Automation Script#
Next is the core part of implementing the automation logic—writing a simple Express application and triggering a series of Git operations through an HTTP interface.
Main Functional Modules#
Setting Up the Express Application#
Import the required modules and set up the basic Express application.
// File path: index.js
const express = require('express')
const cp = require('child-process-promise')
const path = require('path')
const app = express()
const directory = 'xxx' // File path
GET Route for Update Operations#
Define the /update
route to perform all Git operations.
app.get('/update', async (req, res) => {
try {
await executeGitCommand('checkout dev')
await executeGitCommand('pull --no-rebase')
await executeGitCommand('pull bkop dev_databus --no-rebase')
await executeGitCommand('push')
const recentCommits = await executeGitCommand('log -n 5 --pretty=format:"%h %s"')
res.send(`
<h1>Update and Push Successful!</h1>
<h2>Most Recent Commits:</h2>
<pre>${recentCommits.stdout}</pre>
`)
} catch(error) {
console.error(`Failed to perform update operations: ${error}`)
res.status(500).send(`<pre>Error: ${error.stderr || error.stack}</pre>`)
}
})
function executeGitCommand(command) {
const fullCommand = `git ${command}`
console.log(`Executing command: ${fullCommand} in ${directory}`)
return cp.exec(fullCommand, {cwd: directory})
}
In this route, the Git operations are executed in order, and exceptions are caught in each command to ensure the robustness of the program.
Starting the Express Service#
The final step is to start the application and listen on a port.
const PORT = process.env.PORT || 30035;
app.listen(PORT, () =>
console.log(`Server is running at http://localhost:${PORT}/`)
);
Using PM2 for Process Management#
To ensure that the application can run stably in the background, use PM2 for management. This way, there is no need to keep the terminal open.
pm2 start index.js --name "git-auto-pilot"
Now, even if the terminal is closed or the machine is restarted, this service will be automatically revived by PM2.
Summary#
With the combination of Node and PM2, many simple and practical automation scripts can be written. Currently, this script cannot handle conflicts, but it is sufficient to solve most of my problems and saves a lot of time on manual code merging.