The company uses Bugzilla to manage the product bug, recently made a thing with node. js, it is convenient to be able to import the relevant information of the Bug into Excel table, so as to follow the management analysis.
Paste the code directly, write the comments. Reprint please indicate the source.
var request = require ("request") var Cheerio = require ("Cheerio"); var Excel = require (' Exceljs '); var colors = require ("Colo var program = require ("Commander"), var Readlinesync = require (' Readline-sync '); var Agent = require (' agentkeepalive var ProgressBar = require (' progress '); var fs = require (' FS ');//need to use these modules
var puterror = Console.log;global.console.error = function (Error) {Puterror (colors.red ("[ERROR]:" + error);} Just for the output error message to be more visible and unified
Program.on ('--help ', function () {console.log (' examples:\n '); Console.log (' node App.js-u '/http: "-P Name ');})
The Commander module automatically has helpful information and feels that adding an example will be more clear program.option ('-U,--url ', ' URL of bug list to generate. '). Option ('-S,--specifyname ', ' Specify string of file name '). Parse (PROCESS.ARGV);//on and option to read in the command arguments before parse
var fileName = "buglist-" + (new Date ()). toLocaleDateString () + (program.specifyname? "-" +program.specifyname: "");//-s parameter in order to save the file better distinguish, not necessary
var url = "", if (!program.url) {var count = 0;while (url = = "") {if (++count > 3) {program.outputhelp (); Process.exit (1);} url = readlinesync.question (' Please input the URL of the bug list: '). Trim (). Replace (/^ "(. *)" $/g, "$");}} -U parameter required, if three times blank to print help information and exit else {URL = program.url;} url = decodeuricomponent (URL), url = encodeURI (URL),//url address conversion, such as copying with Chinese address directly from the browser will be an error
var urlindex = Url.indexof ("/bugzilla3/"), if (urlindex! =-1) {var root = Url.slice (0, urlindex+11);//company Bugzilla placed in this directory, the amount Make a judgment}else{var root = Url.replace (/^ (https?:\ /\/)? [^\/]*\/]. */ig, "$"); Take the domain name root = (/^http:\/\//ig.test (root) Root: "/http" +root); If there is no http://, add it}var bugurl = root + "show_bug.cgi?ctype=xml&id="; The ID of each bug plus this address, is to display the bug information, in the XML document display, good read information Agent = (Root.tolowercase (). IndexOf ("https://")! =-1)? Agent.HttpsAgent:Agent; HTTPS will be used to support the HTTPS address pool, because bugzilla with a long connection, no address pool error var keepaliveagent = new Agent ({maxsockets:100,maxfreesockets:10, timeout:60000,freesocketkeepalivetimeout:30000});
Address pool configuration var option = {agent:keepaliveagent, headers: {"user-agent": "NodeJS", Host:url.replace (/^ (https?:\ /\/)? ([^\/]*) \/). */g, "$ $")},url:url};
Configuration of Request
Send the request with the bottom-written getfunc, return the Promise object Getfunc (option, function (URL, $) {var bugs = new Array (); var td = $ ("Table.bz_buglist TR t D.bz_id_column a "); Td.each (function (key) {Bugs.push (Td.eq (key). text ());}) if (Bugs.length > 0) {//Get the ID list of the bug and initialize the progress bar Console.log ("\ntotal Number of Bugs:" + bugs.length); Global.bar = new Progre Ssbar (' Getting Bugs [: Bar]:p ercent | ETA:: ETAs | : Current/:total ', {complete: "-", Incomplete: ", Width:25,clear:false, Total:bugs.length,});} else {console.error ("No bugs can be found."); Process.exit (1);} return bugs; Bugs This value is passed through the Resolve function to the function inside the then}). Then (function (bugs) {var-done = 0; The ID array is retrieved with a map for each bug, and each request returns a Promise object, which is the promise object that makes up the item in the map return array as a promise.all parameter when
After all the Promise objects are successful, the Promise objects returned by Promise.all are all resolve.
Return Promise.all (Bugs.map (function (eachbug, index) {option.url = Bugurl + Eachbug;var promisegetone = getfunc (option, F Neinfo.id = $ ("bug_id"). Text (); oneinfo.summary = $ ("Short_desc"). Text (); oneinfo.reporter = $ ("reporter"). text (); O Neinfo.product = $ ("Product"). text (); oneinfo.component = $ ("component"). Text (); oneinfo.version = $ ("version"). Text () ; oneinfo.status = $ ("Bug_status"). Text (); oneinfo.priority = $ ("priority"). Text (); oneinfo.security = $ ("bug_security" ). text (); oneinfo.assign = $ ("assigned_to"). Text (); oneinfo.comment = new Array (); var comments = $ ("Long_desc"); The first comment is treated as a bug description Comments.each (function (key) {var who = Comments.eq (key). Find (' who '). text (); var when = Comments.eq (key). Find ("Bug_when"). Text (), when = When.replace (/([^\s]+) \s.*$/g, "$"), var desc = 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});}) return oneinfo;}) Promisegetone.then (function () {done ++;bar.tick ();//Update progress bar if (done = = Bugs.length) {console.log ("\ n");}}) return promisegetone;})}). Then (function (buglists) {var workbook = new Excel.Workbook ();//New Excel document var productnum = 0;for (var i in buglists) { Buginfo = Buglists[i]; var sheet = workbook.getworksheet (buginfo.product); Depending on the project, if there is no worksheet, create a new if (sheet = = = undefined) {sheet = Workbook.addworksheet (buginfo.product); Productnum + +; try {sheet.getcolumn ("id");//If there is no header row, add the header row} catch (Error) {sheet.columns = [ {header: ' Bug ID ', key: ' ID '}, {header: ' Summary ', key: ' Summary ', width:35}, {header: ' Bug Det Ail ', key: ' Detail ', width:75}, {header: ' Priority ', key: ' Priority ', Width:8}, {header: ' Version ' , key: ' Version ', width:15}, {header: ' Status ', key: ' Status ', WIdth:15}, {header: ' Component ', key: ' Component ', width:15}, {header: ' Comments ', key: ' Comment ', Widt H:60}, {header: ' Assign to ', Key: ' Assign ', width:20}, {header: ' Reporter ', key: ' Reporter ', width:20 }, ]; }var comment = ""; for (Var j in Buginfo.comment) {comment + = buginfo.comment[j].who + "(" + Buginfo.comment[j].when + "): \ r \ n "; Comment + = Buginfo.comment[j].desc.replace (/\n/gm," \ r \ n ") +" \ r \ n "; Comment + ="------------------------------- ------------------------\ r \ n "}sheet.addrow ({//each bug adds one row ID: {text:bugInfo.id, hyperlink:buginfo.url},summary: Buginfo.summary,detail:buginfo.detail.replace (/\n/gm, "\ r \ n"), priority:buginfo.priority,version:buginfo.version , Status:buginfo.status,component:buginfo.component,comment:comment,assign:buginfo.assign,reporter: Buginfo.reporter,}); Sheet.eachrow (function (Row, rowNum) {//Set alignment etc Row.eachcell (function (Cell, cellnum) {if (RowNum = = 1) cell.align ment = {vertical: ' Middle ', Horizontal: ' Center ', size:25, wraptext:true} else Cell.alignment = {vertical: ' top ', Horizontal: ' Left ', Wraptext:true}}})} FileName = ((Productnum > 1)? "": buginfo.product+ "-") + FileName + ". xlsx"; var files = Fs.readdirsync ("./"); var postfix = 1; while (Files.indexof (fileName)! =-1) {//If the file has the same name, add (1) to the following number until there is no duplicate name, otherwise it will overwrite the name file filename = filename.replace (\ (\ (\ d+\))? \.xlsx$/g, "(" + (postfix++) + "). xlsx"); if (Postfix >) {console.warn ("It may occur somethins wrong."); Break }}return Workbook.xlsx.writeFile (FileName);}). Then (function () {Console.log ("Generate xlsx file successfully. File name is "+ Colors.cyan (fileName)); End, tells the user the generated file name}). catch (function (err) {Console.error (err);p rocess.exit (1);}) function Getfunc (getOption, Parsefunc) {return new Promise (function (resolve, reject) {Request.get (getOption, function ( Error, response, body) {if (!error && response.statuscode = = 200){var $ = cheerio.load (body); var result = Parsefunc (Getoption.url, $); resolve (result);} else {reject (error);}})})}
Paste two test address:
1. http://chinajr.com/buglist.cgi?product=%e5%8d%b3%e5%ae%89%e5%88%86%e5%8d%95&query_format=advanced& resolution=---
2. https://bugzilla.mozilla.org/buglist.cgi?order=Importance&resolution=---&query_format=advanced& Product=add-on%20sdk
The resulting document:
Use node. js to import the bug list on bugzilla into an Excel table