I've written a CLI tool that uses node. js to import a bug list from Bugzilla to an Excel table, but with a few points in mind, you always feel like you need to do something else.
- The interface was rough, and I was using it in Git bash under Vscode, and it looked good. If it is used under CMD, you can't bear to look straight.
- Need to start with a command, URL address also need to add double quotation marks, the experience is not good.
- Need to install NODEJS environment yourself
So I made this tool into an online version, just copy the URL, click Start, fool operation, multi-person use.
1 varExpress = require (' Express ');2 varBodyparser = require (' Body-parser '));3 varChildprocess = require (' child_process '));4 varFS = require (' FS ');5 6Const MAXTASK = 10;7Const PORT = 1024;8 9 varApp =Express ();Ten OneApp.use (express.static (' public '))); A -App.get ("/",function(req, res) { -Console.log ("[New Visitors]:" + req.ip.replace (/[^\d\.) /g, "")); theRes.sendfile ("./public/index.html"); -});
Load the module first, define the port and the maximum number of simultaneous runs (the server that downloads the bug can hold up, Bugzilla server can't handle it, and the task will slow down the normal use of a colleague).
Define an instance of express, set the static file directory.
Set the home page.
1 var New Array (); 2 App.use (Bodyparser.json ());
Define the task list because the API's data format is JSON, so add a middleware parsing data
/* tasks = [{ fingerprint:12345678, starttime:123456, savename: ' test.xlsx ' child:child_process , status: [Error|running|done], reason: "", total:245, done:34}]* /
This is the data structure of the task list
App.post ('/start ',function(req, res) {varFROMIP = Req.ip.replace (/[^\d\.) /g, ""); if(Getrunningnum () > (MaxTask-1) {Res.json ({result:"Fail", Reason: "Maxtask", maxtask:maxtask}); return; } varURL =Req.body.taskURL; varFingerprint =Req.body.fingerprint; varindex =Gettaskindex (fingerprint); if(Index! =-1) { if(Tasks[index].status = = "Running"{Res.json ({result:"Fail", Reason: "Running" }); return; } Else{tasks.splice (index,1); Deleteexcel (fingerprint); } } varChild = Childprocess.fork ("./transport.js", [url, fingerprint, FROMIP]); Console.log ("[New Task]: from IP" +fromip) Tasks.push ({fingerprint:fingerprint, child:child, Status:"Running", StartTime: (NewDate ()). GetTime ()}); Res.json ({result:"Success", Reason: "" }); Child.on (' Message ',function(msg) {varID =Gettaskindex (Msg.fingerprint); if(id! =-1) {Tasks[id].status=Msg.status; Tasks[id].reason=Msg.reason; Tasks[id].total=Msg.total; Tasks[id].done=Msg.done; Tasks[id].savename=Msg.savename; } });});
Receive a task request API. Determine whether the maximum number of tasks is reached, and then determine if the task list already has a task in the current browser based on fingerprint. If there is, and is running, an error is returned. If the task is complete, delete it from the task list.
Start a child process to download the bug information and add the task to the Task list. Listens for messages from child processes, updating the status of the task list in real time.
1 function Gettaskindex (fingerprint) {2 for (var in tasks) {3 if (Tasks[i].fingerprint = = fingerprint) 4 return i; 5 }6 return -1; 7 }
Determine if a task is in the task list according to fingerprint
function (req, res) { var fingerprint = req.query.fingerprint; var i = gettaskindex (fingerprint); if (I! =-1) { Res.json ({status:tasks[i].status, Reason:tasks[i].reason, Total:tasks[i].total, Done:tasks[i]. Done}); Else { "error", Reason: "Noprocess" });} )
Get the status API for the current task
function (req, res) { Res.json ({running:getrunningnum (), max:maxtask});})
function Getrunningnum () { var num = 0; for (var in tasks) { if (tasks[i].status = = "Running") num ++; } return num;}
Get the total number of tasks API
App.get ("/download",function(req, res) {varFingerprint =Req.query.fingerprint; varFiles = Fs.readdirsync (' Excel '); varSavename = "Result.xlsx"; varindex =Gettaskindex (fingerprint); if(Index! =-1) Savename=Tasks[index].savename; if(Files.indexof (fingerprint + ". xlsx")! =-1) {Res.type ("Application/binary"); Res.download ("excel/" + fingerprint + ". xlsx", Savename); } Else{Res.json ({status:"Fail" }); }})
Download the Excel Results API
var function () { console.log (' Bug to Excel Web site start at ' + (new Date). toLocaleString ());});
Start the server
SetInterval (Cleartask, 1 * 60 * 60);functionCleartask () {varCurrent = (NewDate ()). GetTime (); for(varIinchtasks) { if(parseint (Current-tasks[i].starttime)/$) > 1 * 60 * 60) {deleteexcel (tasks[i].fingerprint); Tasks.splice (i,1); } }}functionDeleteexcel (fingerprint) {varFile = "excel/" + fingerprint + ". xlsx"; Fs.exists (file,function(exists) {if(exists) {fs.unlink (file,function(err) {if(Err) {Console.log ("Delete" + file + "failed."); } }); } })}
Every one hours to determine whether the task is out of date, and indeed expires, delete the Excel file and move out of the task list.
The server that provides the static files and APIs is the above. Next look at the child process is if you go to download the bug information and generate Excel table. There is also a status update to the parent process.
The code to download the bug information is actually similar to the previous one in the CLI. But one of the most important changes is that the CLI tool is a bug to fetch information, so the burden on the server, when the bug has hundreds of, and the server connection often error.
Therefore, in the online version of this change to every 200 bugs to send a request. This greatly reduces the number of connections, but also makes a lot faster. Makes it possible to support multiple tasks at the same time.
Please refer to the CLI for most of the code. This is only the section that downloads the bug information and updates the status of the task.
varSplitlength = 200;. Then (function(bugs) {varSplitbugs =NewArray (); Do{Splitbugs.push (Bugs.splice (0, splitlength)); } while(Bugs.length > 0) varDone = 0; returnPromise.all (Splitbugs.map (function(Eachgroup, index) {varSplitpromise =Getlongformat (Eachgroup); Splitpromise.then (function() { done+=eachgroup.length; Msg.done=Done ; Process.send (msg); }) returnsplitpromise; }))})
After getting the array of bug IDs, divide the array every 200
functionGetlongformat (bugs) {varPostData = Bugs.join ("&") + "&ctype=xml&excludefield=attachmentdata"; returnPostfunc (Bugurl, PostData,function(URL, data) {var$ =cheerio.load (data); varXmllists = $ ("Bugzilla bug"); varBuglists =NewArray (); Xmllists.each (function(key) {varOnebug =Xmllists.eq (key); varOneinfo =NewObject (); Oneinfo.id= Onebug.children ("bug_id"). text (); Oneinfo.url= Bugurl + "? id=" +oneinfo.id; Oneinfo.summary= Onebug.children ("Short_desc"). text (); Oneinfo.reporter= Onebug.children ("reporter"). text (); Oneinfo.product= Onebug.children ("Product"). text (); Oneinfo.component= Onebug.children ("Component"). text (); Oneinfo.version= Onebug.children ("Version"). text (); Oneinfo.status= Onebug.children ("Bug_status"). text (); Oneinfo.priority= Onebug.children ("Priority"). text (); Oneinfo.security= Onebug.children ("bug_security"). text (); Oneinfo.assign= Onebug.children ("assigned_to"). text (); Oneinfo.comment=NewArray (); varComments = Onebug.children ("Long_desc"); Comments.each (function(key) {varwho = Comments.eq (key). Find (the "who"). text (); varwhen = Comments.eq (key). Find ("Bug_when"). text (); when= When.replace (/([^\s]+) \s.*$/g, "$"); vardesc = Comments.eq (key). Find ("TheText"). text (); if(key = = 0 && who = =oneinfo.reporter) {oneinfo.detail=desc; return true; } oneInfo.comment.push ({' Who ': Who, ' when ': when, ' desc ': desc}); }) Buglists.push (Oneinfo); }) Msg.done=buglists.length; Process.send (msg); returnbuglists; })}
The 200 bug IDs are appended to the POST request data, and the resulting data is the XML format for all bugs, parsing each XML to get each bug information. Please refer to the CLI for writing to the Excel section
Get the Excel table
[Node tool] uses node. js to import the list of bugs on Bugzilla to one of the online versions of the Excel table (server side)