From 2cfaaad2dd8bb45a4500e429c5e81c5387b30e55 Mon Sep 17 00:00:00 2001 From: Greg Gibeling Date: Fri, 10 May 2024 13:14:19 -0700 Subject: [PATCH 1/2] G2-1564 Create basic planning tool - query jira & log results --- .../g2forge/project/plan/create/Create.java | 3 +- .../com/g2forge/project/plan/Download.java | 64 +++++++++++++++++++ .../java/com/g2forge/project/plan/Plan.java | 1 + 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 pj-plan/src/main/java/com/g2forge/project/plan/Download.java diff --git a/pj-create/src/main/java/com/g2forge/project/plan/create/Create.java b/pj-create/src/main/java/com/g2forge/project/plan/create/Create.java index 98c406e..df85940 100644 --- a/pj-create/src/main/java/com/g2forge/project/plan/create/Create.java +++ b/pj-create/src/main/java/com/g2forge/project/plan/create/Create.java @@ -30,7 +30,6 @@ import com.atlassian.jira.rest.client.api.domain.input.IssueInputBuilder; import com.atlassian.jira.rest.client.api.domain.input.LinkIssuesInput; import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -296,6 +295,6 @@ public IExit invoke(CommandInvocation invocation) thro protected CreateConfig load(final InputStream stream) throws IOException, JsonParseException, JsonMappingException { final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - return mapper.readValue(stream, new TypeReference() {}); + return mapper.readValue(stream, CreateConfig.class); } } diff --git a/pj-plan/src/main/java/com/g2forge/project/plan/Download.java b/pj-plan/src/main/java/com/g2forge/project/plan/Download.java new file mode 100644 index 0000000..c0a5012 --- /dev/null +++ b/pj-plan/src/main/java/com/g2forge/project/plan/Download.java @@ -0,0 +1,64 @@ +package com.g2forge.project.plan; + +import java.io.InputStream; +import java.io.PrintStream; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.slf4j.event.Level; + +import com.atlassian.jira.rest.client.api.domain.Issue; +import com.atlassian.jira.rest.client.api.domain.SearchResult; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.g2forge.alexandria.command.command.IStandardCommand; +import com.g2forge.alexandria.command.exit.IExit; +import com.g2forge.alexandria.command.invocation.CommandInvocation; +import com.g2forge.alexandria.log.HLog; +import com.g2forge.gearbox.jira.ExtendedJiraRestClient; +import com.g2forge.gearbox.jira.JIRAServer; + +import lombok.Builder; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.jackson.Jacksonized; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class Download implements IStandardCommand { + @Data + @Builder(toBuilder = true) + @RequiredArgsConstructor + @Jacksonized + public static class Input { + protected final String query; + } + + public static void main(String[] args) throws Throwable { + IStandardCommand.main(args, new Download()); + } + + @Override + public IExit invoke(CommandInvocation invocation) throws Throwable { + HLog.getLogControl().setLogLevel(Level.INFO); + if (invocation.getArguments().size() != 1) throw new IllegalArgumentException(); + final Path inputPath = Paths.get(invocation.getArguments().get(0)); + final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + final Input input = mapper.readValue(inputPath.toFile(), Input.class); + + try (final ExtendedJiraRestClient client = JIRAServer.load().connect(true)) { + final int max = 500; + int base = 0; + while (true) { + final SearchResult searchResult = client.getSearchClient().searchJql(input.getQuery(), max, base, null).get(); + for (Issue issue : searchResult.getIssues()) { + log.info("Issue: {} - {}", issue.getKey(), issue.getSummary()); + } + if ((base + max) >= searchResult.getTotal()) break; + else base += max; + } + } + + return IStandardCommand.SUCCESS; + } +} diff --git a/pj-plan/src/main/java/com/g2forge/project/plan/Plan.java b/pj-plan/src/main/java/com/g2forge/project/plan/Plan.java index 724787f..b8f8b8b 100644 --- a/pj-plan/src/main/java/com/g2forge/project/plan/Plan.java +++ b/pj-plan/src/main/java/com/g2forge/project/plan/Plan.java @@ -6,6 +6,7 @@ public class Plan implements IStructuredCommand { public static void main(String[] args) throws Throwable { final DispatchCommand.ManualBuilder builder = new DispatchCommand.ManualBuilder(); + builder.command(new Download(), "download"); builder.main(args); } } From 6f44539f960dce250cfe6cda8a8b8303fd0111f1 Mon Sep 17 00:00:00 2001 From: Greg Gibeling Date: Fri, 10 May 2024 13:25:43 -0700 Subject: [PATCH 2/2] G2-1564 Save results to excel spreadsheet --- pj-plan/.gitignore | 2 + pj-plan/pom.xml | 15 ++++++ .../com/g2forge/project/plan/Download.java | 48 +++++++++++++++---- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/pj-plan/.gitignore b/pj-plan/.gitignore index 5572039..bf51015 100644 --- a/pj-plan/.gitignore +++ b/pj-plan/.gitignore @@ -5,3 +5,5 @@ /bulldozer-temp.json /bulldozer-state.json /.factorypath +/Download.yaml +/Download.xlsx diff --git a/pj-plan/pom.xml b/pj-plan/pom.xml index c247714..701393f 100644 --- a/pj-plan/pom.xml +++ b/pj-plan/pom.xml @@ -12,6 +12,10 @@ 0.0.1-SNAPSHOT ../pj-project/pom.xml + + + 5.2.5 + @@ -24,5 +28,16 @@ gb-jira ${gearbox.version} + + + org.apache.poi + poi + ${poi.version} + + + org.apache.poi + poi-ooxml + ${poi.version} + diff --git a/pj-plan/src/main/java/com/g2forge/project/plan/Download.java b/pj-plan/src/main/java/com/g2forge/project/plan/Download.java index c0a5012..3909d28 100644 --- a/pj-plan/src/main/java/com/g2forge/project/plan/Download.java +++ b/pj-plan/src/main/java/com/g2forge/project/plan/Download.java @@ -1,10 +1,16 @@ package com.g2forge.project.plan; import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintStream; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.event.Level; import com.atlassian.jira.rest.client.api.domain.Issue; @@ -32,12 +38,19 @@ public class Download implements IStandardCommand { @Jacksonized public static class Input { protected final String query; + + protected final Path output; } public static void main(String[] args) throws Throwable { IStandardCommand.main(args, new Download()); } + public static Path withBase(Path base, Path path) { + if (path.isAbsolute() || (base == null)) return path; + return base.resolve(path); + } + @Override public IExit invoke(CommandInvocation invocation) throws Throwable { HLog.getLogControl().setLogLevel(Level.INFO); @@ -46,16 +59,33 @@ public IExit invoke(CommandInvocation invocation) thro final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); final Input input = mapper.readValue(inputPath.toFile(), Input.class); - try (final ExtendedJiraRestClient client = JIRAServer.load().connect(true)) { - final int max = 500; - int base = 0; - while (true) { - final SearchResult searchResult = client.getSearchClient().searchJql(input.getQuery(), max, base, null).get(); - for (Issue issue : searchResult.getIssues()) { - log.info("Issue: {} - {}", issue.getKey(), issue.getSummary()); + try (final Workbook workbook = new XSSFWorkbook()) { + final Sheet sheet = workbook.createSheet("Issues"); + { + final Row header = sheet.createRow(0); + header.createCell(0).setCellValue("Key"); + header.createCell(1).setCellValue("Summary"); + } + + try (final ExtendedJiraRestClient client = JIRAServer.load().connect(true)) { + final int max = 500; + int base = 0, rowNum = 1; + while (true) { + final SearchResult searchResult = client.getSearchClient().searchJql(input.getQuery(), max, base, null).get(); + log.info("Got issues {} to {} of {}", base, base + Math.min(searchResult.getMaxResults(), searchResult.getTotal() - base), searchResult.getTotal()); + + for (Issue issue : searchResult.getIssues()) { + final Row row = sheet.createRow(rowNum++); + row.createCell(0).setCellValue(issue.getKey()); + row.createCell(1).setCellValue(issue.getSummary()); + } + if ((base + max) >= searchResult.getTotal()) break; + else base += max; } - if ((base + max) >= searchResult.getTotal()) break; - else base += max; + } + + try (final OutputStream outputStream = Files.newOutputStream(withBase(inputPath.getParent(), input.getOutput()))) { + workbook.write(outputStream); } }