(* Poll Bugzilla, find new tasks, and add them to the database. * This runs from a cron job. *) open CalendarLib open Unix open Printf let quote = Filename.quote let products = [ "Red Hat Enterprise Linux 6", Printer.Date.from_string "2016-11-14"; "Red Hat Enterprise Linux 7", Printer.Date.from_string "2017-04-03"; ] let assigned_to = "rjones@redhat.com" let states = ["NEW";"ASSIGNED";"ON_DEV";"POST";"MODIFIED"] let () = let rex = Pcre.regexp "^(\\d+) (\\S+) (.*)$" in let errors = ref 0 in let dbh = PGOCaml.connect ~database:"todo" () in List.iter ( fun (product, my_deadline) -> (* Query bugzilla. *) let lines = let cmd = sprintf "bugzilla query -p %s -a %s -t %s --outputformat='%%{bug_id} %%{component} %%{short_desc}'" (quote product) (quote assigned_to) (quote (String.concat "," states)) in let chan = open_process_in cmd in let lines = ref [] in (try while true do lines := input_line chan :: !lines done with End_of_file -> ()); let stat = close_process_in chan in (match stat with | WEXITED 0 -> () | WEXITED i -> eprintf "error: bugzilla command: exited with error %d\n%!" i; incr errors | WSIGNALED i -> eprintf "error: bugzilla command: killed by signal %d\n%!" i; incr errors | WSTOPPED i -> eprintf "error: bugzilla command: stopped by signal %d\n%!" i; incr errors ); List.rev !lines in if lines <> [] then ( (* The output is . * The component is turned into a tag. *) List.iter ( fun line -> try let subs = Pcre.exec ~rex line in let bugid = Int32.of_string (Pcre.get_substring subs 1) in let component = Pcre.get_substring subs 2 in let description = Pcre.get_substring subs 3 in PGOCaml.begin_work dbh; (* If the bug doesn't exist in the tasks table, add it. *) let rows = PGSQL(dbh) "select id from tasks where rhbz = $bugid" in let taskid = match rows with | [id] -> id | [] -> printf "new task: RHBZ#%ld %s %s\n%!" bugid component description; PGSQL(dbh) "insert into tasks (description, rhbz) values ($description, $bugid)"; PGOCaml.serial4 dbh "tasks_id_seq" | _ -> assert false in (* If the component doesn't exist as a tag, create it. *) let rows = PGSQL(dbh) "select id from tags where name = $component" in let tagid = match rows with | [id] -> id | [] -> printf "new tag: %s\n%!" component; PGSQL(dbh) "insert into tags (name, colour) values ($component, 'blue')"; PGOCaml.serial4 dbh "tags_id_seq" | _ -> assert false in (* If the bug is not tagged with the component, tag it. * If the bug changes component, this creates a second * tag, which is intentional. *) let rows = PGSQL(dbh) "select 1 from tags_tasks, tasks, tags where tags_tasks.taskid = tasks.id and tags_tasks.tagid = tags.id and tasks.rhbz = $bugid and tags.name = $component" in if rows <> [Some 1_l] then PGSQL(dbh) "insert into tags_tasks (tagid, taskid) values ($tagid, $taskid)"; (* Add the bug to the todo table with the appropriate * deadline. *) let rows = PGSQL(dbh) "select 1 from todo where taskid = $taskid" in if rows <> [Some 1_l] then PGSQL(dbh) "insert into todo (taskid, deadline) values ($taskid, $my_deadline::date)"; PGOCaml.commit dbh with Not_found -> eprintf "error: line did not match regular expression: %s\n%!" line; incr errors ) lines ) ) products; if !errors > 0 then exit 1