View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.changes.github;
20  
21  import javax.inject.Inject;
22  
23  import java.net.MalformedURLException;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Locale;
27  import java.util.Map;
28  import java.util.ResourceBundle;
29  
30  import org.apache.maven.plugins.annotations.Mojo;
31  import org.apache.maven.plugins.annotations.Parameter;
32  import org.apache.maven.plugins.changes.AbstractChangesReport;
33  import org.apache.maven.plugins.changes.ProjectUtils;
34  import org.apache.maven.plugins.changes.issues.Issue;
35  import org.apache.maven.plugins.changes.issues.IssueUtils;
36  import org.apache.maven.plugins.changes.issues.IssuesReportHelper;
37  import org.apache.maven.plugins.changes.issues.IssuesReportRenderer;
38  import org.apache.maven.reporting.MavenReportException;
39  import org.apache.maven.settings.Settings;
40  import org.apache.maven.settings.crypto.SettingsDecrypter;
41  
42  /**
43   * Goal which downloads issues from GitHub and generates a report.
44   *
45   * @author Bryan Baugher
46   * @since 2.8
47   */
48  @Mojo(name = "github-changes", threadSafe = true)
49  public class GitHubChangesReport extends AbstractChangesReport {
50  
51      /**
52       * Valid Github columns.
53       */
54      private static final Map<String, Integer> GITHUB_COLUMNS = new HashMap<>();
55  
56      static {
57          GITHUB_COLUMNS.put("Assignee", IssuesReportHelper.COLUMN_ASSIGNEE);
58          GITHUB_COLUMNS.put("Created", IssuesReportHelper.COLUMN_CREATED);
59          GITHUB_COLUMNS.put("Fix Version", IssuesReportHelper.COLUMN_FIX_VERSION);
60          GITHUB_COLUMNS.put("Id", IssuesReportHelper.COLUMN_ID);
61          GITHUB_COLUMNS.put("Reporter", IssuesReportHelper.COLUMN_REPORTER);
62          GITHUB_COLUMNS.put("Status", IssuesReportHelper.COLUMN_STATUS);
63          GITHUB_COLUMNS.put("Summary", IssuesReportHelper.COLUMN_SUMMARY);
64          GITHUB_COLUMNS.put("Type", IssuesReportHelper.COLUMN_TYPE);
65          GITHUB_COLUMNS.put("Updated", IssuesReportHelper.COLUMN_UPDATED);
66      }
67  
68      /**
69       * Sets the column names that you want to show in the report. The columns will appear in the report in the same
70       * order as you specify them here. Multiple values can be separated by commas.
71       * <p>
72       * Valid columns are: <code>Assignee</code>, <code>Created</code>, <code>Fix Version</code>, <code>Id</code>,
73       * <code>Reporter</code>, <code>Status</code>, <code>Summary</code>, <code>Type</code> and <code>Updated</code>.
74       * </p>
75       */
76      @Parameter(defaultValue = "Id,Type,Summary,Assignee,Reporter,Status,Created,Updated,Fix Version")
77      private String columnNames;
78  
79      /**
80       * The settings.xml server id to be used to authenticate into GitHub Api.
81       * <br>
82       * Since 3.x - only password item is used as authentication token with {@code Authorization: Bearer YOUR-TOKEN}
83       * <a href="https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api">Authenticating to the REST API</a>
84       *
85       * @since 2.12
86       */
87      @Parameter(defaultValue = "github")
88      private String githubAPIServerId;
89  
90      /**
91       * Settings XML configuration.
92       */
93      @Parameter(defaultValue = "${settings}", readonly = true, required = true)
94      private Settings settings;
95  
96      /**
97       * Boolean which says if we should include open issues in the report.
98       */
99      @Parameter(defaultValue = "true")
100     private boolean includeOpenIssues;
101 
102     /**
103      * Boolean which says if we should include only issues with milestones.
104      */
105     @Parameter(defaultValue = "true")
106     private boolean onlyMilestoneIssues;
107 
108     /**
109      * If you only want to show issues for the current version in the report. The current version being used is
110      * <code>${project.version}</code> minus any "-SNAPSHOT" suffix.
111      */
112     @Parameter(defaultValue = "false")
113     private boolean onlyCurrentVersion;
114 
115     /**
116      * Component used to decrypt server information.
117      */
118     private SettingsDecrypter settingsDecrypter;
119 
120     @Inject
121     public GitHubChangesReport(SettingsDecrypter settingsDecrypter) {
122         this.settingsDecrypter = settingsDecrypter;
123     }
124 
125     /* --------------------------------------------------------------------- */
126     /* Public methods */
127     /* --------------------------------------------------------------------- */
128 
129     @Override
130     @Deprecated
131     public String getOutputName() {
132         return "github-changes";
133     }
134 
135     @Override
136     public String getName(Locale locale) {
137         return getBundle(locale).getString("report.issues.name");
138     }
139 
140     @Override
141     public String getDescription(Locale locale) {
142         return getBundle(locale).getString("report.issues.description");
143     }
144 
145     /**
146      * @see org.apache.maven.reporting.AbstractMavenReport#canGenerateReport()
147      */
148     @Override
149     public boolean canGenerateReport() {
150         // Run only at the execution root
151         if (runOnlyAtExecutionRoot && !isThisTheExecutionRoot()) {
152             getLog().info("Skipping the GitHub Report in this project because it's not the Execution Root");
153             return false;
154         }
155         String message = ProjectUtils.validateIssueManagement(project, "GitHub", "GitHub Report");
156         if (message != null) {
157             getLog().warn(message);
158         }
159         return message == null;
160     }
161 
162     @Override
163     protected void executeReport(Locale locale) throws MavenReportException {
164 
165         // Validate parameters
166         List<Integer> columnIds = IssuesReportHelper.getColumnIds(columnNames, GITHUB_COLUMNS);
167         if (columnIds.isEmpty()) {
168             // This can happen if the user has configured column names and they are all invalid
169             throw new MavenReportException(
170                     "maven-changes-plugin: None of the configured columnNames '" + columnNames + "' are valid.");
171         }
172 
173         try {
174             // Download issues
175             GitHubDownloader issueDownloader = new GitHubDownloader(project, includeOpenIssues, onlyMilestoneIssues);
176 
177             issueDownloader.configureAuthentication(settingsDecrypter, githubAPIServerId, settings, getLog());
178 
179             List<Issue> issueList = issueDownloader.getIssueList();
180 
181             if (onlyCurrentVersion) {
182                 issueList = IssueUtils.getIssuesForVersion(issueList, project.getVersion());
183                 getLog().info("The GitHub Report will contain issues only for the current version.");
184             }
185 
186             // Generate the report
187             IssuesReportRenderer report = new IssuesReportRenderer(getSink(), getBundle(locale), columnIds, issueList);
188             report.render();
189 
190         } catch (MalformedURLException e) {
191             // Rethrow this error so that the build fails
192             throw new MavenReportException("The Github URL is incorrect - " + e.getMessage());
193         } catch (Exception e) {
194             throw new MavenReportException(e.getMessage(), e);
195         }
196     }
197 
198     /* --------------------------------------------------------------------- */
199     /* Private methods */
200     /* --------------------------------------------------------------------- */
201 
202     private ResourceBundle getBundle(Locale locale) {
203         return ResourceBundle.getBundle("github-report", locale, this.getClass().getClassLoader());
204     }
205 }